btrfs: replace many BUG_ONs with proper error handling
btrfs currently handles most errors with BUG_ON. This patch is a work-in- progress but aims to handle most errors other than internal logic errors and ENOMEM more gracefully. This iteration prevents most crashes but can run into lockups with the page lock on occasion when the timing "works out." Signed-off-by: Jeff Mahoney <jeffm@suse.com>
This commit is contained in:

committed by
David Sterba

parent
49b25e0540
commit
79787eaab4
@@ -425,13 +425,18 @@ static noinline int create_subvol(struct btrfs_root *root,
|
||||
|
||||
key.offset = (u64)-1;
|
||||
new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
|
||||
BUG_ON(IS_ERR(new_root));
|
||||
if (IS_ERR(new_root)) {
|
||||
btrfs_abort_transaction(trans, root, PTR_ERR(new_root));
|
||||
ret = PTR_ERR(new_root);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
btrfs_record_root_in_trans(trans, new_root);
|
||||
|
||||
ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
|
||||
if (ret) {
|
||||
/* We potentially lose an unused inode item here */
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -439,13 +444,18 @@ static noinline int create_subvol(struct btrfs_root *root,
|
||||
* insert the directory item
|
||||
*/
|
||||
ret = btrfs_set_inode_index(dir, &index);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = btrfs_insert_dir_item(trans, root,
|
||||
name, namelen, dir, &key,
|
||||
BTRFS_FT_DIR, index);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
btrfs_i_size_write(dir, dir->i_size + namelen * 2);
|
||||
ret = btrfs_update_inode(trans, root, dir);
|
||||
@@ -1970,7 +1980,11 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
||||
dest->root_key.objectid,
|
||||
dentry->d_name.name,
|
||||
dentry->d_name.len);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
err = ret;
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
goto out_end_trans;
|
||||
}
|
||||
|
||||
btrfs_record_root_in_trans(trans, dest);
|
||||
|
||||
@@ -1983,11 +1997,16 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
||||
ret = btrfs_insert_orphan_item(trans,
|
||||
root->fs_info->tree_root,
|
||||
dest->root_key.objectid);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
err = ret;
|
||||
goto out_end_trans;
|
||||
}
|
||||
}
|
||||
|
||||
out_end_trans:
|
||||
ret = btrfs_end_transaction(trans, root);
|
||||
BUG_ON(ret);
|
||||
if (ret && !err)
|
||||
err = ret;
|
||||
inode->i_flags |= S_DEAD;
|
||||
out_up_write:
|
||||
up_write(&root->fs_info->subvol_sem);
|
||||
@@ -2451,11 +2470,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
new_key.offset,
|
||||
new_key.offset + datal,
|
||||
&hint_byte, 1);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root,
|
||||
ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path,
|
||||
&new_key, size);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root,
|
||||
ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
@@ -2482,7 +2511,15 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
btrfs_ino(inode),
|
||||
new_key.offset - datao,
|
||||
0);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans,
|
||||
root,
|
||||
ret);
|
||||
btrfs_end_transaction(trans,
|
||||
root);
|
||||
goto out;
|
||||
|
||||
}
|
||||
}
|
||||
} else if (type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
u64 skip = 0;
|
||||
@@ -2507,11 +2544,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
new_key.offset,
|
||||
new_key.offset + datal,
|
||||
&hint_byte, 1);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root,
|
||||
ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path,
|
||||
&new_key, size);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root,
|
||||
ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
u32 start =
|
||||
@@ -2545,8 +2592,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
btrfs_i_size_write(inode, endoff);
|
||||
|
||||
ret = btrfs_update_inode(trans, root, inode);
|
||||
BUG_ON(ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
goto out;
|
||||
}
|
||||
ret = btrfs_end_transaction(trans, root);
|
||||
}
|
||||
next:
|
||||
btrfs_release_path(path);
|
||||
|
Reference in New Issue
Block a user