Commit 1ab86aed authored by Sage Weil's avatar Sage Weil Committed by Chris Mason

Btrfs: fix error cases for ioctl transactions

Fix leak of vfsmount write reference and open_ioctl_trans reference on
ENOMEM.  Clean up the error paths while we're at it.
Signed-off-by: default avatarSage Weil <sage@newdream.net>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3baf0bed
...@@ -1232,15 +1232,15 @@ static long btrfs_ioctl_trans_start(struct file *file) ...@@ -1232,15 +1232,15 @@ static long btrfs_ioctl_trans_start(struct file *file)
struct inode *inode = fdentry(file)->d_inode; struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0; int ret;
ret = -EPERM;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; goto out;
if (file->private_data) {
ret = -EINPROGRESS; ret = -EINPROGRESS;
if (file->private_data)
goto out; goto out;
}
ret = mnt_want_write(file->f_path.mnt); ret = mnt_want_write(file->f_path.mnt);
if (ret) if (ret)
...@@ -1250,12 +1250,19 @@ static long btrfs_ioctl_trans_start(struct file *file) ...@@ -1250,12 +1250,19 @@ static long btrfs_ioctl_trans_start(struct file *file)
root->fs_info->open_ioctl_trans++; root->fs_info->open_ioctl_trans++;
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
ret = -ENOMEM;
trans = btrfs_start_ioctl_transaction(root, 0); trans = btrfs_start_ioctl_transaction(root, 0);
if (trans) if (!trans)
goto out_drop;
file->private_data = trans; file->private_data = trans;
else return 0;
ret = -ENOMEM;
/*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/ out_drop:
mutex_lock(&root->fs_info->trans_mutex);
root->fs_info->open_ioctl_trans--;
mutex_unlock(&root->fs_info->trans_mutex);
mnt_drop_write(file->f_path.mnt);
out: out:
return ret; return ret;
} }
...@@ -1271,24 +1278,20 @@ long btrfs_ioctl_trans_end(struct file *file) ...@@ -1271,24 +1278,20 @@ long btrfs_ioctl_trans_end(struct file *file)
struct inode *inode = fdentry(file)->d_inode; struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0;
trans = file->private_data; trans = file->private_data;
if (!trans) { if (!trans)
ret = -EINVAL; return -EINVAL;
goto out;
}
btrfs_end_transaction(trans, root);
file->private_data = NULL; file->private_data = NULL;
btrfs_end_transaction(trans, root);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
root->fs_info->open_ioctl_trans--; root->fs_info->open_ioctl_trans--;
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
mnt_drop_write(file->f_path.mnt); mnt_drop_write(file->f_path.mnt);
return 0;
out:
return ret;
} }
long btrfs_ioctl(struct file *file, unsigned int long btrfs_ioctl(struct file *file, unsigned int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment