linux-stable/fs/btrfs
Filipe Manana fdb1388994 Btrfs: incremental send, fix invalid path for unlink commands
An incremental send can contain unlink operations with an invalid target
path when we rename some directory inode A, then rename some file inode B
to the old name of inode A and directory inode A is an ancestor of inode B
in the parent snapshot (but not anymore in the send snapshot).

Consider the following example scenario where this issue happens.

Parent snapshot:

 .                                                      (ino 256)
 |
 |--- dir1/                                             (ino 257)
       |--- dir2/                                       (ino 258)
       |     |--- file1                                 (ino 259)
       |     |--- file3                                 (ino 261)
       |
       |--- dir3/                                       (ino 262)
             |--- file22                                (ino 260)
             |--- dir4/                                 (ino 263)

Send snapshot:

 .                                                      (ino 256)
 |
 |--- dir1/                                             (ino 257)
       |--- dir2/                                       (ino 258)
       |--- dir3                                        (ino 260)
       |--- file3/                                      (ino 262)
             |--- dir4/                                 (ino 263)
                   |--- file11                          (ino 269)
                   |--- file33                          (ino 261)

When attempting to apply the corresponding incremental send stream, an
unlink operation contains an invalid path which makes the receiver fail.
The following is verbose output of the btrfs receive command:

 receiving snapshot snap2 uuid=7d5450da-a573-e043-a451-ec85f4879f0f (...)
 utimes
 utimes dir1
 utimes dir1/dir2
 link dir1/dir3/dir4/file11 -> dir1/dir2/file1
 unlink dir1/dir2/file1
 utimes dir1/dir2
 truncate dir1/dir3/dir4/file11 size=0
 utimes dir1/dir3/dir4/file11
 rename dir1/dir3 -> o262-7-0
 link dir1/dir3 -> o262-7-0/file22
 unlink dir1/dir3/file22
 ERROR: unlink dir1/dir3/file22 failed. Not a directory

The following steps happen during the computation of the incremental send
stream the lead to this issue:

1) Before we start processing the new and deleted references for inode
   260, we compute the full path of the deleted reference
   ("dir1/dir3/file22") and cache it in the list of deleted references
   for our inode.

2) We then start processing the new references for inode 260, for which
   there is only one new, located at "dir1/dir3". When processing this
   new reference, we check that inode 262, which was not yet processed,
   collides with the new reference and because of that we orphanize
   inode 262 so its new full path becomes "o262-7-0".

3) After the orphanization of inode 262, we create the new reference for
   inode 260 by issuing a link command with a target path of "dir1/dir3"
   and a source path of "o262-7-0/file22".

4) We then start processing the deleted references for inode 260, for
   which there is only one with the base name of "file22", and issue
   an unlink operation containing the target path computed at step 1,
   which is wrong because that path no longer exists and should be
   replaced with "o262-7-0/file22".

So fix this issue by recomputing the full path of deleted references if
when we processed the new references for an inode we ended up orphanizing
any other inode that is an ancestor of our inode in the parent snapshot.

A test case for fstests follows soon.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
[ adjusted after prev patch removed fs_path::dir_path and dir_path_len ]
Signed-off-by: David Sterba <dsterba@suse.com>
2017-06-21 16:53:10 +02:00
..
tests Btrfs: replace tree->mapping with tree->private_data 2017-06-19 18:25:58 +02:00
acl.c posix_acl: Clear SGID bit when setting file permissions 2016-09-22 10:55:32 +02:00
async-thread.c btrfs: fix crash when tracepoint arguments are freed by wq callbacks 2017-01-09 11:24:50 +01:00
async-thread.h btrfs: limit async_work allocation and worker func duration 2016-12-13 11:01:30 -08:00
backref.c btrfs: use GFP_KERNEL in init_ipath 2017-06-19 18:26:02 +02:00
backref.h
btrfs_inode.h Btrfs: fix reported number of inode blocks 2017-04-26 16:27:26 +01:00
check-integrity.c btrfs: sink gfp parameter to btrfs_io_bio_alloc 2017-06-19 18:26:04 +02:00
check-integrity.h btrfs: take an fs_info directly when the root is not used otherwise 2016-12-06 16:06:59 +01:00
compression.c btrfs: pass bytes to btrfs_bio_alloc 2017-06-19 18:26:03 +02:00
compression.h btrfs: reduce arguments for decompress_bio ops 2017-06-19 18:26:00 +02:00
ctree.c btrfs: adjust includes after vmalloc removal 2017-06-19 18:26:02 +02:00
ctree.h btrfs: Round down values which are written for total_bytes_size 2017-06-20 14:22:48 +02:00
dedupe.h btrfs: expand cow_file_range() to support in-band dedup and subpage-blocksize 2016-07-26 13:52:25 +02:00
delayed-inode.c btrfs: convert btrfs_delayed_item.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
delayed-inode.h btrfs: convert btrfs_delayed_item.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
delayed-ref.c btrfs: convert btrfs_delayed_ref_node.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
delayed-ref.h btrfs: convert btrfs_delayed_ref_node.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
dev-replace.c Btrfs: switch to div64_u64 if with a u64 divisor 2017-04-18 14:07:26 +02:00
dev-replace.h btrfs: constify device path passed to relevant helpers 2017-02-28 14:26:07 +01:00
dir-item.c btrfs: tree-log.c: Wrong printk information about namelen 2017-06-09 12:48:07 -07:00
disk-io.c btrfs: move fs_info::fs_frozen to the flags 2017-06-20 14:22:42 +02:00
disk-io.h btrfs: btrfs_wait_tree_block_writeback can be void return 2017-06-19 18:26:01 +02:00
export.c btrfs: Make btrfs_ino take a struct btrfs_inode 2017-02-14 15:50:51 +01:00
export.h
extent-tree.c btrfs: Use btrfs_space_info_used instead of opencoding it 2017-06-19 18:26:04 +02:00
extent_io.c btrfs: sink gfp parameter to btrfs_io_bio_alloc 2017-06-19 18:26:04 +02:00
extent_io.h btrfs: sink gfp parameter to btrfs_io_bio_alloc 2017-06-19 18:26:04 +02:00
extent_map.c btrfs: convert extent_map.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
extent_map.h btrfs: convert extent_map.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
file-item.c Btrfs: change how we iterate bios in endio 2017-06-19 18:25:59 +02:00
file.c Btrfs: fix invalid extent maps due to hole punching 2017-06-21 16:52:45 +02:00
free-space-cache.c btrfs: use clear_page where appropriate 2017-04-18 14:07:26 +02:00
free-space-cache.h btrfs: free-space-cache, clean up unnecessary root arguments 2017-02-17 12:03:56 +01:00
free-space-tree.c Btrfs: use memalloc_nofs and kvzalloc() for free space tree bitmaps 2017-06-19 18:26:01 +02:00
free-space-tree.h Btrfs: implement the free space B-tree 2015-12-17 12:16:47 -08:00
hash.c crypto: Work around deallocated stack frame reference gcc bug on sparc. 2017-06-08 17:36:03 +08:00
hash.h btrfs: advertise which crc32c implementation is being used at module load 2016-06-06 14:08:28 +02:00
inode-item.c btrfs: take an fs_info directly when the root is not used otherwise 2016-12-06 16:06:59 +01:00
inode-map.c btrfs: all btrfs_delalloc_release_metadata take btrfs_inode 2017-02-28 11:30:07 +01:00
inode-map.h Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots 2016-01-15 19:25:02 +01:00
inode.c btrfs: cleanup duplicate return value in insert_inline_extent 2017-06-20 14:22:12 +02:00
ioctl.c btrfs: use GFP_KERNEL in init_ipath 2017-06-19 18:26:02 +02:00
Kconfig
locking.c btrfs: cleanup, remove stray return statements 2016-01-07 14:30:52 +01:00
locking.h
lzo.c btrfs: switch to kvmalloc and GFP_KERNEL in lzo/zlib alloc_workspace 2017-06-19 18:26:02 +02:00
Makefile Btrfs: add free space tree sanity tests 2015-12-17 12:16:47 -08:00
math.h
ordered-data.c btrfs: convert btrfs_ordered_extent.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
ordered-data.h btrfs: convert btrfs_ordered_extent.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
orphan.c
print-tree.c Btrfs: let btrfs_print_leaf print more about block group 2017-06-19 18:26:00 +02:00
print-tree.h btrfs: take an fs_info directly when the root is not used otherwise 2016-12-06 16:06:59 +01:00
props.c btrfs: Make btrfs_ino take a struct btrfs_inode 2017-02-14 15:50:51 +01:00
props.h
qgroup.c btrfs: add cond_resched to btrfs_qgroup_trace_leaf_items 2017-06-21 15:48:01 +02:00
qgroup.h btrfs: qgroup: Re-arrange tracepoint timing to co-operate with reserved space tracepoint 2017-04-18 14:07:26 +02:00
raid56.c btrfs: sink gfp parameter to btrfs_io_bio_alloc 2017-06-19 18:26:04 +02:00
raid56.h btrfs: take an fs_info directly when the root is not used otherwise 2016-12-06 16:06:59 +01:00
rcu-string.h
reada.c btrfs: remove unused member err from reada_extent 2017-06-19 18:25:59 +02:00
relocation.c Btrfs: replace tree->mapping with tree->private_data 2017-06-19 18:25:58 +02:00
root-tree.c btrfs: Use ktime_get_real_ts for root ctime 2017-04-18 14:07:27 +02:00
scrub.c btrfs: sink gfp parameter to btrfs_io_bio_alloc 2017-06-19 18:26:04 +02:00
send.c Btrfs: incremental send, fix invalid path for unlink commands 2017-06-21 16:53:10 +02:00
send.h Btrfs: use linux/sizes.h to represent constants 2016-01-07 14:38:02 +01:00
struct-funcs.c btrfs: fix string and comment grammatical issues and typos 2016-05-25 22:35:14 +02:00
super.c btrfs: obsolete and remove mount option alloc_start 2017-06-20 14:22:48 +02:00
sysfs.c btrfs: Add quota_override knob into sysfs 2017-06-19 18:25:58 +02:00
sysfs.h btrfs: sysfs: introduce helper for syncing bits with sysfs files 2016-01-21 18:50:40 +01:00
transaction.c btrfs: move fs_info::fs_frozen to the flags 2017-06-20 14:22:42 +02:00
transaction.h btrfs: remove unused qgroup members from btrfs_trans_handle 2017-04-18 14:07:25 +02:00
tree-defrag.c Btrfs: fix locking bugs when defragging leaves 2015-12-18 02:51:32 +00:00
tree-log.c btrfs: convert extent_map.refs from atomic_t to refcount_t 2017-04-18 14:07:23 +02:00
tree-log.h btrfs: Make btrfs_del_inode_ref take btrfs_inode 2017-02-14 15:50:54 +01:00
ulist.c btrfs: ulist: rename ulist_fini to ulist_release 2017-02-17 12:03:50 +01:00
ulist.h btrfs: ulist: rename ulist_fini to ulist_release 2017-02-17 12:03:50 +01:00
uuid-tree.c btrfs: return the actual error value from from btrfs_uuid_tree_iterate 2016-12-19 18:08:15 +01:00
volumes.c btrfs: Round down values which are written for total_bytes_size 2017-06-20 14:22:48 +02:00
volumes.h btrfs: document mandatory order of bio in btrfs_io_bio 2017-06-19 18:26:03 +02:00
xattr.c btrfs: fix over-80 lines introduced by previous cleanups 2017-02-14 15:50:57 +01:00
xattr.h btrfs: Switch to generic xattr handlers 2016-05-17 19:17:09 -04:00
zlib.c btrfs: switch to kvmalloc and GFP_KERNEL in lzo/zlib alloc_workspace 2017-06-19 18:26:02 +02:00