| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (C) 2017 Synology Inc. All Rights Reserved. |
| # |
| # FS QA Test No. btrfs/135 |
| # |
| # Test that an incremental send operation works when in both snapshots there are |
| # two directory inodes that have the same number but different generations and |
| # have an entry with the same name that corresponds to different inodes in each |
| # snapshot. |
| # |
| . ./common/preamble |
| _begin_fstest auto quick send |
| |
| # Override the default cleanup function. |
| _cleanup() |
| { |
| cd / |
| rm -fr $send_files_dir |
| rm -f $tmp.* |
| } |
| |
| . ./common/filter |
| |
| _require_test |
| _require_scratch |
| _require_fssum |
| |
| send_files_dir=$TEST_DIR/btrfs-test-$seq |
| |
| rm -fr $send_files_dir |
| mkdir $send_files_dir |
| |
| _scratch_mkfs >>$seqres.full 2>&1 |
| _scratch_mount |
| |
| touch $SCRATCH_MNT/f |
| mkdir $SCRATCH_MNT/d1 |
| mkdir $SCRATCH_MNT/d259_old |
| mv $SCRATCH_MNT/d1 $SCRATCH_MNT/d259_old/d1 |
| |
| # Filesystem looks like: |
| # |
| # . (ino 256) |
| # |--- f (ino 257) |
| # | |
| # |--- d259_old/ (ino 259) |
| # |--- d1/ (ino 258) |
| # |
| $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT \ |
| $SCRATCH_MNT/mysnap1 > /dev/null |
| |
| $BTRFS_UTIL_PROG send -f $send_files_dir/1.snap \ |
| $SCRATCH_MNT/mysnap1 2>&1 1>/dev/null | _filter_scratch |
| |
| _scratch_unmount |
| _scratch_mkfs >>$seqres.full 2>&1 |
| _scratch_mount |
| mkdir $SCRATCH_MNT/d1 |
| mkdir $SCRATCH_MNT/dir258 |
| mkdir $SCRATCH_MNT/dir259 |
| mv $SCRATCH_MNT/d1 $SCRATCH_MNT/dir259/d1 |
| |
| # Filesystem now looks like: |
| # |
| # . (ino 256) |
| # |--- dir258/ (ino 258) |
| # | |
| # |--- dir259/ (ino 259) |
| # |--- d1/ (ino 257) |
| # |
| # Notice that at this point all inodes have a generation with value 7, which is |
| # the generation value for a brand new filesystem. |
| |
| # Now create the second snapshot. This makes the filesystem's current generation |
| # value to increase to the value 8, due to a transaction commit performed by the |
| # snapshot creation ioctl. |
| $BTRFS_UTIL_PROG subvolume snapshot -r $SCRATCH_MNT \ |
| $SCRATCH_MNT/mysnap2 > /dev/null |
| |
| # Now receive the first snapshot created in the first filesystem. |
| # Before creating any inodes, the receive command creates the first snapshot, |
| # which causes a transaction commit and therefore bumps the filesystem's current |
| # generation to the value 9. All the inodes created end up getting a generation |
| # value of 9 and the snapshot's root inode (256) gets a generation value of 8. |
| $BTRFS_UTIL_PROG receive -f $send_files_dir/1.snap $SCRATCH_MNT > /dev/null |
| rm $send_files_dir/1.snap |
| |
| $FSSUM_PROG -A -f -w $send_files_dir/1.fssum $SCRATCH_MNT/mysnap1 |
| $FSSUM_PROG -A -f -w $send_files_dir/2.fssum $SCRATCH_MNT/mysnap2 |
| |
| $BTRFS_UTIL_PROG send -f $send_files_dir/1.snap \ |
| $SCRATCH_MNT/mysnap1 2>&1 1>/dev/null | _filter_scratch |
| $BTRFS_UTIL_PROG send -p $SCRATCH_MNT/mysnap1 -f $send_files_dir/2.snap \ |
| $SCRATCH_MNT/mysnap2 2>&1 1>/dev/null | _filter_scratch |
| |
| # Now recreate the filesystem by receiving both send streams and verify we get |
| # the same content that the original filesystem had. |
| _scratch_unmount |
| _scratch_mkfs >>$seqres.full 2>&1 |
| _scratch_mount |
| |
| $BTRFS_UTIL_PROG receive -f $send_files_dir/1.snap $SCRATCH_MNT > /dev/null |
| $FSSUM_PROG -r $send_files_dir/1.fssum $SCRATCH_MNT/mysnap1 |
| # The receive of the incremental send stream used to fail because it contained |
| # a rmdir operation with an invalid path. The output of the receive command, |
| # with verbose mode (argument -vv), was the following: |
| # |
| # utimes |
| # unlink f |
| # mkdir o257-7-0 |
| # mkdir o259-7-0 |
| # rename o257-7-0 -> o259-7-0/d1 |
| # chown o259-7-0/d1 - uid=0, gid=0 |
| # chmod o259-7-0/d1 - mode=0755 |
| # utimes o259-7-0/d1 |
| # rmdir o258-9-0 |
| # ERROR: rmdir o258-9-0 failed: No such file or directory |
| # |
| # When the kernel was computing the send stream and processing inode 258, it |
| # noticed that in both snapshots this inode is a direct child of inode 259, and |
| # that in both snapshots inode 259 as an entry with the name "d1". Because of |
| # that it decided (incorrectly) to issue an rmdir operation using the orphanized |
| # name of the inode 258 from the parent snapshot (which has a generation of 9). |
| # However that decision to send an rmdir operation due to the dentry collision |
| # was incorrect because the inodes with number 259 in both snapshots are not the |
| # same, they have different generations. |
| # |
| $BTRFS_UTIL_PROG receive -f $send_files_dir/2.snap $SCRATCH_MNT > /dev/null |
| $FSSUM_PROG -r $send_files_dir/2.fssum $SCRATCH_MNT/mysnap2 |
| |
| status=0 |
| exit |