diff options
author | Josef Bacik <josef@redhat.com> | 2011-08-05 13:22:24 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-10-19 15:12:33 -0400 |
commit | 4289a667a0d7c6b134898cac7bfbe950267c305c (patch) | |
tree | 2a0564c4d33dc7f56eb7c1b0671885d5dbb79381 /fs/btrfs/inode.c | |
parent | 37be25bcb6d731914e126f8de59c4367f0d66b80 (diff) |
Btrfs: fix how we reserve space for deleting inodes
I converted btrfs_truncate to do sane reservations for truncate, but didn't
convert btrfs_evict_inode. Basically we need to save the orphan_rsv for
deleting the orphan item, and do normal reservations for our truncate. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6402a41b9023..fe3891e240b3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3527,6 +3527,8 @@ void btrfs_evict_inode(struct inode *inode) | |||
3527 | { | 3527 | { |
3528 | struct btrfs_trans_handle *trans; | 3528 | struct btrfs_trans_handle *trans; |
3529 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3529 | struct btrfs_root *root = BTRFS_I(inode)->root; |
3530 | struct btrfs_block_rsv *rsv; | ||
3531 | u64 min_size = btrfs_calc_trans_metadata_size(root, 2); | ||
3530 | unsigned long nr; | 3532 | unsigned long nr; |
3531 | int ret; | 3533 | int ret; |
3532 | 3534 | ||
@@ -3554,22 +3556,44 @@ void btrfs_evict_inode(struct inode *inode) | |||
3554 | goto no_delete; | 3556 | goto no_delete; |
3555 | } | 3557 | } |
3556 | 3558 | ||
3559 | rsv = btrfs_alloc_block_rsv(root); | ||
3560 | if (!rsv) { | ||
3561 | btrfs_orphan_del(NULL, inode); | ||
3562 | goto no_delete; | ||
3563 | } | ||
3564 | |||
3557 | btrfs_i_size_write(inode, 0); | 3565 | btrfs_i_size_write(inode, 0); |
3558 | 3566 | ||
3567 | /* | ||
3568 | * This is a bit simpler than btrfs_truncate since | ||
3569 | * | ||
3570 | * 1) We've already reserved our space for our orphan item in the | ||
3571 | * unlink. | ||
3572 | * 2) We're going to delete the inode item, so we don't need to update | ||
3573 | * it at all. | ||
3574 | * | ||
3575 | * So we just need to reserve some slack space in case we add bytes when | ||
3576 | * doing the truncate. | ||
3577 | */ | ||
3559 | while (1) { | 3578 | while (1) { |
3560 | trans = btrfs_join_transaction(root); | 3579 | ret = btrfs_block_rsv_check(NULL, root, rsv, min_size, 0); |
3561 | BUG_ON(IS_ERR(trans)); | ||
3562 | trans->block_rsv = root->orphan_block_rsv; | ||
3563 | |||
3564 | ret = btrfs_block_rsv_check(trans, root, | ||
3565 | root->orphan_block_rsv, 0, 5); | ||
3566 | if (ret) { | 3580 | if (ret) { |
3567 | BUG_ON(ret != -EAGAIN); | 3581 | printk(KERN_WARNING "Could not get space for a " |
3568 | ret = btrfs_commit_transaction(trans, root); | 3582 | "delete, will truncate on mount\n"); |
3569 | BUG_ON(ret); | 3583 | btrfs_orphan_del(NULL, inode); |
3570 | continue; | 3584 | btrfs_free_block_rsv(root, rsv); |
3585 | goto no_delete; | ||
3586 | } | ||
3587 | |||
3588 | trans = btrfs_start_transaction(root, 0); | ||
3589 | if (IS_ERR(trans)) { | ||
3590 | btrfs_orphan_del(NULL, inode); | ||
3591 | btrfs_free_block_rsv(root, rsv); | ||
3592 | goto no_delete; | ||
3571 | } | 3593 | } |
3572 | 3594 | ||
3595 | trans->block_rsv = rsv; | ||
3596 | |||
3573 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); | 3597 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); |
3574 | if (ret != -EAGAIN) | 3598 | if (ret != -EAGAIN) |
3575 | break; | 3599 | break; |
@@ -3578,14 +3602,17 @@ void btrfs_evict_inode(struct inode *inode) | |||
3578 | btrfs_end_transaction(trans, root); | 3602 | btrfs_end_transaction(trans, root); |
3579 | trans = NULL; | 3603 | trans = NULL; |
3580 | btrfs_btree_balance_dirty(root, nr); | 3604 | btrfs_btree_balance_dirty(root, nr); |
3581 | |||
3582 | } | 3605 | } |
3583 | 3606 | ||
3607 | btrfs_free_block_rsv(root, rsv); | ||
3608 | |||
3584 | if (ret == 0) { | 3609 | if (ret == 0) { |
3610 | trans->block_rsv = root->orphan_block_rsv; | ||
3585 | ret = btrfs_orphan_del(trans, inode); | 3611 | ret = btrfs_orphan_del(trans, inode); |
3586 | BUG_ON(ret); | 3612 | BUG_ON(ret); |
3587 | } | 3613 | } |
3588 | 3614 | ||
3615 | trans->block_rsv = &root->fs_info->trans_block_rsv; | ||
3589 | if (!(root == root->fs_info->tree_root || | 3616 | if (!(root == root->fs_info->tree_root || |
3590 | root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)) | 3617 | root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID)) |
3591 | btrfs_return_ino(root, btrfs_ino(inode)); | 3618 | btrfs_return_ino(root, btrfs_ino(inode)); |