On Tue, Jul 24, 2018 at 11:54:04AM +0100, fdman...@kernel.org wrote:
> From: Filipe Manana <fdman...@suse.com>
> 
> The more common use case of send involves creating a RO snapshot and then
> use it for a send operation. In this case it's not possible to have inodes
> in the snapshot that have a link count of zero (inode with an orphan item)
> since during snapshot creation we do the orphan cleanup. However, other
> less common use cases for send can end up seeing inodes with a link count
> of zero and in this case the send operation fails with a ENOENT error
> because any attempt to generate a path for the inode, with the purpose
> of creating it or updating it at the receiver, fails since there are no
> inode reference items. One use case it to use a regular subvolume for
> a send operation after turning it to RO mode or turning a RW snapshot
> into RO mode and then using it for a send operation. In both cases, if a
> file gets all its hard links deleted while there is an open file
> descriptor before turning the subvolume/snapshot into RO mode, the send
> operation will encounter an inode with a link count of zero and then
> fail with errno ENOENT.
> 
> Example using a full send with a subvolume:
> 
>   $ mkfs.btrfs -f /dev/sdb
>   $ mount /dev/sdb /mnt
> 
>   $ btrfs subvolume create /mnt/sv1
>   $ touch /mnt/sv1/foo
>   $ touch /mnt/sv1/bar
> 
>   # keep an open file descriptor on file bar
>   $ exec 73</mnt/sv1/bar
>   $ unlink /mnt/sv1/bar
> 
>   # Turn the subvolume to RO mode and use it for a full send, while
>   # holding the open file descriptor.
>   $ btrfs property set /mnt/sv1 ro true
> 
>   $ btrfs send -f /tmp/full.send /mnt/sv1
>   At subvol /mnt/sv1
>   ERROR: send ioctl failed with -2: No such file or directory
> 
> Example using an incremental send with snapshots:
> 
>   $ mkfs.btrfs -f /dev/sdb
>   $ mount /dev/sdb /mnt
> 
>   $ btrfs subvolume create /mnt/sv1
>   $ touch /mnt/sv1/foo
>   $ touch /mnt/sv1/bar
> 
>   $ btrfs subvolume snapshot -r /mnt/sv1 /mnt/snap1
> 
>   $ echo "hello world" >> /mnt/sv1/bar
> 
>   $ btrfs subvolume snapshot -r /mnt/sv1 /mnt/snap2
> 
>   # Turn the second snapshot to RW mode and delete file foo while
>   # holding an open file descriptor on it.
>   $ btrfs property set /mnt/snap2 ro false
>   $ exec 73</mnt/snap2/foo
>   $ unlink /mnt/snap2/foo
> 
>   # Set the second snapshot back to RO mode and do an incremental send.
>   $ btrfs property set /mnt/snap2 ro true
> 
>   $ btrfs send -f /tmp/inc.send -p /mnt/snap1 /mnt/snap2
>   At subvol /mnt/snap2
>   ERROR: send ioctl failed with -2: No such file or directory
> 
> So fix this by ignoring inodes with a link count of zero if we are either
> doing a full send or if they do not exist in the parent snapshot (they
> are new in the send snapshot), and unlink all paths found in the parent
> snapshot when doing an incremental send (and ignoring all other inode
> items, such as xattrs and extents).
> 
> A test case for fstests follows soon.
> 
> Reported-by: Martin Wilck <martin.wi...@suse.com>
> Signed-off-by: Filipe Manana <fdman...@suse.com>

Added to misc-next, thanks. I did a light review of the overall logic
how the ignore_cur_inode is passed around, skipping the orphans and
replacing with send_unlink sounds ok to me.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to