diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-08-13 14:10:08 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:05:03 -0400 |
commit | 4ef31a45a009a81b2f3c5aaf6f07d7147f80bc8c (patch) | |
tree | c10236f3a3ff81731aa601f6163baa3d44bad96d /fs/btrfs/inode.c | |
parent | 175a2b871f46272a2aedce5fb3222a72568b84c3 (diff) |
Btrfs: fix the error handling wrt orphan items
There are several places where we BUG_ON() if we fail to remove the orphan items
and such, which is not ok, so remove those and either abort or just carry on.
This also fixes a problem where if we couldn't start a transaction we wouldn't
actually remove the orphan item reserve for the inode. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 66571dce88d1..de7085bc28f6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2940,8 +2940,10 @@ void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, | |||
2940 | btrfs_root_refs(&root->root_item) > 0) { | 2940 | btrfs_root_refs(&root->root_item) > 0) { |
2941 | ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root, | 2941 | ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root, |
2942 | root->root_key.objectid); | 2942 | root->root_key.objectid); |
2943 | BUG_ON(ret); | 2943 | if (ret) |
2944 | root->orphan_item_inserted = 0; | 2944 | btrfs_abort_transaction(trans, root, ret); |
2945 | else | ||
2946 | root->orphan_item_inserted = 0; | ||
2945 | } | 2947 | } |
2946 | 2948 | ||
2947 | if (block_rsv) { | 2949 | if (block_rsv) { |
@@ -3010,11 +3012,18 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
3010 | /* insert an orphan item to track this unlinked/truncated file */ | 3012 | /* insert an orphan item to track this unlinked/truncated file */ |
3011 | if (insert >= 1) { | 3013 | if (insert >= 1) { |
3012 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); | 3014 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); |
3013 | if (ret && ret != -EEXIST) { | 3015 | if (ret) { |
3014 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 3016 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
3015 | &BTRFS_I(inode)->runtime_flags); | 3017 | &BTRFS_I(inode)->runtime_flags); |
3016 | btrfs_abort_transaction(trans, root, ret); | 3018 | if (reserve) { |
3017 | return ret; | 3019 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3020 | &BTRFS_I(inode)->runtime_flags); | ||
3021 | btrfs_orphan_release_metadata(inode); | ||
3022 | } | ||
3023 | if (ret != -EEXIST) { | ||
3024 | btrfs_abort_transaction(trans, root, ret); | ||
3025 | return ret; | ||
3026 | } | ||
3018 | } | 3027 | } |
3019 | ret = 0; | 3028 | ret = 0; |
3020 | } | 3029 | } |
@@ -3053,17 +3062,15 @@ static int btrfs_orphan_del(struct btrfs_trans_handle *trans, | |||
3053 | release_rsv = 1; | 3062 | release_rsv = 1; |
3054 | spin_unlock(&root->orphan_lock); | 3063 | spin_unlock(&root->orphan_lock); |
3055 | 3064 | ||
3056 | if (trans && delete_item) { | 3065 | if (trans && delete_item) |
3057 | ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode)); | 3066 | ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode)); |
3058 | BUG_ON(ret); /* -ENOMEM or corruption (JDM: Recheck) */ | ||
3059 | } | ||
3060 | 3067 | ||
3061 | if (release_rsv) { | 3068 | if (release_rsv) { |
3062 | btrfs_orphan_release_metadata(inode); | 3069 | btrfs_orphan_release_metadata(inode); |
3063 | atomic_dec(&root->orphan_inodes); | 3070 | atomic_dec(&root->orphan_inodes); |
3064 | } | 3071 | } |
3065 | 3072 | ||
3066 | return 0; | 3073 | return ret; |
3067 | } | 3074 | } |
3068 | 3075 | ||
3069 | /* | 3076 | /* |
@@ -3193,8 +3200,9 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
3193 | found_key.objectid); | 3200 | found_key.objectid); |
3194 | ret = btrfs_del_orphan_item(trans, root, | 3201 | ret = btrfs_del_orphan_item(trans, root, |
3195 | found_key.objectid); | 3202 | found_key.objectid); |
3196 | BUG_ON(ret); /* -ENOMEM or corruption (JDM: Recheck) */ | ||
3197 | btrfs_end_transaction(trans, root); | 3203 | btrfs_end_transaction(trans, root); |
3204 | if (ret) | ||
3205 | goto out; | ||
3198 | continue; | 3206 | continue; |
3199 | } | 3207 | } |
3200 | 3208 | ||
@@ -4570,10 +4578,15 @@ void btrfs_evict_inode(struct inode *inode) | |||
4570 | 4578 | ||
4571 | btrfs_free_block_rsv(root, rsv); | 4579 | btrfs_free_block_rsv(root, rsv); |
4572 | 4580 | ||
4581 | /* | ||
4582 | * Errors here aren't a big deal, it just means we leave orphan items | ||
4583 | * in the tree. They will be cleaned up on the next mount. | ||
4584 | */ | ||
4573 | if (ret == 0) { | 4585 | if (ret == 0) { |
4574 | trans->block_rsv = root->orphan_block_rsv; | 4586 | trans->block_rsv = root->orphan_block_rsv; |
4575 | ret = btrfs_orphan_del(trans, inode); | 4587 | btrfs_orphan_del(trans, inode); |
4576 | BUG_ON(ret); | 4588 | } else { |
4589 | btrfs_orphan_del(NULL, inode); | ||
4577 | } | 4590 | } |
4578 | 4591 | ||
4579 | trans->block_rsv = &root->fs_info->trans_block_rsv; | 4592 | trans->block_rsv = &root->fs_info->trans_block_rsv; |
@@ -8120,10 +8133,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
8120 | new_dentry->d_name.name, | 8133 | new_dentry->d_name.name, |
8121 | new_dentry->d_name.len); | 8134 | new_dentry->d_name.len); |
8122 | } | 8135 | } |
8123 | if (!ret && new_inode->i_nlink == 0) { | 8136 | if (!ret && new_inode->i_nlink == 0) |
8124 | ret = btrfs_orphan_add(trans, new_dentry->d_inode); | 8137 | ret = btrfs_orphan_add(trans, new_dentry->d_inode); |
8125 | BUG_ON(ret); | ||
8126 | } | ||
8127 | if (ret) { | 8138 | if (ret) { |
8128 | btrfs_abort_transaction(trans, root, ret); | 8139 | btrfs_abort_transaction(trans, root, ret); |
8129 | goto out_fail; | 8140 | goto out_fail; |