• Robbie Ko's avatar
    Btrfs: send, fix failure to move directories with the same name around · 801bec36
    Robbie Ko authored
    When doing an incremental send we can end up not moving directories that
    have the same name. This happens when the same parent directory has
    different child directories with the same name in the parent and send
    snapshots.
    
    For example, consider the following scenario:
    
      Parent snapshot:
    
      .                   (ino 256)
      |---- d/            (ino 257)
      |     |--- p1/      (ino 258)
      |
      |---- p1/           (ino 259)
    
      Send snapshot:
    
      .                    (ino 256)
      |--- d/              (ino 257)
           |--- p1/        (ino 259)
                 |--- p1/  (ino 258)
    
    The directory named "d" (inode 257) has in both snapshots an entry with
    the name "p1" but it refers to different inodes in both snapshots (inode
    258 in the parent snapshot and inode 259 in the send snapshot). When
    attempting to move inode 258, the operation is delayed because its new
    parent, inode 259, was not yet moved/renamed (as the stream is currently
    processing inode 258). Then when processing inode 259, we also end up
    delaying its move/rename operation so that it happens after inode 258 is
    moved/renamed. This decision to delay the move/rename rename operation
    of inode 259 is due to the fact that the new parent inode (257) still
    has inode 258 as its child, which has the same name has inode 259. So
    we end up with inode 258 move/rename operation waiting for inode's 259
    move/rename operation, which in turn it waiting for inode's 258
    move/rename. This results in ending the send stream without issuing
    move/rename operations for inodes 258 and 259 and generating the
    following warnings in syslog/dmesg:
    
    [148402.979747] ------------[ cut here ]------------
    [148402.980588] WARNING: CPU: 14 PID: 4117 at fs/btrfs/send.c:6177 btrfs_ioctl_send+0xe03/0xe51 [btrfs]
    [148402.981928] Modules linked in: btrfs crc32c_generic xor raid6_pq acpi_cpufreq tpm_tis ppdev tpm parport_pc psmouse parport sg pcspkr i2c_piix4 i2c_core evdev processor serio_raw button loop autofs4 ext4 crc16 jbd2 mbcache sr_mod cdrom sd_mod ata_generic virtio_scsi ata_piix libata virtio_pci virtio_ring virtio e1000 scsi_mod floppy [last unloaded: btrfs]
    [148402.986999] CPU: 14 PID: 4117 Comm: btrfs Tainted: G        W       4.6.0-rc7-btrfs-next-31+ #1
    [148402.988136] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014
    [148402.988136]  0000000000000000 ffff88022139fca8 ffffffff8126b42c 0000000000000000
    [148402.988136]  0000000000000000 ffff88022139fce8 ffffffff81052b14 000018212139fac8
    [148402.988136]  ffff88022b0db400 0000000000000000 0000000000000001 0000000000000000
    [148402.988136] Call Trace:
    [148402.988136]  [<ffffffff8126b42c>] dump_stack+0x67/0x90
    [148402.988136]  [<ffffffff81052b14>] __warn+0xc2/0xdd
    [148402.988136]  [<ffffffff81052beb>] warn_slowpath_null+0x1d/0x1f
    [148402.988136]  [<ffffffffa04bc831>] btrfs_ioctl_send+0xe03/0xe51 [btrfs]
    [148402.988136]  [<ffffffffa048b358>] btrfs_ioctl+0x14f/0x1f81 [btrfs]
    [148402.988136]  [<ffffffff8108e456>] ? arch_local_irq_save+0x9/0xc
    [148402.988136]  [<ffffffff8108eb51>] ? __lock_is_held+0x3c/0x57
    [148402.988136]  [<ffffffff8118da05>] vfs_ioctl+0x18/0x34
    [148402.988136]  [<ffffffff8118e00c>] do_vfs_ioctl+0x550/0x5be
    [148402.988136]  [<ffffffff81196f0c>] ? __fget+0x6b/0x77
    [148402.988136]  [<ffffffff81196fa1>] ? __fget_light+0x62/0x71
    [148402.988136]  [<ffffffff8118e0d1>] SyS_ioctl+0x57/0x79
    [148402.988136]  [<ffffffff8149e025>] entry_SYSCALL_64_fastpath+0x18/0xa8
    [148402.988136]  [<ffffffff8108e89d>] ? trace_hardirqs_off_caller+0x3f/0xaa
    [148403.011373] ---[ end trace a4539270c8056f8b ]---
    [148403.012296] ------------[ cut here ]------------
    [148403.013071] WARNING: CPU: 14 PID: 4117 at fs/btrfs/send.c:6194 btrfs_ioctl_send+0xe19/0xe51 [btrfs]
    [148403.014447] Modules linked in: btrfs crc32c_generic xor raid6_pq acpi_cpufreq tpm_tis ppdev tpm parport_pc psmouse parport sg pcspkr i2c_piix4 i2c_core evdev processor serio_raw button loop autofs4 ext4 crc16 jbd2 mbcache sr_mod cdrom sd_mod ata_generic virtio_scsi ata_piix libata virtio_pci virtio_ring virtio e1000 scsi_mod floppy [last unloaded: btrfs]
    [148403.019708] CPU: 14 PID: 4117 Comm: btrfs Tainted: G        W       4.6.0-rc7-btrfs-next-31+ #1
    [148403.020104] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014
    [148403.020104]  0000000000000000 ffff88022139fca8 ffffffff8126b42c 0000000000000000
    [148403.020104]  0000000000000000 ffff88022139fce8 ffffffff81052b14 000018322139fac8
    [148403.020104]  ffff88022b0db400 0000000000000000 0000000000000001 0000000000000000
    [148403.020104] Call Trace:
    [148403.020104]  [<ffffffff8126b42c>] dump_stack+0x67/0x90
    [148403.020104]  [<ffffffff81052b14>] __warn+0xc2/0xdd
    [148403.020104]  [<ffffffff81052beb>] warn_slowpath_null+0x1d/0x1f
    [148403.020104]  [<ffffffffa04bc847>] btrfs_ioctl_send+0xe19/0xe51 [btrfs]
    [148403.020104]  [<ffffffffa048b358>] btrfs_ioctl+0x14f/0x1f81 [btrfs]
    [148403.020104]  [<ffffffff8108e456>] ? arch_local_irq_save+0x9/0xc
    [148403.020104]  [<ffffffff8108eb51>] ? __lock_is_held+0x3c/0x57
    [148403.020104]  [<ffffffff8118da05>] vfs_ioctl+0x18/0x34
    [148403.020104]  [<ffffffff8118e00c>] do_vfs_ioctl+0x550/0x5be
    [148403.020104]  [<ffffffff81196f0c>] ? __fget+0x6b/0x77
    [148403.020104]  [<ffffffff81196fa1>] ? __fget_light+0x62/0x71
    [148403.020104]  [<ffffffff8118e0d1>] SyS_ioctl+0x57/0x79
    [148403.020104]  [<ffffffff8149e025>] entry_SYSCALL_64_fastpath+0x18/0xa8
    [148403.020104]  [<ffffffff8108e89d>] ? trace_hardirqs_off_caller+0x3f/0xaa
    [148403.038981] ---[ end trace a4539270c8056f8c ]---
    
    There's another issue caused by similar (but more complex) changes in the
    directory hierarchy that makes move/rename operations fail, described with
    the following example:
    
      Parent snapshot:
    
      .
      |---- a/                                                   (ino 262)
      |     |---- c/                                             (ino 268)
      |
      |---- d/                                                   (ino 263)
            |---- ance/                                          (ino 267)
                    |---- e/                                     (ino 264)
                    |---- f/                                     (ino 265)
                    |---- ance/                                  (ino 266)
    
      Send snapshot:
    
      .
      |---- a/                                                   (ino 262)
      |---- c/                                                   (ino 268)
      |     |---- ance/                                          (ino 267)
      |
      |---- d/                                                   (ino 263)
      |     |---- ance/                                          (ino 266)
      |
      |---- f/                                                   (ino 265)
            |---- e/                                             (ino 264)
    
    When the inode 265 is processed, the path for inode 267 is computed, which
    at that time corresponds to "d/ance", and it's stored in the names cache.
    Later on when processing inode 266, we end up orphanizing (renaming to a
    name matching the pattern o<ino>-<gen>-<seq>) inode 267 because it has
    the same name as inode 266 and it's currently a child of the new parent
    directory (inode 263) for inode 266. After the orphanization and while we
    are still processing inode 266, a rename operation for inode 266 is
    generated. However the source path for that rename operation is incorrect
    because it ends up using the old, pre-orphanization, name of inode 267.
    The no longer valid name for inode 267 was previously cached when
    processing inode 265 and it remains usable and considered valid until
    the inode currently being processed has a number greater than 267.
    This resulted in the receiving side failing with the following error:
    
      ERROR: rename d/ance/ance -> d/ance failed: No such file or directory
    
    So fix these issues by detecting such circular dependencies for rename
    operations and by clearing the cached name of an inode once the inode
    is orphanized.
    
    A test case for fstests will follow soon.
    Signed-off-by: default avatarRobbie Ko <robbieko@synology.com>
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    [Rewrote change log to be more detailed and organized, and improved
     comments]
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    801bec36
send.c 148 KB