btrfs: delayed-inode: Kill the BUG_ON() in btrfs_delete_delayed_dir_index()
There is one report of fuzzed image which leads to BUG_ON() in btrfs_delete_delayed_dir_index(). Although that fuzzed image can already be addressed by enhanced extent-tree error handler, it's still better to hunt down more BUG_ON(). This patch will hunt down two BUG_ON()s in btrfs_delete_delayed_dir_index(): - One for error from btrfs_delayed_item_reserve_metadata() Instead of BUG_ON(), we output an error message and free the item. And return the error. All callers of this function handles the error by aborting current trasaction. - One for possible EEXIST from __btrfs_add_delayed_deletion_item() That function can return -EEXIST. We already have a good enough error message for that, only need to clean up the reserved metadata space and allocated item. To help above cleanup, also modifiy __btrfs_remove_delayed_item() called in btrfs_release_delayed_item(), to skip unassociated item. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203253 Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
112974d406
commit
933c22a751
|
@ -474,6 +474,9 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
|
||||||
struct rb_root_cached *root;
|
struct rb_root_cached *root;
|
||||||
struct btrfs_delayed_root *delayed_root;
|
struct btrfs_delayed_root *delayed_root;
|
||||||
|
|
||||||
|
/* Not associated with any delayed_node */
|
||||||
|
if (!delayed_item->delayed_node)
|
||||||
|
return;
|
||||||
delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root;
|
delayed_root = delayed_item->delayed_node->root->fs_info->delayed_root;
|
||||||
|
|
||||||
BUG_ON(!delayed_root);
|
BUG_ON(!delayed_root);
|
||||||
|
@ -1525,7 +1528,12 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
|
||||||
* we have reserved enough space when we start a new transaction,
|
* we have reserved enough space when we start a new transaction,
|
||||||
* so reserving metadata failure is impossible.
|
* so reserving metadata failure is impossible.
|
||||||
*/
|
*/
|
||||||
BUG_ON(ret);
|
if (ret < 0) {
|
||||||
|
btrfs_err(trans->fs_info,
|
||||||
|
"metadata reservation failed for delayed dir item deltiona, should have been reserved");
|
||||||
|
btrfs_release_delayed_item(item);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock(&node->mutex);
|
mutex_lock(&node->mutex);
|
||||||
ret = __btrfs_add_delayed_deletion_item(node, item);
|
ret = __btrfs_add_delayed_deletion_item(node, item);
|
||||||
|
@ -1534,7 +1542,8 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans,
|
||||||
"err add delayed dir index item(index: %llu) into the deletion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)",
|
"err add delayed dir index item(index: %llu) into the deletion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)",
|
||||||
index, node->root->root_key.objectid,
|
index, node->root->root_key.objectid,
|
||||||
node->inode_id, ret);
|
node->inode_id, ret);
|
||||||
BUG();
|
btrfs_delayed_item_release_metadata(dir->root, item);
|
||||||
|
btrfs_release_delayed_item(item);
|
||||||
}
|
}
|
||||||
mutex_unlock(&node->mutex);
|
mutex_unlock(&node->mutex);
|
||||||
end:
|
end:
|
||||||
|
|
Loading…
Reference in New Issue