aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-11-10 21:23:48 -0500
committerChris Mason <chris.mason@oracle.com>2009-11-11 14:20:17 -0500
commit5df6a9f606bf2ee25ab8031bff124ed883b823be (patch)
tree2492876b6ebd9c4c52a50de1a431285fe3779889 /fs
parent01dea1efc23b511d3b58bb94da07ddb6d6db9895 (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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c36
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)
2606out: 2628out:
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