misc: move exit status into trap handler
[xfstests-dev.git] / tests / generic / 563
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2019 Red Hat, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. 563
6 #
7 # This test verifies that cgroup aware writeback properly accounts I/Os in
8 # various scenarios. We perform reads/writes from different combinations of
9 # cgroups and verify that pages are accounted against the group that brought
10 # them into cache.
11 #
12
13 seq=`basename $0`
14 seqres=$RESULT_DIR/$seq
15 echo "QA output created by $seq"
16
17 here=`pwd`
18 tmp=/tmp/$$
19 status=1        # failure is the default!
20 trap "_cleanup; exit \$status" 0 1 2 3 15
21
22 _cleanup()
23 {
24         cd /
25         rm -f $tmp.*
26
27         echo $$ > $cgdir/cgroup.procs
28         rmdir $cgdir/$seq-cg* > /dev/null 2>&1
29         umount $SCRATCH_MNT > /dev/null 2>&1
30         _destroy_loop_device $LOOP_DEV > /dev/null 2>&1
31 }
32
33 # get standard environment, filters and checks
34 . ./common/rc
35 . ./common/filter
36 . ./common/cgroup2
37
38 # remove previous $seqres.full before test
39 rm -f $seqres.full
40
41 # real QA test starts here
42
43 # Modify as appropriate.
44 _supported_fs generic
45 _require_scratch_nocheck
46 _require_cgroup2 io
47 _require_loop
48
49 # cgroup v2 writeback is only support on block devices so far
50 _require_block_device $SCRATCH_DEV
51
52 cgdir=$CGROUP2_PATH
53 iosize=$((1024 * 1024 * 8))
54
55 # Check cgroup read/write charges against expected values. Allow for some
56 # tolerance as different filesystems seem to account slightly differently.
57 check_cg()
58 {
59         cgroot=$1
60         cgname=$(basename $cgroot)
61         expectedread=$2
62         expectedwrite=$3
63         readtol=$4
64         writetol=$5
65         rbytes=0
66         wbytes=0
67
68         iobytes=`cat $cgroot/io.stat | grep $smajor:$sminor`
69         if [ $? == 0 ]; then
70                 rbytes=`echo $iobytes | awk '{ print $2 }' | \
71                         awk -F = '{ print $2 }'`
72                 wbytes=`echo $iobytes | awk '{ print $3 }' | \
73                         awk -F = '{ print $2 }'`
74         fi
75
76         _within_tolerance "read" $rbytes $expectedread $readtol -v
77         _within_tolerance "write" $wbytes $expectedwrite $writetol -v
78 }
79
80 # Move current process to another cgroup.
81 switch_cg()
82 {
83         mkdir -p $1
84         echo $$ > $1/cgroup.procs
85 }
86
87 # Reset cgroup state for a new test.
88 reset()
89 {
90         echo $$ > $cgdir/cgroup.procs
91         rmdir $cgdir/$seq-cg* > /dev/null 2>&1
92         $XFS_IO_PROG -fc "pwrite 0 $iosize" $SCRATCH_MNT/file \
93                 >> $seqres.full 2>&1
94         umount $SCRATCH_MNT || _fail "umount failed"
95         _mount $LOOP_DEV $SCRATCH_MNT || _fail "mount failed"
96         stat $SCRATCH_MNT/file > /dev/null
97 }
98
99 # cgroup I/O accounting doesn't work on partitions. Use a loop device to rule
100 # that out.
101 LOOP_DEV=$(_create_loop_device $SCRATCH_DEV)
102 smajor=$((0x`stat -L -c %t $LOOP_DEV`))
103 sminor=$((0x`stat -L -c %T $LOOP_DEV`))
104
105 _mkfs_dev $LOOP_DEV >> $seqres.full 2>&1
106 _mount $LOOP_DEV $SCRATCH_MNT || _fail "mount failed"
107
108 drop_io_cgroup=
109 grep -q -w io $cgdir/cgroup.subtree_control || drop_io_cgroup=1
110
111 echo "+io" > $cgdir/cgroup.subtree_control || _fail "subtree control"
112
113 # Read and write from a single group.
114 echo "read/write"
115 reset
116 switch_cg $cgdir/$seq-cg
117 $XFS_IO_PROG -c "pread 0 $iosize" -c "pwrite 0 $iosize" -c fsync \
118         $SCRATCH_MNT/file >> $seqres.full 2>&1
119 switch_cg $cgdir
120 $XFS_IO_PROG -c fsync $SCRATCH_MNT/file
121 check_cg $cgdir/$seq-cg $iosize $iosize 5% 5%
122
123 # Write from one cgroup then read and write from a second. Writes are charged to
124 # the first group and nothing to the second.
125 echo "write -> read/write"
126 reset
127 switch_cg $cgdir/$seq-cg
128 $XFS_IO_PROG -c "pwrite 0 $iosize" $SCRATCH_MNT/file >> $seqres.full 2>&1
129 switch_cg $cgdir/$seq-cg-2
130 $XFS_IO_PROG -c "pread 0 $iosize" -c "pwrite 0 $iosize" $SCRATCH_MNT/file \
131         >> $seqres.full 2>&1
132 switch_cg $cgdir
133 $XFS_IO_PROG -c fsync $SCRATCH_MNT/file
134 # Use a fixed value tolerance for the expected value of zero here
135 # because filesystems might perform a small number of metadata reads to
136 # complete the write. On ext2/3 with 1k block size, the read bytes is
137 # as large as 33792.
138 check_cg $cgdir/$seq-cg 0 $iosize 33792 5%
139 check_cg $cgdir/$seq-cg-2 0 0 0 0
140
141 # Read from one cgroup, read & write from a second. Both reads and writes are
142 # charged to the first group and nothing to the second.
143 echo "read -> read/write"
144 reset
145 switch_cg $cgdir/$seq-cg
146 $XFS_IO_PROG -c "pread 0 $iosize" $SCRATCH_MNT/file >> $seqres.full 2>&1
147 switch_cg $cgdir/$seq-cg-2
148 $XFS_IO_PROG -c "pread 0 $iosize" -c "pwrite 0 $iosize" $SCRATCH_MNT/file \
149         >> $seqres.full 2>&1
150 switch_cg $cgdir
151 $XFS_IO_PROG -c fsync $SCRATCH_MNT/file
152 check_cg $cgdir/$seq-cg $iosize $iosize 5% 5%
153 check_cg $cgdir/$seq-cg-2 0 0 0 0
154
155 if [ "$drop_io_cgroup" = 1 ]; then
156         echo "-io" > $cgdir/cgroup.subtree_control || _fail "subtree control"
157 fi
158
159 # success, all done
160 status=0
161 exit