aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2011-08-01 12:11:57 -0400
committerAlexander Block <ablock84@googlemail.com>2012-07-25 11:33:09 -0400
commit362a20c5e27614739c46707d1c5f55c214d164ce (patch)
tree82be478b5d25808ea823bcee1efccbfbec05840b /fs/btrfs
parent28a33cbc24e4256c143dce96c7d93bf423229f92 (diff)
btrfs: allow cross-subvolume file clone
Lift the EXDEV condition and allow different root trees for files being cloned, then pass source inode's root when searching for extents. Cloning is not allowed to cross vfsmounts, ie. when two subvolumes from one filesystem are mounted separately. Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ioctl.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0e92e5763005..7011871c45b8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2340,6 +2340,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2340 goto out_drop_write; 2340 goto out_drop_write;
2341 } 2341 }
2342 2342
2343 ret = -EXDEV;
2344 if (src_file->f_path.mnt != file->f_path.mnt)
2345 goto out_fput;
2346
2343 src = src_file->f_dentry->d_inode; 2347 src = src_file->f_dentry->d_inode;
2344 2348
2345 ret = -EINVAL; 2349 ret = -EINVAL;
@@ -2360,7 +2364,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2360 goto out_fput; 2364 goto out_fput;
2361 2365
2362 ret = -EXDEV; 2366 ret = -EXDEV;
2363 if (src->i_sb != inode->i_sb || BTRFS_I(src)->root != root) 2367 if (src->i_sb != inode->i_sb)
2364 goto out_fput; 2368 goto out_fput;
2365 2369
2366 ret = -ENOMEM; 2370 ret = -ENOMEM;
@@ -2434,13 +2438,14 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2434 * note the key will change type as we walk through the 2438 * note the key will change type as we walk through the
2435 * tree. 2439 * tree.
2436 */ 2440 */
2437 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 2441 ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
2442 0, 0);
2438 if (ret < 0) 2443 if (ret < 0)
2439 goto out; 2444 goto out;
2440 2445
2441 nritems = btrfs_header_nritems(path->nodes[0]); 2446 nritems = btrfs_header_nritems(path->nodes[0]);
2442 if (path->slots[0] >= nritems) { 2447 if (path->slots[0] >= nritems) {
2443 ret = btrfs_next_leaf(root, path); 2448 ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
2444 if (ret < 0) 2449 if (ret < 0)
2445 goto out; 2450 goto out;
2446 if (ret > 0) 2451 if (ret > 0)