aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c114
1 files changed, 108 insertions, 6 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 3f3cbe928a1..43f0012016e 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. */
58static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) 60static 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
3609static 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
3683out:
3684 kfree(sa);
3685 up_write(&root->fs_info->subvol_sem);
3686 mnt_drop_write_file(file);
3687 return ret;
3688}
3689
3592long btrfs_ioctl(struct file *file, unsigned int 3690long 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: