• Filipe Manana's avatar
    Btrfs: part 2, fix incremental send's decision to delay a dir move/rename · bfa7e1f8
    Filipe Manana authored
    For an incremental send, fix the process of determining whether the directory
    inode we're currently processing needs to have its move/rename operation delayed.
    
    We were ignoring the fact that if the inode's new immediate ancestor has a higher
    inode number than ours but wasn't renamed/moved, we might still need to delay our
    move/rename, because some other ancestor directory higher in the hierarchy might
    have an inode number higher than ours *and* was renamed/moved too - in this case
    we have to wait for rename/move of that ancestor to happen before our current
    directory's rename/move operation.
    
    Simple steps to reproduce this issue:
    
          $ mkfs.btrfs -f /dev/sdd
          $ mount /dev/sdd /mnt
    
          $ mkdir -p /mnt/a/x1/x2
          $ mkdir /mnt/a/Z
          $ mkdir -p /mnt/a/x1/x2/x3/x4/x5
    
          $ btrfs subvolume snapshot -r /mnt /mnt/snap1
          $ btrfs send /mnt/snap1 -f /tmp/base.send
    
          $ mv /mnt/a/x1/x2/x3 /mnt/a/Z/X33
          $ mv /mnt/a/x1/x2 /mnt/a/Z/X33/x4/x5/X22
    
          $ btrfs subvolume snapshot -r /mnt /mnt/snap2
          $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/incremental.send
    
    The incremental send caused the kernel code to enter an infinite loop when
    building the path string for directory Z after its references are processed.
    
    A more complex scenario:
    
          $ mkfs.btrfs -f /dev/sdd
          $ mount /dev/sdd /mnt
    
          $ mkdir -p /mnt/a/b/c/d
          $ mkdir /mnt/a/b/c/d/e
          $ mkdir /mnt/a/b/c/d/f
          $ mv /mnt/a/b/c/d/e /mnt/a/b/c/d/f/E2
          $ mkdir /mmt/a/b/c/g
          $ mv /mnt/a/b/c/d /mnt/a/b/D2
    
          $ btrfs subvolume snapshot -r /mnt /mnt/snap1
          $ btrfs send /mnt/snap1 -f /tmp/base.send
    
          $ mkdir /mnt/a/o
          $ mv /mnt/a/b/c/g /mnt/a/b/D2/f/G2
          $ mv /mnt/a/b/D2 /mnt/a/b/dd
          $ mv /mnt/a/b/c /mnt/a/C2
          $ mv /mnt/a/b/dd/f /mnt/a/o/FF
          $ mv /mnt/a/b /mnt/a/o/FF/E2/BB
    
          $ btrfs subvolume snapshot -r /mnt /mnt/snap2
          $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/incremental.send
    
    A test case for xfstests follows.
    Signed-off-by: default avatarFilipe David Borba Manana <fdmanana@gmail.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    bfa7e1f8
send.c 133 KB