Merge branch 'send-v2' of git://github.com/ablock84/linux-btrfs into for-linus
authorChris Mason <chris.mason@fusionio.com>
Wed, 25 Jul 2012 23:17:39 +0000 (19:17 -0400)
committerChris Mason <chris.mason@fusionio.com>
Wed, 25 Jul 2012 23:19:10 +0000 (19:19 -0400)
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>
1  2 
fs/btrfs/Makefile
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/transaction.c

index 0bc4d3a10a5fe631b6a85873a6b44b72f6bce4c6,f740644bb5a5e8753c4084a95fc0b5b1d442138a..d7fcdba141a2f2508999003344008458c2cf48ea
@@@ -8,7 -8,7 +8,7 @@@ btrfs-y += super.o ctree.o extent-tree.
           extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
           export.o tree-log.o free-space-cache.o zlib.o lzo.o \
           compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
-          reada.o backref.o ulist.o qgroup.o
 -         reada.o backref.o ulist.o send.o
++         reada.o backref.o ulist.o qgroup.o send.o
  
  btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
  btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
Simple merge
index 3a1ad3e2dcb05caeff5de53a56c18496e0922698,1a765792fbf2c91fd1b3690ea70676a4b7f315c0..032f4dc7eab82f9ba5e17497e0062d5556451698
@@@ -58,7 -59,11 +59,10 @@@ int paths_from_inode(u64 inum, struct i
  
  int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
                                struct btrfs_fs_info *fs_info, u64 bytenr,
 -                              u64 delayed_ref_seq, u64 time_seq,
 -                              struct ulist **roots);
 +                              u64 time_seq, struct ulist **roots);
+ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                        struct btrfs_inode_ref *iref, struct extent_buffer *eb,
+                        u64 parent, char *dest, u32 size);
  
  struct btrfs_data_container *init_data_container(u32 total_bytes);
  struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
Simple merge
Simple merge
Simple merge
index 144f4642b2a9596bf5d83a6dd9f9aa2b102207b8,4ffc8738954557c0317e9a425623f08dfb6497b9..dac1fc21d8090d7687f5b75b5e6416ddddf54bc7
@@@ -2732,8 -2732,10 +2732,10 @@@ noinline int btrfs_update_inode(struct 
         * The data relocation inode should also be directly updated
         * without delay
         */
 -      if (!btrfs_is_free_space_inode(root, inode)
 +      if (!btrfs_is_free_space_inode(inode)
            && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
+               btrfs_update_root_times(trans, root);
                ret = btrfs_delayed_update_inode(trans, root, inode);
                if (!ret)
                        btrfs_set_inode_last_trans(trans, inode);
index 3f3cbe928a1ab5e05bd8147d0833992994c493bd,bca6997fdb8086bc3825750f0cd7438512518246..43f0012016e3e6291cb79579a60940f52ec94a9c
        return ret;
  }
  
 +static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg)
 +{
 +      struct btrfs_ioctl_quota_ctl_args *sa;
 +      struct btrfs_trans_handle *trans = NULL;
 +      int ret;
 +      int err;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      if (root->fs_info->sb->s_flags & MS_RDONLY)
 +              return -EROFS;
 +
 +      sa = memdup_user(arg, sizeof(*sa));
 +      if (IS_ERR(sa))
 +              return PTR_ERR(sa);
 +
 +      if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) {
 +              trans = btrfs_start_transaction(root, 2);
 +              if (IS_ERR(trans)) {
 +                      ret = PTR_ERR(trans);
 +                      goto out;
 +              }
 +      }
 +
 +      switch (sa->cmd) {
 +      case BTRFS_QUOTA_CTL_ENABLE:
 +              ret = btrfs_quota_enable(trans, root->fs_info);
 +              break;
 +      case BTRFS_QUOTA_CTL_DISABLE:
 +              ret = btrfs_quota_disable(trans, root->fs_info);
 +              break;
 +      case BTRFS_QUOTA_CTL_RESCAN:
 +              ret = btrfs_quota_rescan(root->fs_info);
 +              break;
 +      default:
 +              ret = -EINVAL;
 +              break;
 +      }
 +
 +      if (copy_to_user(arg, sa, sizeof(*sa)))
 +              ret = -EFAULT;
 +
 +      if (trans) {
 +              err = btrfs_commit_transaction(trans, root);
 +              if (err && !ret)
 +                      ret = err;
 +      }
 +
 +out:
 +      kfree(sa);
 +      return ret;
 +}
 +
 +static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg)
 +{
 +      struct btrfs_ioctl_qgroup_assign_args *sa;
 +      struct btrfs_trans_handle *trans;
 +      int ret;
 +      int err;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      if (root->fs_info->sb->s_flags & MS_RDONLY)
 +              return -EROFS;
 +
 +      sa = memdup_user(arg, sizeof(*sa));
 +      if (IS_ERR(sa))
 +              return PTR_ERR(sa);
 +
 +      trans = btrfs_join_transaction(root);
 +      if (IS_ERR(trans)) {
 +              ret = PTR_ERR(trans);
 +              goto out;
 +      }
 +
 +      /* FIXME: check if the IDs really exist */
 +      if (sa->assign) {
 +              ret = btrfs_add_qgroup_relation(trans, root->fs_info,
 +                                              sa->src, sa->dst);
 +      } else {
 +              ret = btrfs_del_qgroup_relation(trans, root->fs_info,
 +                                              sa->src, sa->dst);
 +      }
 +
 +      err = btrfs_end_transaction(trans, root);
 +      if (err && !ret)
 +              ret = err;
 +
 +out:
 +      kfree(sa);
 +      return ret;
 +}
 +
 +static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg)
 +{
 +      struct btrfs_ioctl_qgroup_create_args *sa;
 +      struct btrfs_trans_handle *trans;
 +      int ret;
 +      int err;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      if (root->fs_info->sb->s_flags & MS_RDONLY)
 +              return -EROFS;
 +
 +      sa = memdup_user(arg, sizeof(*sa));
 +      if (IS_ERR(sa))
 +              return PTR_ERR(sa);
 +
 +      trans = btrfs_join_transaction(root);
 +      if (IS_ERR(trans)) {
 +              ret = PTR_ERR(trans);
 +              goto out;
 +      }
 +
 +      /* FIXME: check if the IDs really exist */
 +      if (sa->create) {
 +              ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid,
 +                                        NULL);
 +      } else {
 +              ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid);
 +      }
 +
 +      err = btrfs_end_transaction(trans, root);
 +      if (err && !ret)
 +              ret = err;
 +
 +out:
 +      kfree(sa);
 +      return ret;
 +}
 +
 +static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg)
 +{
 +      struct btrfs_ioctl_qgroup_limit_args *sa;
 +      struct btrfs_trans_handle *trans;
 +      int ret;
 +      int err;
 +      u64 qgroupid;
 +
 +      if (!capable(CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      if (root->fs_info->sb->s_flags & MS_RDONLY)
 +              return -EROFS;
 +
 +      sa = memdup_user(arg, sizeof(*sa));
 +      if (IS_ERR(sa))
 +              return PTR_ERR(sa);
 +
 +      trans = btrfs_join_transaction(root);
 +      if (IS_ERR(trans)) {
 +              ret = PTR_ERR(trans);
 +              goto out;
 +      }
 +
 +      qgroupid = sa->qgroupid;
 +      if (!qgroupid) {
 +              /* take the current subvol as qgroup */
 +              qgroupid = root->root_key.objectid;
 +      }
 +
 +      /* FIXME: check if the IDs really exist */
 +      ret = btrfs_limit_qgroup(trans, root->fs_info, qgroupid, &sa->lim);
 +
 +      err = btrfs_end_transaction(trans, root);
 +      if (err && !ret)
 +              ret = err;
 +
 +out:
 +      kfree(sa);
 +      return ret;
 +}
 +
+ static long btrfs_ioctl_set_received_subvol(struct file *file,
+                                           void __user *arg)
+ {
+       struct btrfs_ioctl_received_subvol_args *sa = NULL;
+       struct inode *inode = fdentry(file)->d_inode;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_root_item *root_item = &root->root_item;
+       struct btrfs_trans_handle *trans;
+       struct timespec ct = CURRENT_TIME;
+       int ret = 0;
+       ret = mnt_want_write_file(file);
+       if (ret < 0)
+               return ret;
+       down_write(&root->fs_info->subvol_sem);
+       if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (btrfs_root_readonly(root)) {
+               ret = -EROFS;
+               goto out;
+       }
+       if (!inode_owner_or_capable(inode)) {
+               ret = -EACCES;
+               goto out;
+       }
+       sa = memdup_user(arg, sizeof(*sa));
+       if (IS_ERR(sa)) {
+               ret = PTR_ERR(sa);
+               sa = NULL;
+               goto out;
+       }
+       trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               trans = NULL;
+               goto out;
+       }
+       sa->rtransid = trans->transid;
+       sa->rtime.sec = ct.tv_sec;
+       sa->rtime.nsec = ct.tv_nsec;
+       memcpy(root_item->received_uuid, sa->uuid, BTRFS_UUID_SIZE);
+       btrfs_set_root_stransid(root_item, sa->stransid);
+       btrfs_set_root_rtransid(root_item, sa->rtransid);
+       root_item->stime.sec = cpu_to_le64(sa->stime.sec);
+       root_item->stime.nsec = cpu_to_le32(sa->stime.nsec);
+       root_item->rtime.sec = cpu_to_le64(sa->rtime.sec);
+       root_item->rtime.nsec = cpu_to_le32(sa->rtime.nsec);
+       ret = btrfs_update_root(trans, root->fs_info->tree_root,
+                               &root->root_key, &root->root_item);
+       if (ret < 0) {
+               btrfs_end_transaction(trans, root);
+               trans = NULL;
+               goto out;
+       } else {
+               ret = btrfs_commit_transaction(trans, root);
+               if (ret < 0)
+                       goto out;
+       }
+       ret = copy_to_user(arg, sa, sizeof(*sa));
+       if (ret)
+               ret = -EFAULT;
+ out:
+       kfree(sa);
+       up_write(&root->fs_info->subvol_sem);
+       mnt_drop_write_file(file);
+       return ret;
+ }
  long btrfs_ioctl(struct file *file, unsigned int
                cmd, unsigned long arg)
  {
                return btrfs_ioctl_balance_ctl(root, arg);
        case BTRFS_IOC_BALANCE_PROGRESS:
                return btrfs_ioctl_balance_progress(root, argp);
+       case BTRFS_IOC_SET_RECEIVED_SUBVOL:
+               return btrfs_ioctl_set_received_subvol(file, argp);
+       case BTRFS_IOC_SEND:
+               return btrfs_ioctl_send(file, argp);
        case BTRFS_IOC_GET_DEV_STATS:
 -              return btrfs_ioctl_get_dev_stats(root, argp, 0);
 -      case BTRFS_IOC_GET_AND_RESET_DEV_STATS:
 -              return btrfs_ioctl_get_dev_stats(root, argp, 1);
 +              return btrfs_ioctl_get_dev_stats(root, argp);
 +      case BTRFS_IOC_QUOTA_CTL:
 +              return btrfs_ioctl_quota_ctl(root, argp);
 +      case BTRFS_IOC_QGROUP_ASSIGN:
 +              return btrfs_ioctl_qgroup_assign(root, argp);
 +      case BTRFS_IOC_QGROUP_CREATE:
 +              return btrfs_ioctl_qgroup_create(root, argp);
 +      case BTRFS_IOC_QGROUP_LIMIT:
 +              return btrfs_ioctl_qgroup_limit(root, argp);
        }
  
        return -ENOTTY;
index 3f9701d571ea39f8251f7c3fc2139244293111a8,27097e8bfa39e470e4671af41db7170436bc11a8..731e2875ab93900b0f623797642f371b2f042e2f
@@@ -330,24 -295,29 +330,47 @@@ struct btrfs_ioctl_get_dev_stats 
        __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
  };
  
 +#define BTRFS_QUOTA_CTL_ENABLE        1
 +#define BTRFS_QUOTA_CTL_DISABLE       2
 +#define BTRFS_QUOTA_CTL_RESCAN        3
 +struct btrfs_ioctl_quota_ctl_args {
 +      __u64 cmd;
 +      __u64 status;
 +};
 +
 +struct btrfs_ioctl_qgroup_assign_args {
 +      __u64 assign;
 +      __u64 src;
 +      __u64 dst;
 +};
 +
 +struct btrfs_ioctl_qgroup_create_args {
 +      __u64 create;
 +      __u64 qgroupid;
 +};
+ struct btrfs_ioctl_timespec {
+       __u64 sec;
+       __u32 nsec;
+ };
+ struct btrfs_ioctl_received_subvol_args {
+       char    uuid[BTRFS_UUID_SIZE];  /* in */
+       __u64   stransid;               /* in */
+       __u64   rtransid;               /* out */
+       struct btrfs_ioctl_timespec stime; /* in */
+       struct btrfs_ioctl_timespec rtime; /* out */
+       __u64   flags;                  /* in */
+       __u64   reserved[16];           /* in */
+ };
+ struct btrfs_ioctl_send_args {
+       __s64 send_fd;                  /* in */
+       __u64 clone_sources_count;      /* in */
+       __u64 __user *clone_sources;    /* in */
+       __u64 parent_root;              /* in */
+       __u64 flags;                    /* in */
+       __u64 reserved[4];              /* in */
+ };
  
  #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
                                   struct btrfs_ioctl_vol_args)
                                        struct btrfs_ioctl_ino_path_args)
  #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
                                        struct btrfs_ioctl_ino_path_args)
+ #define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \
+                               struct btrfs_ioctl_received_subvol_args)
+ #define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args)
 +#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \
 +                                   struct btrfs_ioctl_vol_args)
 +#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \
 +                             struct btrfs_ioctl_quota_ctl_args)
 +#define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \
 +                             struct btrfs_ioctl_qgroup_assign_args)
 +#define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \
 +                             struct btrfs_ioctl_qgroup_create_args)
 +#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \
 +                             struct btrfs_ioctl_qgroup_limit_args)
  #define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
                                      struct btrfs_ioctl_get_dev_stats)
 -#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \
 -                                      struct btrfs_ioctl_get_dev_stats)
 -
  #endif
Simple merge