2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2015 SUSE Linux Products GmbH. All Rights Reserved.
5 # FS QA Test No. btrfs/092
7 # Test btrfs incremental send after renaming and moving directories around in a
8 # way that ends up making a directory have different dentries with the same name
9 # but pointing to different inodes in the parent and send snapshots, and also
10 # inverting the ancestor-descendent relationship between one of those inodes and
13 # Cases like this made an incremental send enter an infinite lopp when building
14 # path strings, leading to -ENOMEM errors when the path string reached a length
16 # This issue was fixed by the following linux kernel btrfs patch:
18 # Btrfs: incremental send, check if orphanized dir inode needs delayed rename
21 seqres=$RESULT_DIR/$seq
22 echo "QA output created by $seq"
25 status=1 # failure is the default!
26 trap "_cleanup; exit \$status" 0 1 2 3 15
30 rm -fr $send_files_dir
34 # get standard environment, filters and checks
38 # real QA test starts here
43 send_files_dir=$TEST_DIR/btrfs-test-$seq
46 rm -fr $send_files_dir
49 _scratch_mkfs >>$seqres.full 2>&1
52 mkdir -p $SCRATCH_MNT/data/n1/n2
53 mkdir $SCRATCH_MNT/data/n4
54 mkdir -p $SCRATCH_MNT/data/t6/t7
55 mkdir $SCRATCH_MNT/data/t5
56 mkdir $SCRATCH_MNT/data/t7
57 mkdir $SCRATCH_MNT/data/n4/t2
58 mkdir $SCRATCH_MNT/data/t4
59 mkdir $SCRATCH_MNT/data/t3
60 mv $SCRATCH_MNT/data/t7 $SCRATCH_MNT/data/n4/t2
61 mv $SCRATCH_MNT/data/t4 $SCRATCH_MNT/data/n4/t2/t7
62 mv $SCRATCH_MNT/data/t5 $SCRATCH_MNT/data/n4/t2/t7/t4
63 mv $SCRATCH_MNT/data/t6 $SCRATCH_MNT/data/n4/t2/t7/t4/t5
64 mv $SCRATCH_MNT/data/n1/n2 $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6
65 mv $SCRATCH_MNT/data/n1 $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6
66 mv $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6/t7 $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6/n2
67 mv $SCRATCH_MNT/data/t3 $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6/n2/t7
69 # Filesystem looks like:
84 _run_btrfs_util_prog subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap1
86 # The sequence of directory rename operations below made the btrfs incremental
87 # send implementation enter an infinite loop when building path strings. The
88 # reason for this was the following:
90 # * While processing inode 262 it ended up orphanizing inode 264 (rename it to
91 # "/o264-6-0"). This is because the parent inode 265 has a dentry with name
92 # t7 in the parent snapshot that refers to inode 264, which is ahead of the
93 # current send progress (inode 262) and our inode 262 has the name t7 in
94 # the directory inode 265 in the send snapshot - so in order to rename inode
95 # 262 to its new name/location, it orphanizes (renames) 264 before 264 is
98 # * When it processes inode 264 it was not checking if it needed to delay its
99 # rename operation. This was incorrect because in the parent snapshot inode
100 # 267 is a descendent of inode 264 and inode 267 is an ancestor of inode 264
101 # in the send snapshot, which means the rename of inode 264 must happen after
102 # inode 267 is renamed in order to avoid the infinite loops when building
103 # path strings that involved inodes 264 and 267;
105 # * As a consequence as soon as the send progress moved to inode 265, the
106 # following loop when building a path string for inode 264 happened:
108 # start inode 264, send progress of 265 for example
109 # parent of 264 -> 267
110 # parent of 267 -> 262
111 # parent of 262 -> 259
112 # parent of 259 -> 261
113 # parent of 261 -> 263
114 # parent of 263 -> 266
115 # parent of 266 -> 264
116 # |--> back to first iteration while current path string length
117 # is <= PATH_MAX, and fail with -ENOMEM otherwise
119 mv $SCRATCH_MNT/data/n4/t2/t7/t4/t5/t6/n1 $SCRATCH_MNT/data/n4
120 mv $SCRATCH_MNT/data/n4/t2 $SCRATCH_MNT/data/n4/n1
121 mv $SCRATCH_MNT/data/n4/n1/t2/t7/t4/t5/t6/n2 $SCRATCH_MNT/data/n4/n1/t2
122 mv $SCRATCH_MNT/data/n4/n1/t2/n2/t7/t3 $SCRATCH_MNT/data/n4/n1/t2
123 mv $SCRATCH_MNT/data/n4/n1/t2/t7/t4/t5/t6 $SCRATCH_MNT/data/n4/n1/t2
124 mv $SCRATCH_MNT/data/n4/n1/t2/t7/t4 $SCRATCH_MNT/data/n4/n1/t2/t6
125 mv $SCRATCH_MNT/data/n4/n1/t2/t7 $SCRATCH_MNT/data/n4/n1/t2/t3
126 mv $SCRATCH_MNT/data/n4/n1/t2/n2/t7 $SCRATCH_MNT/data/n4/n1/t2
128 # Filesystem now looks like:
131 # |-- data/ (ino 257)
140 # | |-- t4/ (ino 266)
141 # | |-- t5/ (ino 263)
145 _run_btrfs_util_prog subvolume snapshot -r $SCRATCH_MNT $SCRATCH_MNT/mysnap2
147 run_check $FSSUM_PROG -A -f -w $send_files_dir/1.fssum $SCRATCH_MNT/mysnap1
148 run_check $FSSUM_PROG -A -f -w $send_files_dir/2.fssum \
149 -x $SCRATCH_MNT/mysnap2/mysnap1 $SCRATCH_MNT/mysnap2
151 _run_btrfs_util_prog send -f $send_files_dir/1.snap $SCRATCH_MNT/mysnap1
152 _run_btrfs_util_prog send -p $SCRATCH_MNT/mysnap1 -f $send_files_dir/2.snap \
155 # Now recreate the filesystem by receiving both send streams and verify we get
156 # the same content that the original filesystem had.
158 _scratch_mkfs >>$seqres.full 2>&1
161 _run_btrfs_util_prog receive -f $send_files_dir/1.snap $SCRATCH_MNT
162 run_check $FSSUM_PROG -r $send_files_dir/1.fssum $SCRATCH_MNT/mysnap1
163 _run_btrfs_util_prog receive -f $send_files_dir/2.snap $SCRATCH_MNT
164 run_check $FSSUM_PROG -r $send_files_dir/2.fssum $SCRATCH_MNT/mysnap2
166 echo "Silence is golden"