aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-09-29 18:38:44 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-29 18:38:44 -0400
commit1ab86aedbc7845a946b4ba4edf37762629970708 (patch)
tree1a3ad19d12a807d76d5700abc6415e1535c88312 /fs/btrfs/ioctl.c
parent3baf0bed0a5adab95c7599d2f27124c74692ef28 (diff)
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: Sage Weil <sage@newdream.net> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4de7ef6f8603..9a780c8d0ac8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1232,15 +1232,15 @@ static long btrfs_ioctl_trans_start(struct file *file)
1232 struct inode *inode = fdentry(file)->d_inode; 1232 struct inode *inode = fdentry(file)->d_inode;
1233 struct btrfs_root *root = BTRFS_I(inode)->root; 1233 struct btrfs_root *root = BTRFS_I(inode)->root;
1234 struct btrfs_trans_handle *trans; 1234 struct btrfs_trans_handle *trans;
1235 int ret = 0; 1235 int ret;
1236 1236
1237 ret = -EPERM;
1237 if (!capable(CAP_SYS_ADMIN)) 1238 if (!capable(CAP_SYS_ADMIN))
1238 return -EPERM; 1239 goto out;
1239 1240
1240 if (file->private_data) { 1241 ret = -EINPROGRESS;
1241 ret = -EINPROGRESS; 1242 if (file->private_data)
1242 goto out; 1243 goto out;
1243 }
1244 1244
1245 ret = mnt_want_write(file->f_path.mnt); 1245 ret = mnt_want_write(file->f_path.mnt);
1246 if (ret) 1246 if (ret)
@@ -1250,12 +1250,19 @@ static long btrfs_ioctl_trans_start(struct file *file)
1250 root->fs_info->open_ioctl_trans++; 1250 root->fs_info->open_ioctl_trans++;
1251 mutex_unlock(&root->fs_info->trans_mutex); 1251 mutex_unlock(&root->fs_info->trans_mutex);
1252 1252
1253 ret = -ENOMEM;
1253 trans = btrfs_start_ioctl_transaction(root, 0); 1254 trans = btrfs_start_ioctl_transaction(root, 0);
1254 if (trans) 1255 if (!trans)
1255 file->private_data = trans; 1256 goto out_drop;
1256 else 1257
1257 ret = -ENOMEM; 1258 file->private_data = trans;
1258 /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/ 1259 return 0;
1260
1261out_drop:
1262 mutex_lock(&root->fs_info->trans_mutex);
1263 root->fs_info->open_ioctl_trans--;
1264 mutex_unlock(&root->fs_info->trans_mutex);
1265 mnt_drop_write(file->f_path.mnt);
1259out: 1266out:
1260 return ret; 1267 return ret;
1261} 1268}
@@ -1271,24 +1278,20 @@ long btrfs_ioctl_trans_end(struct file *file)
1271 struct inode *inode = fdentry(file)->d_inode; 1278 struct inode *inode = fdentry(file)->d_inode;
1272 struct btrfs_root *root = BTRFS_I(inode)->root; 1279 struct btrfs_root *root = BTRFS_I(inode)->root;
1273 struct btrfs_trans_handle *trans; 1280 struct btrfs_trans_handle *trans;
1274 int ret = 0;
1275 1281
1276 trans = file->private_data; 1282 trans = file->private_data;
1277 if (!trans) { 1283 if (!trans)
1278 ret = -EINVAL; 1284 return -EINVAL;
1279 goto out;
1280 }
1281 btrfs_end_transaction(trans, root);
1282 file->private_data = NULL; 1285 file->private_data = NULL;
1283 1286
1287 btrfs_end_transaction(trans, root);
1288
1284 mutex_lock(&root->fs_info->trans_mutex); 1289 mutex_lock(&root->fs_info->trans_mutex);
1285 root->fs_info->open_ioctl_trans--; 1290 root->fs_info->open_ioctl_trans--;
1286 mutex_unlock(&root->fs_info->trans_mutex); 1291 mutex_unlock(&root->fs_info->trans_mutex);
1287 1292
1288 mnt_drop_write(file->f_path.mnt); 1293 mnt_drop_write(file->f_path.mnt);
1289 1294 return 0;
1290out:
1291 return ret;
1292} 1295}
1293 1296
1294long btrfs_ioctl(struct file *file, unsigned int 1297long btrfs_ioctl(struct file *file, unsigned int