forked from luck/tmp_suning_uos_patched
Btrfs: improve error handling for btrfs_insert_dir_item callers
This allows us to gracefully continue if we aren't able to insert directory items, both for normal files/dirs and snapshots. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
692e5759a4
commit
fe66a05a06
|
@ -4585,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
|
|||
ret = btrfs_insert_dir_item(trans, root, name, name_len,
|
||||
parent_inode, &key,
|
||||
btrfs_inode_type(inode), index);
|
||||
BUG_ON(ret);
|
||||
if (ret)
|
||||
goto fail_dir_item;
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size +
|
||||
name_len * 2);
|
||||
|
@ -4593,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
|
|||
ret = btrfs_update_inode(trans, root, parent_inode);
|
||||
}
|
||||
return ret;
|
||||
|
||||
fail_dir_item:
|
||||
if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) {
|
||||
u64 local_index;
|
||||
int err;
|
||||
err = btrfs_del_root_ref(trans, root->fs_info->tree_root,
|
||||
key.objectid, root->root_key.objectid,
|
||||
parent_ino, &local_index, name, name_len);
|
||||
|
||||
} else if (add_backref) {
|
||||
u64 local_index;
|
||||
int err;
|
||||
|
||||
err = btrfs_del_inode_ref(trans, root, name, name_len,
|
||||
ino, parent_ino, &local_index);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
|
||||
|
|
|
@ -915,7 +915,11 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
|||
dentry->d_name.name, dentry->d_name.len,
|
||||
parent_inode, &key,
|
||||
BTRFS_FT_DIR, index);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
pending->error = -EEXIST;
|
||||
dput(parent);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size +
|
||||
dentry->d_name.len * 2);
|
||||
|
@ -993,12 +997,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
|
|||
{
|
||||
struct btrfs_pending_snapshot *pending;
|
||||
struct list_head *head = &trans->transaction->pending_snapshots;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(pending, head, list) {
|
||||
ret = create_pending_snapshot(trans, fs_info, pending);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
list_for_each_entry(pending, head, list)
|
||||
create_pending_snapshot(trans, fs_info, pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user