linux/fs
Filipe Manana 46b2f4590a Btrfs: fix send failure when root has deleted files still open
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.

CC: stable@vger.kernel.org # 4.4+
Reported-by: Martin Wilck <martin.wilck@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2018-08-06 13:12:59 +02:00
..
9p treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
adfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
affs affs: fix potential memory leak when parsing option 'prefix' 2018-05-28 12:36:41 +02:00
afs Merge branch 'afs-proc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-16 16:32:04 +09:00
autofs autofs: fix slab out of bounds read in getname_kernel() 2018-07-14 11:11:09 -07:00
befs fix a series of Documentation/ broken file name references 2018-06-15 18:10:01 -03:00
bfs bfs_add_entry: pass name/len as qstr pointer 2018-05-22 14:27:50 -04:00
btrfs Btrfs: fix send failure when root has deleted files still open 2018-08-06 13:12:59 +02:00
cachefiles cachefiles: Wait rather than BUG'ing on "Unexpected object collision" 2018-07-25 14:49:00 +01:00
ceph ceph: fix dentry leak in splice_dentry() 2018-06-26 18:42:44 +02:00
cifs cifs: Fix stack out-of-bounds in smb{2,3}_create_lease_buf() 2018-07-05 13:48:25 -05:00
coda vfs: change inode times to use struct timespec64 2018-06-05 16:57:31 -07:00
configfs vfs: change inode times to use struct timespec64 2018-06-05 16:57:31 -07:00
cramfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
crypto f2fs-for-4.18-rc1 2018-06-11 10:16:13 -07:00
debugfs Revert "debugfs: inode: debugfs_create_dir uses mode permission from parent" 2018-06-12 20:52:16 -07:00
devpts
dlm treewide: Use array_size() in vmalloc() 2018-06-12 16:19:22 -07:00
ecryptfs Merge branch 'fixes' of https://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs into aio-base 2018-05-26 09:16:25 +02:00
efivarfs
efs
exofs exofs: avoid VLA in structures 2018-06-15 07:55:24 +09:00
exportfs ovl: do not try to reconnect a disconnected origin dentry 2018-04-12 12:04:49 +02:00
ext2 ext2: add warning when specifying nocheck option 2018-06-20 11:04:26 +02:00
ext4 ext4: fix check to prevent initializing reserved inodes 2018-07-29 15:34:00 -04:00
f2fs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
fat fat: fix memory allocation failure handling of match_strdup() 2018-07-21 12:50:46 -07:00
freevxfs freevxfs_lookup(): use d_splice_alias() 2018-05-22 14:27:51 -04:00
fscache fscache: Fix reference overput in fscache_attach_object() error handling 2018-07-25 14:49:00 +01:00
fuse vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
gfs2 vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
hfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
hfsplus vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
hostfs vfs: change inode times to use struct timespec64 2018-06-05 16:57:31 -07:00
hpfs treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
hugetlbfs mm: use vma_init() to initialize VMAs on stack and data segments 2018-07-26 19:38:03 -07:00
isofs isofs: fix potential memory leak in mount option parsing 2018-04-16 09:47:41 +02:00
jbd2 Bug fixes for ext4; most of which relate to vulnerabilities where a 2018-07-08 11:10:30 -07:00
jffs2 vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
jfs jfs: Fix usercopy whitelist for inline inode data 2018-08-04 07:53:46 -07:00
kernfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
lockd
minix minix_lookup: use d_splice_alias() 2018-05-22 14:27:52 -04:00
nfs NFSv4: Fix _nfs4_do_setlk() 2018-08-01 23:17:06 -04:00
nfs_common
nfsd vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
nilfs2 do d_instantiate/unlock_new_inode combinations safely 2018-05-11 15:36:37 -04:00
nls
notify fsnotify: add fsnotify_add_inode_mark() wrappers 2018-05-18 14:58:22 +02:00
ntfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
ocfs2 vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
omfs omfs_lookup(): report IO errors, use d_splice_alias() 2018-05-22 14:27:58 -04:00
openpromfs openpromfs: switch to d_splice_alias() 2018-05-22 14:27:57 -04:00
orangefs Solve a series of broken links for files under Documentation: 2018-06-17 05:25:18 +09:00
overlayfs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
proc fs/proc/task_mmu.c: fix Locked field in /proc/pid/smaps* 2018-07-14 11:11:09 -07:00
pstore pstore: Remove bogus format string definition 2018-06-14 14:57:24 +02:00
qnx4 qnx4_lookup: use d_splice_alias() 2018-05-22 14:27:52 -04:00
qnx6 qnx6_lookup: switch to d_splice_alias() 2018-05-22 14:27:54 -04:00
quota quota: Cleanup list iteration in dqcache_shrink_scan() 2018-06-20 11:04:26 +02:00
ramfs
reiserfs reiserfs: fix buffer overflow with long warning messages 2018-07-14 11:11:10 -07:00
romfs romfs_lookup: switch to d_splice_alias() 2018-05-22 14:27:55 -04:00
squashfs Squashfs: Compute expected length from inode size rather than block length 2018-08-02 09:34:02 -07:00
sysfs unfuck sysfs_mount() 2018-05-21 14:30:09 -04:00
sysv sysv_lookup: use d_splice_alias() 2018-05-22 14:27:53 -04:00
tracefs
ubifs vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
udf udf: Drop unused arguments of udf_delete_aext() 2018-06-20 11:05:49 +02:00
ufs treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
xfs xfs: properly handle free inodes in extent hint validators 2018-07-24 11:34:52 -07:00
aio.c Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-07-22 12:04:51 -07:00
anon_inodes.c
attr.c vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
bad_inode.c vfs: change inode times to use struct timespec64 2018-06-05 16:57:31 -07:00
binfmt_aout.c exec: introduce finalize_exec() before start_thread() 2018-04-11 10:28:37 -07:00
binfmt_elf_fdpic.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
binfmt_elf.c fs, elf: make sure to page align bss in load_elf_library 2018-07-14 11:11:10 -07:00
binfmt_em86.c
binfmt_flat.c exec: introduce finalize_exec() before start_thread() 2018-04-11 10:28:37 -07:00
binfmt_misc.c docs: Fix more broken references 2018-06-15 18:11:26 -03:00
binfmt_script.c
block_dev.c for-linus-20180727 2018-07-27 12:51:00 -07:00
buffer.c fs: move page_cache_seek_hole_data to iomap.c 2018-06-01 18:37:33 -07:00
char_dev.c
compat_binfmt_elf.c
compat_ioctl.c autofs: clean up includes 2018-06-07 17:34:40 -07:00
compat.c ncpfs: remove compat functionality 2018-06-05 19:23:26 +02:00
coredump.c
d_path.c
dax.c libnvdimm for 4.18 2018-06-08 17:21:52 -07:00
dcache.c Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-04 10:14:28 -07:00
dcookies.c
direct-io.c block: consistently use GFP_NOIO instead of __GFP_NORECLAIM 2018-05-14 08:55:18 -06:00
drop_caches.c
eventfd.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
eventpoll.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
exec.c mm: fix vma_is_anonymous() false-positives 2018-07-26 19:38:03 -07:00
fcntl.c mm: restructure memfd code 2018-06-07 17:34:35 -07:00
fhandle.c
file_table.c
file.c
filesystems.c proc: introduce proc_create_single{,_data} 2018-05-16 07:23:35 +02:00
fs_pin.c
fs_struct.c
fs-writeback.c bdi: Fix oops in wb_workfn() 2018-05-03 16:11:37 -06:00
inode.c Fix up non-directory creation in SGID directories 2018-07-05 12:36:36 -07:00
internal.h drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() 2018-07-10 23:29:03 -04:00
ioctl.c fs: Allow CAP_SYS_ADMIN in s_user_ns to freeze and thaw filesystems 2018-05-24 12:04:28 -05:00
iomap.c fs: fix iomap_bmap position calculation 2018-08-02 13:09:27 -07:00
Kconfig autofs: remove left-over autofs4 stubs 2018-06-11 08:22:34 -07:00
Kconfig.binfmt docs: Fix more broken references 2018-06-15 18:11:26 -03:00
libfs.c
locks.c vfs/y2038: inode timestamps conversion to timespec64 2018-06-15 07:31:07 +09:00
Makefile autofs: remove left-over autofs4 stubs 2018-06-11 08:22:34 -07:00
mbcache.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
mount.h
mpage.c
namei.c Merge branch 'afs-proc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-16 16:32:04 +09:00
namespace.c fs: Allow superblock owner to access do_remount_sb() 2018-05-24 12:02:25 -05:00
no-block.c
nsfs.c
open.c Revert "fs: fold open_check_o_direct into do_dentry_open" 2018-06-03 10:58:23 -07:00
pipe.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
pnode.c
pnode.h
posix_acl.c
proc_namespace.c
read_write.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
readdir.c
select.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
seq_file.c proc: fix smaps and meminfo alignment 2018-05-25 18:12:11 -07:00
signalfd.c Merge branch 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-16 16:21:50 +09:00
splice.c Merge branch 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-16 16:21:50 +09:00
stack.c
stat.c
statfs.c
super.c Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2018-06-04 10:14:28 -07:00
sync.c
timerfd.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
userfaultfd.c userfaultfd: remove uffd flags from vma->vm_flags if UFFD_EVENT_FORK fails 2018-08-02 16:03:40 -07:00
utimes.c
xattr.c vfs: delete unnecessary assignment in vfs_listxattr 2018-05-29 13:22:41 -04:00