Commit fe66a05a authored by Chris Mason's avatar Chris Mason

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: default avatarChris Mason <chris.mason@oracle.com>
parent 692e5759
...@@ -4585,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -4585,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
ret = btrfs_insert_dir_item(trans, root, name, name_len, ret = btrfs_insert_dir_item(trans, root, name, name_len,
parent_inode, &key, parent_inode, &key,
btrfs_inode_type(inode), index); btrfs_inode_type(inode), index);
BUG_ON(ret); if (ret)
goto fail_dir_item;
btrfs_i_size_write(parent_inode, parent_inode->i_size + btrfs_i_size_write(parent_inode, parent_inode->i_size +
name_len * 2); name_len * 2);
...@@ -4593,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -4593,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
ret = btrfs_update_inode(trans, root, parent_inode); ret = btrfs_update_inode(trans, root, parent_inode);
} }
return ret; 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, 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, ...@@ -915,7 +915,11 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
dentry->d_name.name, dentry->d_name.len, dentry->d_name.name, dentry->d_name.len,
parent_inode, &key, parent_inode, &key,
BTRFS_FT_DIR, index); 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 + btrfs_i_size_write(parent_inode, parent_inode->i_size +
dentry->d_name.len * 2); dentry->d_name.len * 2);
...@@ -993,12 +997,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, ...@@ -993,12 +997,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
{ {
struct btrfs_pending_snapshot *pending; struct btrfs_pending_snapshot *pending;
struct list_head *head = &trans->transaction->pending_snapshots; struct list_head *head = &trans->transaction->pending_snapshots;
int ret;
list_for_each_entry(pending, head, list) { list_for_each_entry(pending, head, list)
ret = create_pending_snapshot(trans, fs_info, pending); create_pending_snapshot(trans, fs_info, pending);
BUG_ON(ret);
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment