diff options
author | Chris Mason <chris.mason@fusionio.com> | 2012-07-25 19:17:39 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-07-25 19:19:10 -0400 |
commit | 113c1cb530e10bcada93d88ffaa6b521aae2d251 (patch) | |
tree | e41776281314eb8fdc6b07e1533491e5f9ec21af /fs/btrfs/ioctl.c | |
parent | cd1cfc49153ba2bef247e500d8bd4d135193ece9 (diff) | |
parent | 31db9f7c23fbf7e95026143f79645de6507b583b (diff) |
Merge branch 'send-v2' of git://github.com/ablock84/linux-btrfs into for-linus
This is the kernel portion of btrfs send/receive
Conflicts:
fs/btrfs/Makefile
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 114 |
1 files changed, 108 insertions, 6 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 3f3cbe928a1a..43f0012016e3 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/blkdev.h> | 43 | #include <linux/blkdev.h> |
44 | #include <linux/uuid.h> | ||
44 | #include "compat.h" | 45 | #include "compat.h" |
45 | #include "ctree.h" | 46 | #include "ctree.h" |
46 | #include "disk-io.h" | 47 | #include "disk-io.h" |
@@ -53,6 +54,7 @@ | |||
53 | #include "inode-map.h" | 54 | #include "inode-map.h" |
54 | #include "backref.h" | 55 | #include "backref.h" |
55 | #include "rcu-string.h" | 56 | #include "rcu-string.h" |
57 | #include "send.h" | ||
56 | 58 | ||
57 | /* Mask out flags that are inappropriate for the given type of inode. */ | 59 | /* Mask out flags that are inappropriate for the given type of inode. */ |
58 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 60 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
@@ -347,11 +349,13 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
347 | struct btrfs_root *new_root; | 349 | struct btrfs_root *new_root; |
348 | struct dentry *parent = dentry->d_parent; | 350 | struct dentry *parent = dentry->d_parent; |
349 | struct inode *dir; | 351 | struct inode *dir; |
352 | struct timespec cur_time = CURRENT_TIME; | ||
350 | int ret; | 353 | int ret; |
351 | int err; | 354 | int err; |
352 | u64 objectid; | 355 | u64 objectid; |
353 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 356 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
354 | u64 index = 0; | 357 | u64 index = 0; |
358 | uuid_le new_uuid; | ||
355 | 359 | ||
356 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); | 360 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); |
357 | if (ret) | 361 | if (ret) |
@@ -395,8 +399,9 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
395 | BTRFS_UUID_SIZE); | 399 | BTRFS_UUID_SIZE); |
396 | btrfs_mark_buffer_dirty(leaf); | 400 | btrfs_mark_buffer_dirty(leaf); |
397 | 401 | ||
402 | memset(&root_item, 0, sizeof(root_item)); | ||
403 | |||
398 | inode_item = &root_item.inode; | 404 | inode_item = &root_item.inode; |
399 | memset(inode_item, 0, sizeof(*inode_item)); | ||
400 | inode_item->generation = cpu_to_le64(1); | 405 | inode_item->generation = cpu_to_le64(1); |
401 | inode_item->size = cpu_to_le64(3); | 406 | inode_item->size = cpu_to_le64(3); |
402 | inode_item->nlink = cpu_to_le32(1); | 407 | inode_item->nlink = cpu_to_le32(1); |
@@ -414,8 +419,15 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
414 | btrfs_set_root_used(&root_item, leaf->len); | 419 | btrfs_set_root_used(&root_item, leaf->len); |
415 | btrfs_set_root_last_snapshot(&root_item, 0); | 420 | btrfs_set_root_last_snapshot(&root_item, 0); |
416 | 421 | ||
417 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | 422 | btrfs_set_root_generation_v2(&root_item, |
418 | root_item.drop_level = 0; | 423 | btrfs_root_generation(&root_item)); |
424 | uuid_le_gen(&new_uuid); | ||
425 | memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE); | ||
426 | root_item.otime.sec = cpu_to_le64(cur_time.tv_sec); | ||
427 | root_item.otime.nsec = cpu_to_le64(cur_time.tv_nsec); | ||
428 | root_item.ctime = root_item.otime; | ||
429 | btrfs_set_root_ctransid(&root_item, trans->transid); | ||
430 | btrfs_set_root_otransid(&root_item, trans->transid); | ||
419 | 431 | ||
420 | btrfs_tree_unlock(leaf); | 432 | btrfs_tree_unlock(leaf); |
421 | free_extent_buffer(leaf); | 433 | free_extent_buffer(leaf); |
@@ -2370,6 +2382,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2370 | goto out_drop_write; | 2382 | goto out_drop_write; |
2371 | } | 2383 | } |
2372 | 2384 | ||
2385 | ret = -EXDEV; | ||
2386 | if (src_file->f_path.mnt != file->f_path.mnt) | ||
2387 | goto out_fput; | ||
2388 | |||
2373 | src = src_file->f_dentry->d_inode; | 2389 | src = src_file->f_dentry->d_inode; |
2374 | 2390 | ||
2375 | ret = -EINVAL; | 2391 | ret = -EINVAL; |
@@ -2390,7 +2406,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2390 | goto out_fput; | 2406 | goto out_fput; |
2391 | 2407 | ||
2392 | ret = -EXDEV; | 2408 | ret = -EXDEV; |
2393 | if (src->i_sb != inode->i_sb || BTRFS_I(src)->root != root) | 2409 | if (src->i_sb != inode->i_sb) |
2394 | goto out_fput; | 2410 | goto out_fput; |
2395 | 2411 | ||
2396 | ret = -ENOMEM; | 2412 | ret = -ENOMEM; |
@@ -2464,13 +2480,14 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2464 | * note the key will change type as we walk through the | 2480 | * note the key will change type as we walk through the |
2465 | * tree. | 2481 | * tree. |
2466 | */ | 2482 | */ |
2467 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 2483 | ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path, |
2484 | 0, 0); | ||
2468 | if (ret < 0) | 2485 | if (ret < 0) |
2469 | goto out; | 2486 | goto out; |
2470 | 2487 | ||
2471 | nritems = btrfs_header_nritems(path->nodes[0]); | 2488 | nritems = btrfs_header_nritems(path->nodes[0]); |
2472 | if (path->slots[0] >= nritems) { | 2489 | if (path->slots[0] >= nritems) { |
2473 | ret = btrfs_next_leaf(root, path); | 2490 | ret = btrfs_next_leaf(BTRFS_I(src)->root, path); |
2474 | if (ret < 0) | 2491 | if (ret < 0) |
2475 | goto out; | 2492 | goto out; |
2476 | if (ret > 0) | 2493 | if (ret > 0) |
@@ -3589,6 +3606,87 @@ out: | |||
3589 | return ret; | 3606 | return ret; |
3590 | } | 3607 | } |
3591 | 3608 | ||
3609 | static long btrfs_ioctl_set_received_subvol(struct file *file, | ||
3610 | void __user *arg) | ||
3611 | { | ||
3612 | struct btrfs_ioctl_received_subvol_args *sa = NULL; | ||
3613 | struct inode *inode = fdentry(file)->d_inode; | ||
3614 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
3615 | struct btrfs_root_item *root_item = &root->root_item; | ||
3616 | struct btrfs_trans_handle *trans; | ||
3617 | struct timespec ct = CURRENT_TIME; | ||
3618 | int ret = 0; | ||
3619 | |||
3620 | ret = mnt_want_write_file(file); | ||
3621 | if (ret < 0) | ||
3622 | return ret; | ||
3623 | |||
3624 | down_write(&root->fs_info->subvol_sem); | ||
3625 | |||
3626 | if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { | ||
3627 | ret = -EINVAL; | ||
3628 | goto out; | ||
3629 | } | ||
3630 | |||
3631 | if (btrfs_root_readonly(root)) { | ||
3632 | ret = -EROFS; | ||
3633 | goto out; | ||
3634 | } | ||
3635 | |||
3636 | if (!inode_owner_or_capable(inode)) { | ||
3637 | ret = -EACCES; | ||
3638 | goto out; | ||
3639 | } | ||
3640 | |||
3641 | sa = memdup_user(arg, sizeof(*sa)); | ||
3642 | if (IS_ERR(sa)) { | ||
3643 | ret = PTR_ERR(sa); | ||
3644 | sa = NULL; | ||
3645 | goto out; | ||
3646 | } | ||
3647 | |||
3648 | trans = btrfs_start_transaction(root, 1); | ||
3649 | if (IS_ERR(trans)) { | ||
3650 | ret = PTR_ERR(trans); | ||
3651 | trans = NULL; | ||
3652 | goto out; | ||
3653 | } | ||
3654 | |||
3655 | sa->rtransid = trans->transid; | ||
3656 | sa->rtime.sec = ct.tv_sec; | ||
3657 | sa->rtime.nsec = ct.tv_nsec; | ||
3658 | |||
3659 | memcpy(root_item->received_uuid, sa->uuid, BTRFS_UUID_SIZE); | ||
3660 | btrfs_set_root_stransid(root_item, sa->stransid); | ||
3661 | btrfs_set_root_rtransid(root_item, sa->rtransid); | ||
3662 | root_item->stime.sec = cpu_to_le64(sa->stime.sec); | ||
3663 | root_item->stime.nsec = cpu_to_le32(sa->stime.nsec); | ||
3664 | root_item->rtime.sec = cpu_to_le64(sa->rtime.sec); | ||
3665 | root_item->rtime.nsec = cpu_to_le32(sa->rtime.nsec); | ||
3666 | |||
3667 | ret = btrfs_update_root(trans, root->fs_info->tree_root, | ||
3668 | &root->root_key, &root->root_item); | ||
3669 | if (ret < 0) { | ||
3670 | btrfs_end_transaction(trans, root); | ||
3671 | trans = NULL; | ||
3672 | goto out; | ||
3673 | } else { | ||
3674 | ret = btrfs_commit_transaction(trans, root); | ||
3675 | if (ret < 0) | ||
3676 | goto out; | ||
3677 | } | ||
3678 | |||
3679 | ret = copy_to_user(arg, sa, sizeof(*sa)); | ||
3680 | if (ret) | ||
3681 | ret = -EFAULT; | ||
3682 | |||
3683 | out: | ||
3684 | kfree(sa); | ||
3685 | up_write(&root->fs_info->subvol_sem); | ||
3686 | mnt_drop_write_file(file); | ||
3687 | return ret; | ||
3688 | } | ||
3689 | |||
3592 | long btrfs_ioctl(struct file *file, unsigned int | 3690 | long btrfs_ioctl(struct file *file, unsigned int |
3593 | cmd, unsigned long arg) | 3691 | cmd, unsigned long arg) |
3594 | { | 3692 | { |
@@ -3673,6 +3771,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3673 | return btrfs_ioctl_balance_ctl(root, arg); | 3771 | return btrfs_ioctl_balance_ctl(root, arg); |
3674 | case BTRFS_IOC_BALANCE_PROGRESS: | 3772 | case BTRFS_IOC_BALANCE_PROGRESS: |
3675 | return btrfs_ioctl_balance_progress(root, argp); | 3773 | return btrfs_ioctl_balance_progress(root, argp); |
3774 | case BTRFS_IOC_SET_RECEIVED_SUBVOL: | ||
3775 | return btrfs_ioctl_set_received_subvol(file, argp); | ||
3776 | case BTRFS_IOC_SEND: | ||
3777 | return btrfs_ioctl_send(file, argp); | ||
3676 | case BTRFS_IOC_GET_DEV_STATS: | 3778 | case BTRFS_IOC_GET_DEV_STATS: |
3677 | return btrfs_ioctl_get_dev_stats(root, argp); | 3779 | return btrfs_ioctl_get_dev_stats(root, argp); |
3678 | case BTRFS_IOC_QUOTA_CTL: | 3780 | case BTRFS_IOC_QUOTA_CTL: |