diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a8577a7f26ab..cdbb054102b9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -239,7 +239,13 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
239 | u64 index = 0; | 239 | u64 index = 0; |
240 | unsigned long nr = 1; | 240 | unsigned long nr = 1; |
241 | 241 | ||
242 | ret = btrfs_check_metadata_free_space(root); | 242 | /* |
243 | * 1 - inode item | ||
244 | * 2 - refs | ||
245 | * 1 - root item | ||
246 | * 2 - dir items | ||
247 | */ | ||
248 | ret = btrfs_reserve_metadata_space(root, 6); | ||
243 | if (ret) | 249 | if (ret) |
244 | return ret; | 250 | return ret; |
245 | 251 | ||
@@ -340,6 +346,9 @@ fail: | |||
340 | err = btrfs_commit_transaction(trans, root); | 346 | err = btrfs_commit_transaction(trans, root); |
341 | if (err && !ret) | 347 | if (err && !ret) |
342 | ret = err; | 348 | ret = err; |
349 | |||
350 | btrfs_unreserve_metadata_space(root, 6); | ||
351 | btrfs_btree_balance_dirty(root, nr); | ||
343 | return ret; | 352 | return ret; |
344 | } | 353 | } |
345 | 354 | ||
@@ -355,19 +364,27 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
355 | if (!root->ref_cows) | 364 | if (!root->ref_cows) |
356 | return -EINVAL; | 365 | return -EINVAL; |
357 | 366 | ||
358 | ret = btrfs_check_metadata_free_space(root); | 367 | /* |
368 | * 1 - inode item | ||
369 | * 2 - refs | ||
370 | * 1 - root item | ||
371 | * 2 - dir items | ||
372 | */ | ||
373 | ret = btrfs_reserve_metadata_space(root, 6); | ||
359 | if (ret) | 374 | if (ret) |
360 | goto fail_unlock; | 375 | goto fail_unlock; |
361 | 376 | ||
362 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | 377 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
363 | if (!pending_snapshot) { | 378 | if (!pending_snapshot) { |
364 | ret = -ENOMEM; | 379 | ret = -ENOMEM; |
380 | btrfs_unreserve_metadata_space(root, 6); | ||
365 | goto fail_unlock; | 381 | goto fail_unlock; |
366 | } | 382 | } |
367 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); | 383 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); |
368 | if (!pending_snapshot->name) { | 384 | if (!pending_snapshot->name) { |
369 | ret = -ENOMEM; | 385 | ret = -ENOMEM; |
370 | kfree(pending_snapshot); | 386 | kfree(pending_snapshot); |
387 | btrfs_unreserve_metadata_space(root, 6); | ||
371 | goto fail_unlock; | 388 | goto fail_unlock; |
372 | } | 389 | } |
373 | memcpy(pending_snapshot->name, name, namelen); | 390 | memcpy(pending_snapshot->name, name, namelen); |
@@ -813,6 +830,7 @@ out_up_write: | |||
813 | out_unlock: | 830 | out_unlock: |
814 | mutex_unlock(&inode->i_mutex); | 831 | mutex_unlock(&inode->i_mutex); |
815 | if (!err) { | 832 | if (!err) { |
833 | shrink_dcache_sb(root->fs_info->sb); | ||
816 | btrfs_invalidate_inodes(dest); | 834 | btrfs_invalidate_inodes(dest); |
817 | d_delete(dentry); | 835 | d_delete(dentry); |
818 | } | 836 | } |
@@ -1105,8 +1123,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
1105 | datao += off - key.offset; | 1123 | datao += off - key.offset; |
1106 | datal -= off - key.offset; | 1124 | datal -= off - key.offset; |
1107 | } | 1125 | } |
1108 | if (key.offset + datao + datal > off + len) | 1126 | |
1109 | datal = off + len - key.offset - datao; | 1127 | if (key.offset + datal > off + len) |
1128 | datal = off + len - key.offset; | ||
1129 | |||
1110 | /* disko == 0 means it's a hole */ | 1130 | /* disko == 0 means it's a hole */ |
1111 | if (!disko) | 1131 | if (!disko) |
1112 | datao = 0; | 1132 | datao = 0; |
@@ -1215,15 +1235,15 @@ static long btrfs_ioctl_trans_start(struct file *file) | |||
1215 | struct inode *inode = fdentry(file)->d_inode; | 1235 | struct inode *inode = fdentry(file)->d_inode; |
1216 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1236 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1217 | struct btrfs_trans_handle *trans; | 1237 | struct btrfs_trans_handle *trans; |
1218 | int ret = 0; | 1238 | int ret; |
1219 | 1239 | ||
1240 | ret = -EPERM; | ||
1220 | if (!capable(CAP_SYS_ADMIN)) | 1241 | if (!capable(CAP_SYS_ADMIN)) |
1221 | return -EPERM; | 1242 | goto out; |
1222 | 1243 | ||
1223 | if (file->private_data) { | 1244 | ret = -EINPROGRESS; |
1224 | ret = -EINPROGRESS; | 1245 | if (file->private_data) |
1225 | goto out; | 1246 | goto out; |
1226 | } | ||
1227 | 1247 | ||
1228 | ret = mnt_want_write(file->f_path.mnt); | 1248 | ret = mnt_want_write(file->f_path.mnt); |
1229 | if (ret) | 1249 | if (ret) |
@@ -1233,12 +1253,19 @@ static long btrfs_ioctl_trans_start(struct file *file) | |||
1233 | root->fs_info->open_ioctl_trans++; | 1253 | root->fs_info->open_ioctl_trans++; |
1234 | mutex_unlock(&root->fs_info->trans_mutex); | 1254 | mutex_unlock(&root->fs_info->trans_mutex); |
1235 | 1255 | ||
1256 | ret = -ENOMEM; | ||
1236 | trans = btrfs_start_ioctl_transaction(root, 0); | 1257 | trans = btrfs_start_ioctl_transaction(root, 0); |
1237 | if (trans) | 1258 | if (!trans) |
1238 | file->private_data = trans; | 1259 | goto out_drop; |
1239 | else | 1260 | |
1240 | ret = -ENOMEM; | 1261 | file->private_data = trans; |
1241 | /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/ | 1262 | return 0; |
1263 | |||
1264 | out_drop: | ||
1265 | mutex_lock(&root->fs_info->trans_mutex); | ||
1266 | root->fs_info->open_ioctl_trans--; | ||
1267 | mutex_unlock(&root->fs_info->trans_mutex); | ||
1268 | mnt_drop_write(file->f_path.mnt); | ||
1242 | out: | 1269 | out: |
1243 | return ret; | 1270 | return ret; |
1244 | } | 1271 | } |
@@ -1254,24 +1281,20 @@ long btrfs_ioctl_trans_end(struct file *file) | |||
1254 | struct inode *inode = fdentry(file)->d_inode; | 1281 | struct inode *inode = fdentry(file)->d_inode; |
1255 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1282 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1256 | struct btrfs_trans_handle *trans; | 1283 | struct btrfs_trans_handle *trans; |
1257 | int ret = 0; | ||
1258 | 1284 | ||
1259 | trans = file->private_data; | 1285 | trans = file->private_data; |
1260 | if (!trans) { | 1286 | if (!trans) |
1261 | ret = -EINVAL; | 1287 | return -EINVAL; |
1262 | goto out; | ||
1263 | } | ||
1264 | btrfs_end_transaction(trans, root); | ||
1265 | file->private_data = NULL; | 1288 | file->private_data = NULL; |
1266 | 1289 | ||
1290 | btrfs_end_transaction(trans, root); | ||
1291 | |||
1267 | mutex_lock(&root->fs_info->trans_mutex); | 1292 | mutex_lock(&root->fs_info->trans_mutex); |
1268 | root->fs_info->open_ioctl_trans--; | 1293 | root->fs_info->open_ioctl_trans--; |
1269 | mutex_unlock(&root->fs_info->trans_mutex); | 1294 | mutex_unlock(&root->fs_info->trans_mutex); |
1270 | 1295 | ||
1271 | mnt_drop_write(file->f_path.mnt); | 1296 | mnt_drop_write(file->f_path.mnt); |
1272 | 1297 | return 0; | |
1273 | out: | ||
1274 | return ret; | ||
1275 | } | 1298 | } |
1276 | 1299 | ||
1277 | long btrfs_ioctl(struct file *file, unsigned int | 1300 | long btrfs_ioctl(struct file *file, unsigned int |