Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (62 commits) Btrfs: use larger system chunks Btrfs: add a delalloc mutex to inodes for delalloc reservations Btrfs: space leak tracepoints Btrfs: protect orphan block rsv with spin_lock Btrfs: add allocator tracepoints Btrfs: don't call btrfs_throttle in file write Btrfs: release space on error in page_mkwrite Btrfs: fix btrfsck error 400 when truncating a compressed Btrfs: do not use btrfs_end_transaction_throttle everywhere Btrfs: add balance progress reporting Btrfs: allow for resuming restriper after it was paused Btrfs: allow for canceling restriper Btrfs: allow for pausing restriper Btrfs: add skip_balance mount option Btrfs: recover balance on mount Btrfs: save balance parameters to disk Btrfs: soft profile changing mode (aka soft convert) Btrfs: implement online profile changing Btrfs: do not reduce profile in do_chunk_alloc() Btrfs: virtual address space subset filter ... Fix up trivial conflict in fs/btrfs/ioctl.c due to the use of the new mnt_drop_write_file() helper.
This commit is contained in:
261
fs/btrfs/ioctl.c
261
fs/btrfs/ioctl.c
@@ -176,6 +176,8 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
|
||||
struct btrfs_trans_handle *trans;
|
||||
unsigned int flags, oldflags;
|
||||
int ret;
|
||||
u64 ip_oldflags;
|
||||
unsigned int i_oldflags;
|
||||
|
||||
if (btrfs_root_readonly(root))
|
||||
return -EROFS;
|
||||
@@ -192,6 +194,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
|
||||
ip_oldflags = ip->flags;
|
||||
i_oldflags = inode->i_flags;
|
||||
|
||||
flags = btrfs_mask_flags(inode->i_mode, flags);
|
||||
oldflags = btrfs_flags_to_ioctl(ip->flags);
|
||||
if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
|
||||
@@ -249,19 +254,24 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
|
||||
ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
|
||||
}
|
||||
|
||||
trans = btrfs_join_transaction(root);
|
||||
BUG_ON(IS_ERR(trans));
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
goto out_drop;
|
||||
}
|
||||
|
||||
btrfs_update_iflags(inode);
|
||||
inode->i_ctime = CURRENT_TIME;
|
||||
ret = btrfs_update_inode(trans, root, inode);
|
||||
BUG_ON(ret);
|
||||
|
||||
btrfs_end_transaction(trans, root);
|
||||
out_drop:
|
||||
if (ret) {
|
||||
ip->flags = ip_oldflags;
|
||||
inode->i_flags = i_oldflags;
|
||||
}
|
||||
|
||||
mnt_drop_write_file(file);
|
||||
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return ret;
|
||||
@@ -358,7 +368,7 @@ static noinline int create_subvol(struct btrfs_root *root,
|
||||
return PTR_ERR(trans);
|
||||
|
||||
leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
|
||||
0, objectid, NULL, 0, 0, 0);
|
||||
0, objectid, NULL, 0, 0, 0, 0);
|
||||
if (IS_ERR(leaf)) {
|
||||
ret = PTR_ERR(leaf);
|
||||
goto fail;
|
||||
@@ -858,10 +868,8 @@ static int cluster_pages_for_defrag(struct inode *inode,
|
||||
return 0;
|
||||
file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
ret = btrfs_delalloc_reserve_space(inode,
|
||||
num_pages << PAGE_CACHE_SHIFT);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
again:
|
||||
@@ -1203,13 +1211,21 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&root->fs_info->volume_mutex);
|
||||
if (root->fs_info->balance_ctl) {
|
||||
printk(KERN_INFO "btrfs: balance in progress\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args = memdup_user(arg, sizeof(*vol_args));
|
||||
if (IS_ERR(vol_args))
|
||||
return PTR_ERR(vol_args);
|
||||
if (IS_ERR(vol_args)) {
|
||||
ret = PTR_ERR(vol_args);
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
|
||||
|
||||
mutex_lock(&root->fs_info->volume_mutex);
|
||||
sizestr = vol_args->name;
|
||||
devstr = strchr(sizestr, ':');
|
||||
if (devstr) {
|
||||
@@ -1226,7 +1242,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
|
||||
(unsigned long long)devid);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
if (!strcmp(sizestr, "max"))
|
||||
new_size = device->bdev->bd_inode->i_size;
|
||||
@@ -1241,7 +1257,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
new_size = memparse(sizestr, NULL);
|
||||
if (new_size == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1250,7 +1266,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
if (mod < 0) {
|
||||
if (new_size > old_size) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
new_size = old_size - new_size;
|
||||
} else if (mod > 0) {
|
||||
@@ -1259,11 +1275,11 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
|
||||
if (new_size < 256 * 1024 * 1024) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
if (new_size > device->bdev->bd_inode->i_size) {
|
||||
ret = -EFBIG;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
do_div(new_size, root->sectorsize);
|
||||
@@ -1276,7 +1292,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
ret = PTR_ERR(trans);
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
ret = btrfs_grow_device(trans, device, new_size);
|
||||
btrfs_commit_transaction(trans, root);
|
||||
@@ -1284,9 +1300,10 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
|
||||
ret = btrfs_shrink_device(device, new_size);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&root->fs_info->volume_mutex);
|
||||
out_free:
|
||||
kfree(vol_args);
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->volume_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2052,14 +2069,25 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&root->fs_info->volume_mutex);
|
||||
if (root->fs_info->balance_ctl) {
|
||||
printk(KERN_INFO "btrfs: balance in progress\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args = memdup_user(arg, sizeof(*vol_args));
|
||||
if (IS_ERR(vol_args))
|
||||
return PTR_ERR(vol_args);
|
||||
if (IS_ERR(vol_args)) {
|
||||
ret = PTR_ERR(vol_args);
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
|
||||
ret = btrfs_init_new_device(root, vol_args->name);
|
||||
|
||||
kfree(vol_args);
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->volume_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2074,14 +2102,25 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
|
||||
if (root->fs_info->sb->s_flags & MS_RDONLY)
|
||||
return -EROFS;
|
||||
|
||||
mutex_lock(&root->fs_info->volume_mutex);
|
||||
if (root->fs_info->balance_ctl) {
|
||||
printk(KERN_INFO "btrfs: balance in progress\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args = memdup_user(arg, sizeof(*vol_args));
|
||||
if (IS_ERR(vol_args))
|
||||
return PTR_ERR(vol_args);
|
||||
if (IS_ERR(vol_args)) {
|
||||
ret = PTR_ERR(vol_args);
|
||||
goto out;
|
||||
}
|
||||
|
||||
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
|
||||
ret = btrfs_rm_device(root, vol_args->name);
|
||||
|
||||
kfree(vol_args);
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->volume_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2427,7 +2466,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
disko, diskl, 0,
|
||||
root->root_key.objectid,
|
||||
btrfs_ino(inode),
|
||||
new_key.offset - datao);
|
||||
new_key.offset - datao,
|
||||
0);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
} else if (type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
@@ -2977,7 +3017,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
|
||||
{
|
||||
int ret = 0;
|
||||
int size;
|
||||
u64 extent_offset;
|
||||
u64 extent_item_pos;
|
||||
struct btrfs_ioctl_logical_ino_args *loi;
|
||||
struct btrfs_data_container *inodes = NULL;
|
||||
struct btrfs_path *path = NULL;
|
||||
@@ -3008,15 +3048,17 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
|
||||
}
|
||||
|
||||
ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
|
||||
ret = -ENOENT;
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
extent_offset = loi->logical - key.objectid;
|
||||
extent_item_pos = loi->logical - key.objectid;
|
||||
ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
|
||||
extent_offset, build_ino_list, inodes);
|
||||
extent_item_pos, build_ino_list,
|
||||
inodes);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -3034,6 +3076,163 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
|
||||
struct btrfs_ioctl_balance_args *bargs)
|
||||
{
|
||||
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
|
||||
|
||||
bargs->flags = bctl->flags;
|
||||
|
||||
if (atomic_read(&fs_info->balance_running))
|
||||
bargs->state |= BTRFS_BALANCE_STATE_RUNNING;
|
||||
if (atomic_read(&fs_info->balance_pause_req))
|
||||
bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ;
|
||||
if (atomic_read(&fs_info->balance_cancel_req))
|
||||
bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;
|
||||
|
||||
memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
|
||||
memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
|
||||
memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys));
|
||||
|
||||
if (lock) {
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
} else {
|
||||
memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
|
||||
}
|
||||
}
|
||||
|
||||
static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct btrfs_ioctl_balance_args *bargs;
|
||||
struct btrfs_balance_control *bctl;
|
||||
int ret;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (fs_info->sb->s_flags & MS_RDONLY)
|
||||
return -EROFS;
|
||||
|
||||
mutex_lock(&fs_info->volume_mutex);
|
||||
mutex_lock(&fs_info->balance_mutex);
|
||||
|
||||
if (arg) {
|
||||
bargs = memdup_user(arg, sizeof(*bargs));
|
||||
if (IS_ERR(bargs)) {
|
||||
ret = PTR_ERR(bargs);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bargs->flags & BTRFS_BALANCE_RESUME) {
|
||||
if (!fs_info->balance_ctl) {
|
||||
ret = -ENOTCONN;
|
||||
goto out_bargs;
|
||||
}
|
||||
|
||||
bctl = fs_info->balance_ctl;
|
||||
spin_lock(&fs_info->balance_lock);
|
||||
bctl->flags |= BTRFS_BALANCE_RESUME;
|
||||
spin_unlock(&fs_info->balance_lock);
|
||||
|
||||
goto do_balance;
|
||||
}
|
||||
} else {
|
||||
bargs = NULL;
|
||||
}
|
||||
|
||||
if (fs_info->balance_ctl) {
|
||||
ret = -EINPROGRESS;
|
||||
goto out_bargs;
|
||||
}
|
||||
|
||||
bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
|
||||
if (!bctl) {
|
||||
ret = -ENOMEM;
|
||||
goto out_bargs;
|
||||
}
|
||||
|
||||
bctl->fs_info = fs_info;
|
||||
if (arg) {
|
||||
memcpy(&bctl->data, &bargs->data, sizeof(bctl->data));
|
||||
memcpy(&bctl->meta, &bargs->meta, sizeof(bctl->meta));
|
||||
memcpy(&bctl->sys, &bargs->sys, sizeof(bctl->sys));
|
||||
|
||||
bctl->flags = bargs->flags;
|
||||
} else {
|
||||
/* balance everything - no filters */
|
||||
bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
|
||||
}
|
||||
|
||||
do_balance:
|
||||
ret = btrfs_balance(bctl, bargs);
|
||||
/*
|
||||
* bctl is freed in __cancel_balance or in free_fs_info if
|
||||
* restriper was paused all the way until unmount
|
||||
*/
|
||||
if (arg) {
|
||||
if (copy_to_user(arg, bargs, sizeof(*bargs)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
out_bargs:
|
||||
kfree(bargs);
|
||||
out:
|
||||
mutex_unlock(&fs_info->balance_mutex);
|
||||
mutex_unlock(&fs_info->volume_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
switch (cmd) {
|
||||
case BTRFS_BALANCE_CTL_PAUSE:
|
||||
return btrfs_pause_balance(root->fs_info);
|
||||
case BTRFS_BALANCE_CTL_CANCEL:
|
||||
return btrfs_cancel_balance(root->fs_info);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long btrfs_ioctl_balance_progress(struct btrfs_root *root,
|
||||
void __user *arg)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct btrfs_ioctl_balance_args *bargs;
|
||||
int ret = 0;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&fs_info->balance_mutex);
|
||||
if (!fs_info->balance_ctl) {
|
||||
ret = -ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bargs = kzalloc(sizeof(*bargs), GFP_NOFS);
|
||||
if (!bargs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
update_ioctl_balance_args(fs_info, 1, bargs);
|
||||
|
||||
if (copy_to_user(arg, bargs, sizeof(*bargs)))
|
||||
ret = -EFAULT;
|
||||
|
||||
kfree(bargs);
|
||||
out:
|
||||
mutex_unlock(&fs_info->balance_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long btrfs_ioctl(struct file *file, unsigned int
|
||||
cmd, unsigned long arg)
|
||||
{
|
||||
@@ -3078,7 +3277,7 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
case BTRFS_IOC_DEV_INFO:
|
||||
return btrfs_ioctl_dev_info(root, argp);
|
||||
case BTRFS_IOC_BALANCE:
|
||||
return btrfs_balance(root->fs_info->dev_root);
|
||||
return btrfs_ioctl_balance(root, NULL);
|
||||
case BTRFS_IOC_CLONE:
|
||||
return btrfs_ioctl_clone(file, arg, 0, 0, 0);
|
||||
case BTRFS_IOC_CLONE_RANGE:
|
||||
@@ -3110,6 +3309,12 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
return btrfs_ioctl_scrub_cancel(root, argp);
|
||||
case BTRFS_IOC_SCRUB_PROGRESS:
|
||||
return btrfs_ioctl_scrub_progress(root, argp);
|
||||
case BTRFS_IOC_BALANCE_V2:
|
||||
return btrfs_ioctl_balance(root, argp);
|
||||
case BTRFS_IOC_BALANCE_CTL:
|
||||
return btrfs_ioctl_balance_ctl(root, arg);
|
||||
case BTRFS_IOC_BALANCE_PROGRESS:
|
||||
return btrfs_ioctl_balance_progress(root, argp);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
Reference in New Issue
Block a user