diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index cdbb054102b9..645a17927a8f 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -237,7 +237,6 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 237 | u64 objectid; | 237 | u64 objectid; |
| 238 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 238 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
| 239 | u64 index = 0; | 239 | u64 index = 0; |
| 240 | unsigned long nr = 1; | ||
| 241 | 240 | ||
| 242 | /* | 241 | /* |
| 243 | * 1 - inode item | 242 | * 1 - inode item |
| @@ -290,7 +289,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 290 | btrfs_set_root_generation(&root_item, trans->transid); | 289 | btrfs_set_root_generation(&root_item, trans->transid); |
| 291 | btrfs_set_root_level(&root_item, 0); | 290 | btrfs_set_root_level(&root_item, 0); |
| 292 | btrfs_set_root_refs(&root_item, 1); | 291 | btrfs_set_root_refs(&root_item, 1); |
| 293 | btrfs_set_root_used(&root_item, 0); | 292 | btrfs_set_root_used(&root_item, leaf->len); |
| 294 | btrfs_set_root_last_snapshot(&root_item, 0); | 293 | btrfs_set_root_last_snapshot(&root_item, 0); |
| 295 | 294 | ||
| 296 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); | 295 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); |
| @@ -342,24 +341,21 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 342 | 341 | ||
| 343 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | 342 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); |
| 344 | fail: | 343 | fail: |
| 345 | nr = trans->blocks_used; | ||
| 346 | err = btrfs_commit_transaction(trans, root); | 344 | err = btrfs_commit_transaction(trans, root); |
| 347 | if (err && !ret) | 345 | if (err && !ret) |
| 348 | ret = err; | 346 | ret = err; |
| 349 | 347 | ||
| 350 | btrfs_unreserve_metadata_space(root, 6); | 348 | btrfs_unreserve_metadata_space(root, 6); |
| 351 | btrfs_btree_balance_dirty(root, nr); | ||
| 352 | return ret; | 349 | return ret; |
| 353 | } | 350 | } |
| 354 | 351 | ||
| 355 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | 352 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, |
| 356 | char *name, int namelen) | 353 | char *name, int namelen) |
| 357 | { | 354 | { |
| 355 | struct inode *inode; | ||
| 358 | struct btrfs_pending_snapshot *pending_snapshot; | 356 | struct btrfs_pending_snapshot *pending_snapshot; |
| 359 | struct btrfs_trans_handle *trans; | 357 | struct btrfs_trans_handle *trans; |
| 360 | int ret = 0; | 358 | int ret; |
| 361 | int err; | ||
| 362 | unsigned long nr = 0; | ||
| 363 | 359 | ||
| 364 | if (!root->ref_cows) | 360 | if (!root->ref_cows) |
| 365 | return -EINVAL; | 361 | return -EINVAL; |
| @@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 372 | */ | 368 | */ |
| 373 | ret = btrfs_reserve_metadata_space(root, 6); | 369 | ret = btrfs_reserve_metadata_space(root, 6); |
| 374 | if (ret) | 370 | if (ret) |
| 375 | goto fail_unlock; | 371 | goto fail; |
| 376 | 372 | ||
| 377 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | 373 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
| 378 | if (!pending_snapshot) { | 374 | if (!pending_snapshot) { |
| 379 | ret = -ENOMEM; | 375 | ret = -ENOMEM; |
| 380 | btrfs_unreserve_metadata_space(root, 6); | 376 | btrfs_unreserve_metadata_space(root, 6); |
| 381 | goto fail_unlock; | 377 | goto fail; |
| 382 | } | 378 | } |
| 383 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); | 379 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); |
| 384 | if (!pending_snapshot->name) { | 380 | if (!pending_snapshot->name) { |
| 385 | ret = -ENOMEM; | 381 | ret = -ENOMEM; |
| 386 | kfree(pending_snapshot); | 382 | kfree(pending_snapshot); |
| 387 | btrfs_unreserve_metadata_space(root, 6); | 383 | btrfs_unreserve_metadata_space(root, 6); |
| 388 | goto fail_unlock; | 384 | goto fail; |
| 389 | } | 385 | } |
| 390 | memcpy(pending_snapshot->name, name, namelen); | 386 | memcpy(pending_snapshot->name, name, namelen); |
| 391 | pending_snapshot->name[namelen] = '\0'; | 387 | pending_snapshot->name[namelen] = '\0'; |
| @@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 395 | pending_snapshot->root = root; | 391 | pending_snapshot->root = root; |
| 396 | list_add(&pending_snapshot->list, | 392 | list_add(&pending_snapshot->list, |
| 397 | &trans->transaction->pending_snapshots); | 393 | &trans->transaction->pending_snapshots); |
| 398 | err = btrfs_commit_transaction(trans, root); | 394 | ret = btrfs_commit_transaction(trans, root); |
| 395 | BUG_ON(ret); | ||
| 396 | btrfs_unreserve_metadata_space(root, 6); | ||
| 399 | 397 | ||
| 400 | fail_unlock: | 398 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); |
| 401 | btrfs_btree_balance_dirty(root, nr); | 399 | if (IS_ERR(inode)) { |
| 400 | ret = PTR_ERR(inode); | ||
| 401 | goto fail; | ||
| 402 | } | ||
| 403 | BUG_ON(!inode); | ||
| 404 | d_instantiate(dentry, inode); | ||
| 405 | ret = 0; | ||
| 406 | fail: | ||
| 402 | return ret; | 407 | return ret; |
| 403 | } | 408 | } |
| 404 | 409 | ||
| @@ -1027,8 +1032,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1027 | BUG_ON(!trans); | 1032 | BUG_ON(!trans); |
| 1028 | 1033 | ||
| 1029 | /* punch hole in destination first */ | 1034 | /* punch hole in destination first */ |
| 1030 | btrfs_drop_extents(trans, root, inode, off, off + len, | 1035 | btrfs_drop_extents(trans, inode, off, off + len, &hint_byte, 1); |
| 1031 | off + len, 0, &hint_byte, 1); | ||
| 1032 | 1036 | ||
| 1033 | /* clone data */ | 1037 | /* clone data */ |
| 1034 | key.objectid = src->i_ino; | 1038 | key.objectid = src->i_ino; |
