diff options
author | Josef Bacik <josef@redhat.com> | 2009-11-10 21:23:48 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-11-11 14:20:17 -0500 |
commit | 5df6a9f606bf2ee25ab8031bff124ed883b823be (patch) | |
tree | 2492876b6ebd9c4c52a50de1a431285fe3779889 | |
parent | 01dea1efc23b511d3b58bb94da07ddb6d6db9895 (diff) |
Btrfs: fix some metadata enospc issues
We weren't reserving metadata space for rename, rmdir and unlink, which could
cause problems.
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/inode.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d8393ddc72a3..bb7fd8072802 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2488,7 +2488,19 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2488 | 2488 | ||
2489 | root = BTRFS_I(dir)->root; | 2489 | root = BTRFS_I(dir)->root; |
2490 | 2490 | ||
2491 | /* | ||
2492 | * 5 items for unlink inode | ||
2493 | * 1 for orphan | ||
2494 | */ | ||
2495 | ret = btrfs_reserve_metadata_space(root, 6); | ||
2496 | if (ret) | ||
2497 | return ret; | ||
2498 | |||
2491 | trans = btrfs_start_transaction(root, 1); | 2499 | trans = btrfs_start_transaction(root, 1); |
2500 | if (IS_ERR(trans)) { | ||
2501 | btrfs_unreserve_metadata_space(root, 6); | ||
2502 | return PTR_ERR(trans); | ||
2503 | } | ||
2492 | 2504 | ||
2493 | btrfs_set_trans_block_group(trans, dir); | 2505 | btrfs_set_trans_block_group(trans, dir); |
2494 | 2506 | ||
@@ -2503,6 +2515,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2503 | nr = trans->blocks_used; | 2515 | nr = trans->blocks_used; |
2504 | 2516 | ||
2505 | btrfs_end_transaction_throttle(trans, root); | 2517 | btrfs_end_transaction_throttle(trans, root); |
2518 | btrfs_unreserve_metadata_space(root, 6); | ||
2506 | btrfs_btree_balance_dirty(root, nr); | 2519 | btrfs_btree_balance_dirty(root, nr); |
2507 | return ret; | 2520 | return ret; |
2508 | } | 2521 | } |
@@ -2583,7 +2596,16 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2583 | inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | 2596 | inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
2584 | return -ENOTEMPTY; | 2597 | return -ENOTEMPTY; |
2585 | 2598 | ||
2599 | ret = btrfs_reserve_metadata_space(root, 5); | ||
2600 | if (ret) | ||
2601 | return ret; | ||
2602 | |||
2586 | trans = btrfs_start_transaction(root, 1); | 2603 | trans = btrfs_start_transaction(root, 1); |
2604 | if (IS_ERR(trans)) { | ||
2605 | btrfs_unreserve_metadata_space(root, 5); | ||
2606 | return PTR_ERR(trans); | ||
2607 | } | ||
2608 | |||
2587 | btrfs_set_trans_block_group(trans, dir); | 2609 | btrfs_set_trans_block_group(trans, dir); |
2588 | 2610 | ||
2589 | if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { | 2611 | if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { |
@@ -2606,6 +2628,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2606 | out: | 2628 | out: |
2607 | nr = trans->blocks_used; | 2629 | nr = trans->blocks_used; |
2608 | ret = btrfs_end_transaction_throttle(trans, root); | 2630 | ret = btrfs_end_transaction_throttle(trans, root); |
2631 | btrfs_unreserve_metadata_space(root, 5); | ||
2609 | btrfs_btree_balance_dirty(root, nr); | 2632 | btrfs_btree_balance_dirty(root, nr); |
2610 | 2633 | ||
2611 | if (ret && !err) | 2634 | if (ret && !err) |
@@ -5297,11 +5320,14 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
5297 | return -ENOTEMPTY; | 5320 | return -ENOTEMPTY; |
5298 | 5321 | ||
5299 | /* | 5322 | /* |
5300 | * 2 items for dir items | 5323 | * We want to reserve the absolute worst case amount of items. So if |
5301 | * 1 item for orphan entry | 5324 | * both inodes are subvols and we need to unlink them then that would |
5302 | * 1 item for ref | 5325 | * require 4 item modifications, but if they are both normal inodes it |
5326 | * would require 5 item modifications, so we'll assume their normal | ||
5327 | * inodes. So 5 * 2 is 10, plus 1 for the new link, so 11 total items | ||
5328 | * should cover the worst case number of items we'll modify. | ||
5303 | */ | 5329 | */ |
5304 | ret = btrfs_reserve_metadata_space(root, 4); | 5330 | ret = btrfs_reserve_metadata_space(root, 11); |
5305 | if (ret) | 5331 | if (ret) |
5306 | return ret; | 5332 | return ret; |
5307 | 5333 | ||
@@ -5417,7 +5443,7 @@ out_fail: | |||
5417 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | 5443 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
5418 | up_read(&root->fs_info->subvol_sem); | 5444 | up_read(&root->fs_info->subvol_sem); |
5419 | 5445 | ||
5420 | btrfs_unreserve_metadata_space(root, 4); | 5446 | btrfs_unreserve_metadata_space(root, 11); |
5421 | return ret; | 5447 | return ret; |
5422 | } | 5448 | } |
5423 | 5449 | ||