diff options
author | Anand Jain <Anand.Jain@oracle.com> | 2013-07-19 05:39:32 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:04:15 -0400 |
commit | a1b83ac52d23c85581b87836c346fb5cb90f6bfd (patch) | |
tree | 2c4a8512cc3c6e8f464082b3c98c20fc98fd08ba | |
parent | d4c34f6bffe246bcf05a1471873667d678a47a54 (diff) |
btrfs: fix get set label blocking against balance
btrfs_ioctl_get_fslabel() and btrfs_ioctl_set_fslabel()
used root->fs_info->volume_mutex mutex which caused operations
like balance to block set/get label operation until its
completion and generally balance operation takes a long
time to complete, so it will be annoying to the user when
cli appears hung
also this patch will add a bit of optimization within
the btrfs_ioctl_get_falabel() function.
v1->v2:
use fs_info->super_lock instead of uuid_mutex
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f856c97952db..556b3d5b18da 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -4042,18 +4042,22 @@ out: | |||
4042 | static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) | 4042 | static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) |
4043 | { | 4043 | { |
4044 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; | 4044 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
4045 | const char *label = root->fs_info->super_copy->label; | 4045 | size_t len; |
4046 | size_t len = strnlen(label, BTRFS_LABEL_SIZE); | ||
4047 | int ret; | 4046 | int ret; |
4047 | char label[BTRFS_LABEL_SIZE]; | ||
4048 | |||
4049 | spin_lock(&root->fs_info->super_lock); | ||
4050 | memcpy(label, root->fs_info->super_copy->label, BTRFS_LABEL_SIZE); | ||
4051 | spin_unlock(&root->fs_info->super_lock); | ||
4052 | |||
4053 | len = strnlen(label, BTRFS_LABEL_SIZE); | ||
4048 | 4054 | ||
4049 | if (len == BTRFS_LABEL_SIZE) { | 4055 | if (len == BTRFS_LABEL_SIZE) { |
4050 | pr_warn("btrfs: label is too long, return the first %zu bytes\n", | 4056 | pr_warn("btrfs: label is too long, return the first %zu bytes\n", |
4051 | --len); | 4057 | --len); |
4052 | } | 4058 | } |
4053 | 4059 | ||
4054 | mutex_lock(&root->fs_info->volume_mutex); | ||
4055 | ret = copy_to_user(arg, label, len); | 4060 | ret = copy_to_user(arg, label, len); |
4056 | mutex_unlock(&root->fs_info->volume_mutex); | ||
4057 | 4061 | ||
4058 | return ret ? -EFAULT : 0; | 4062 | return ret ? -EFAULT : 0; |
4059 | } | 4063 | } |
@@ -4082,18 +4086,18 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | |||
4082 | if (ret) | 4086 | if (ret) |
4083 | return ret; | 4087 | return ret; |
4084 | 4088 | ||
4085 | mutex_lock(&root->fs_info->volume_mutex); | ||
4086 | trans = btrfs_start_transaction(root, 0); | 4089 | trans = btrfs_start_transaction(root, 0); |
4087 | if (IS_ERR(trans)) { | 4090 | if (IS_ERR(trans)) { |
4088 | ret = PTR_ERR(trans); | 4091 | ret = PTR_ERR(trans); |
4089 | goto out_unlock; | 4092 | goto out_unlock; |
4090 | } | 4093 | } |
4091 | 4094 | ||
4095 | spin_lock(&root->fs_info->super_lock); | ||
4092 | strcpy(super_block->label, label); | 4096 | strcpy(super_block->label, label); |
4097 | spin_unlock(&root->fs_info->super_lock); | ||
4093 | ret = btrfs_end_transaction(trans, root); | 4098 | ret = btrfs_end_transaction(trans, root); |
4094 | 4099 | ||
4095 | out_unlock: | 4100 | out_unlock: |
4096 | mutex_unlock(&root->fs_info->volume_mutex); | ||
4097 | mnt_drop_write_file(file); | 4101 | mnt_drop_write_file(file); |
4098 | return ret; | 4102 | return ret; |
4099 | } | 4103 | } |