Loading fs/btrfs/ctree.c +14 −6 Original line number Diff line number Diff line Loading @@ -80,10 +80,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, int ret = 0; int level; struct btrfs_key first_key; struct btrfs_root new_root; struct btrfs_root *new_root; memcpy(&new_root, root, sizeof(new_root)); new_root.root_key.objectid = new_root_objectid; new_root = kmalloc(sizeof(*new_root), GFP_NOFS); if (!new_root) return -ENOMEM; memcpy(new_root, root, sizeof(*new_root)); new_root->root_key.objectid = new_root_objectid; WARN_ON(root->ref_cows && trans->transid != root->fs_info->running_transaction->transid); Loading @@ -99,12 +103,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, } else { first_key.objectid = 0; } cow = __btrfs_alloc_free_block(trans, &new_root, buf->len, cow = __btrfs_alloc_free_block(trans, new_root, buf->len, new_root_objectid, trans->transid, first_key.objectid, level, buf->start, 0); if (IS_ERR(cow)) if (IS_ERR(cow)) { kfree(new_root); return PTR_ERR(cow); } copy_extent_buffer(cow, buf, 0, 0, cow->len); btrfs_set_header_bytenr(cow, cow->start); Loading @@ -112,7 +118,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, btrfs_set_header_owner(cow, new_root_objectid); WARN_ON(btrfs_header_generation(buf) > trans->transid); ret = btrfs_inc_ref(trans, &new_root, buf); ret = btrfs_inc_ref(trans, new_root, buf); kfree(new_root); if (ret) return ret; Loading fs/btrfs/inode.c +42 −18 Original line number Diff line number Diff line Loading @@ -2302,40 +2302,64 @@ int btrfs_defrag_file(struct file *file) { static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_vol_args vol_args; struct btrfs_ioctl_vol_args *vol_args; struct btrfs_dir_item *di; struct btrfs_path *path; int namelen; u64 root_dirid; int namelen; int ret; if (copy_from_user(&vol_args, arg, sizeof(vol_args))) return -EFAULT; vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); namelen = strlen(vol_args.name); if (namelen > BTRFS_VOL_NAME_MAX) return -EINVAL; if (strchr(vol_args.name, '/')) return -EINVAL; if (!vol_args) return -ENOMEM; if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { ret = -EFAULT; goto out; } namelen = strlen(vol_args->name); if (namelen > BTRFS_VOL_NAME_MAX) { ret = -EINVAL; goto out; } if (strchr(vol_args->name, '/')) { ret = -EINVAL; goto out; } path = btrfs_alloc_path(); if (!path) return -ENOMEM; if (!path) { ret = -ENOMEM; goto out; } root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, mutex_lock(&root->fs_info->fs_mutex); di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, path, root_dirid, vol_args.name, namelen, 0); vol_args->name, namelen, 0); mutex_unlock(&root->fs_info->fs_mutex); btrfs_free_path(path); if (di && !IS_ERR(di)) return -EEXIST; if (IS_ERR(di)) return PTR_ERR(di); if (di && !IS_ERR(di)) { ret = -EEXIST; goto out; } if (IS_ERR(di)) { ret = PTR_ERR(di); goto out; } if (root == root->fs_info->tree_root) return create_subvol(root, vol_args.name, namelen); return create_snapshot(root, vol_args.name, namelen); ret = create_subvol(root, vol_args->name, namelen); else ret = create_snapshot(root, vol_args->name, namelen); out: kfree(vol_args); return ret; } static int btrfs_ioctl_defrag(struct file *file) Loading Loading
fs/btrfs/ctree.c +14 −6 Original line number Diff line number Diff line Loading @@ -80,10 +80,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, int ret = 0; int level; struct btrfs_key first_key; struct btrfs_root new_root; struct btrfs_root *new_root; memcpy(&new_root, root, sizeof(new_root)); new_root.root_key.objectid = new_root_objectid; new_root = kmalloc(sizeof(*new_root), GFP_NOFS); if (!new_root) return -ENOMEM; memcpy(new_root, root, sizeof(*new_root)); new_root->root_key.objectid = new_root_objectid; WARN_ON(root->ref_cows && trans->transid != root->fs_info->running_transaction->transid); Loading @@ -99,12 +103,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, } else { first_key.objectid = 0; } cow = __btrfs_alloc_free_block(trans, &new_root, buf->len, cow = __btrfs_alloc_free_block(trans, new_root, buf->len, new_root_objectid, trans->transid, first_key.objectid, level, buf->start, 0); if (IS_ERR(cow)) if (IS_ERR(cow)) { kfree(new_root); return PTR_ERR(cow); } copy_extent_buffer(cow, buf, 0, 0, cow->len); btrfs_set_header_bytenr(cow, cow->start); Loading @@ -112,7 +118,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, btrfs_set_header_owner(cow, new_root_objectid); WARN_ON(btrfs_header_generation(buf) > trans->transid); ret = btrfs_inc_ref(trans, &new_root, buf); ret = btrfs_inc_ref(trans, new_root, buf); kfree(new_root); if (ret) return ret; Loading
fs/btrfs/inode.c +42 −18 Original line number Diff line number Diff line Loading @@ -2302,40 +2302,64 @@ int btrfs_defrag_file(struct file *file) { static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg) { struct btrfs_ioctl_vol_args vol_args; struct btrfs_ioctl_vol_args *vol_args; struct btrfs_dir_item *di; struct btrfs_path *path; int namelen; u64 root_dirid; int namelen; int ret; if (copy_from_user(&vol_args, arg, sizeof(vol_args))) return -EFAULT; vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); namelen = strlen(vol_args.name); if (namelen > BTRFS_VOL_NAME_MAX) return -EINVAL; if (strchr(vol_args.name, '/')) return -EINVAL; if (!vol_args) return -ENOMEM; if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { ret = -EFAULT; goto out; } namelen = strlen(vol_args->name); if (namelen > BTRFS_VOL_NAME_MAX) { ret = -EINVAL; goto out; } if (strchr(vol_args->name, '/')) { ret = -EINVAL; goto out; } path = btrfs_alloc_path(); if (!path) return -ENOMEM; if (!path) { ret = -ENOMEM; goto out; } root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, mutex_lock(&root->fs_info->fs_mutex); di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, path, root_dirid, vol_args.name, namelen, 0); vol_args->name, namelen, 0); mutex_unlock(&root->fs_info->fs_mutex); btrfs_free_path(path); if (di && !IS_ERR(di)) return -EEXIST; if (IS_ERR(di)) return PTR_ERR(di); if (di && !IS_ERR(di)) { ret = -EEXIST; goto out; } if (IS_ERR(di)) { ret = PTR_ERR(di); goto out; } if (root == root->fs_info->tree_root) return create_subvol(root, vol_args.name, namelen); return create_snapshot(root, vol_args.name, namelen); ret = create_subvol(root, vol_args->name, namelen); else ret = create_snapshot(root, vol_args->name, namelen); out: kfree(vol_args); return ret; } static int btrfs_ioctl_defrag(struct file *file) Loading