Rename _scratch_mount to _scratch_cycle_mount
[xfstests-dev.git] / tests / btrfs / 104
1 #! /bin/bash
2 # FS QA Test No. btrfs/104
3 #
4 # Test btrfs quota group consistency operations during snapshot
5 # delete. Btrfs has had long standing issues with drop snapshot
6 # failing to properly account for quota groups. This test crafts
7 # several snapshot trees with shared and exclusive elements. One of
8 # the trees is removed and then quota group consistency is checked.
9 #
10 # This issue is fixed by the following linux kernel patches:
11 #
12 #    Btrfs: use btrfs_get_fs_root in resolve_indirect_ref
13 #    Btrfs: keep dropped roots in cache until transaciton commit
14 #    btrfs: qgroup: account shared subtree during snapshot delete
15 #
16 #-----------------------------------------------------------------------
17 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
18 #
19 # This program is free software; you can redistribute it and/or
20 # modify it under the terms of the GNU General Public License as
21 # published by the Free Software Foundation.
22 #
23 # This program is distributed in the hope that it would be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 # GNU General Public License for more details.
27 #
28 # You should have received a copy of the GNU General Public License
29 # along with this program; if not, write the Free Software Foundation,
30 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
31 #
32 #-----------------------------------------------------------------------
33 #
34
35 seq=`basename $0`
36 seqres=$RESULT_DIR/$seq
37 echo "QA output created by $seq"
38
39 here=`pwd`
40 tmp=/tmp/$$
41 status=1        # failure is the default!
42 trap "_cleanup; exit \$status" 0 1 2 3 15
43
44 _cleanup()
45 {
46         cd /
47         rm -f $tmp.*
48 }
49
50 # get standard environment, filters and checks
51 . ./common/rc
52 . ./common/filter
53
54 # remove previous $seqres.full before test
55 rm -f $seqres.full
56
57 # real QA test starts here
58 _supported_fs btrfs
59 _supported_os Linux
60 _require_scratch
61 _need_to_be_root
62
63 rm -f $seqres.full
64
65 # Create an fs tree of a given height at a target location. This is
66 # done by agressively creating inline extents to expand the number of
67 # nodes required. We also add an traditional extent so that
68 # drop_snapshot is forced to walk at least one extent that is not
69 # stored in metadata.
70 #
71 # NOTE: The ability to vary tree height for this test is very useful
72 # for debugging problems with drop_snapshot(). As a result we retain
73 # that parameter even though the test below always does level 2 trees.
74 _explode_fs_tree () {
75         local level=$1;
76         local loc="$2";
77         local n;
78
79         if [ -z $loc ]; then
80                 echo "specify location for fileset"
81                 exit 1;
82         fi
83
84         case $level in
85         1)# this always reproduces level 1 trees
86                 n=10;
87                 ;;
88         2)# this always reproduces level 2 trees
89                 n=1500
90                 ;;
91         3)# this always reproduces level 3 trees
92                 n=1000000;
93                 ;;
94         *)
95                 echo "Can't make level $level trees";
96                 exit 1;
97                 ;;
98         esac
99
100         mkdir -p $loc
101         for i in `seq -w 1 $n`; do
102                 $XFS_IO_PROG -f -c "pwrite 0 4095" $loc/file$i > /dev/null 2>&1
103         done
104
105         $XFS_IO_PROG -f -c "pwrite 0 128k" $loc/extentfile > /dev/null 2>&1
106 }
107
108 # Force the default leaf size as the calculations for making our btree
109 # heights are based on that.
110 _scratch_mkfs "--nodesize 16384"
111 _scratch_mount
112
113 # populate the default subvolume and create a snapshot ('snap1')
114 _explode_fs_tree 1 $SCRATCH_MNT/files
115 _run_btrfs_util_prog subvolume snapshot $SCRATCH_MNT $SCRATCH_MNT/snap1
116
117 # create new btree nodes in this snapshot. They will become shared
118 # with the next snapshot we create.
119 _explode_fs_tree 1 $SCRATCH_MNT/snap1/files-snap1
120
121 # create our final snapshot ('snap2'), populate it with
122 # exclusively owned nodes.
123 #
124 # As a result of this action, snap2 will get an implied ref to the
125 # 128K extent created in the default subvolume.
126 _run_btrfs_util_prog subvolume snapshot $SCRATCH_MNT/snap1 $SCRATCH_MNT/snap2
127 _explode_fs_tree 1 $SCRATCH_MNT/snap2/files-snap2
128
129 # Enable qgroups now that we have our filesystem prepared. This
130 # will kick off a scan which we will have to wait for.
131 _run_btrfs_util_prog quota enable $SCRATCH_MNT
132 _run_btrfs_util_prog quota rescan -w $SCRATCH_MNT
133
134 # Remount to clear cache, force everything to disk
135 _scratch_cycle_mount
136
137 # Finally, delete snap1 to trigger btrfs_drop_snapshot(). This
138 # snapshot is most interesting to delete because it will cause some
139 # nodes to go exclusively owned for snap2, while some will stay shared
140 # with the default subvolume. That exercises a maximum of the drop
141 # snapshot/qgroup interactions.
142 #
143 # snap2s imlied ref from to the 128K extent in files/ can be lost by
144 # the root finding code in qgroup accounting due to snap1 no longer
145 # providing a path to it. This was fixed by the first two patches
146 # referenced above.
147 _run_btrfs_util_prog subvolume delete $SCRATCH_MNT/snap1
148
149 # There is no way from userspace to force btrfs_drop_snapshot to run
150 # at a given time (even via mount/unmount). We must wait for it to
151 # start and complete. This is the shortest time on my tests systems I
152 # have found which always allows drop_snapshot to run to completion.
153 sleep 45
154
155 _scratch_unmount
156
157 # generate a qgroup report and look for inconsistent groups
158 #  - don't use _run_btrfs_util_prog here as it captures the output and
159 #    we need to grep it.
160 $BTRFS_UTIL_PROG check --qgroup-report $SCRATCH_DEV 2>&1 | \
161                         grep -E -q "Counts for qgroup.*are different"
162 if [ $? -ne 0 ]; then
163         status=0
164 fi
165
166 exit