aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2012-03-12 11:03:00 -0400
committerDavid Sterba <dsterba@suse.cz>2012-03-22 06:52:54 -0400
commit79787eaab46121d4713ed03c8fc63b9ec3eaec76 (patch)
treeee6b17d0811ee54ab74a03aa4e0bb92769d2f12a /fs/btrfs/ioctl.c
parent49b25e0540904be0bf558b84475c69d72e4de66e (diff)
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>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c79
1 files changed, 65 insertions, 14 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index de25e4255aeb..205809200714 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -425,13 +425,18 @@ static noinline int create_subvol(struct btrfs_root *root,
425 425
426 key.offset = (u64)-1; 426 key.offset = (u64)-1;
427 new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); 427 new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
428 BUG_ON(IS_ERR(new_root)); 428 if (IS_ERR(new_root)) {
429 btrfs_abort_transaction(trans, root, PTR_ERR(new_root));
430 ret = PTR_ERR(new_root);
431 goto fail;
432 }
429 433
430 btrfs_record_root_in_trans(trans, new_root); 434 btrfs_record_root_in_trans(trans, new_root);
431 435
432 ret = btrfs_create_subvol_root(trans, new_root, new_dirid); 436 ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
433 if (ret) { 437 if (ret) {
434 /* We potentially lose an unused inode item here */ 438 /* We potentially lose an unused inode item here */
439 btrfs_abort_transaction(trans, root, ret);
435 goto fail; 440 goto fail;
436 } 441 }
437 442
@@ -439,13 +444,18 @@ static noinline int create_subvol(struct btrfs_root *root,
439 * insert the directory item 444 * insert the directory item
440 */ 445 */
441 ret = btrfs_set_inode_index(dir, &index); 446 ret = btrfs_set_inode_index(dir, &index);
442 BUG_ON(ret); 447 if (ret) {
448 btrfs_abort_transaction(trans, root, ret);
449 goto fail;
450 }
443 451
444 ret = btrfs_insert_dir_item(trans, root, 452 ret = btrfs_insert_dir_item(trans, root,
445 name, namelen, dir, &key, 453 name, namelen, dir, &key,
446 BTRFS_FT_DIR, index); 454 BTRFS_FT_DIR, index);
447 if (ret) 455 if (ret) {
456 btrfs_abort_transaction(trans, root, ret);
448 goto fail; 457 goto fail;
458 }
449 459
450 btrfs_i_size_write(dir, dir->i_size + namelen * 2); 460 btrfs_i_size_write(dir, dir->i_size + namelen * 2);
451 ret = btrfs_update_inode(trans, root, dir); 461 ret = btrfs_update_inode(trans, root, dir);
@@ -1970,7 +1980,11 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
1970 dest->root_key.objectid, 1980 dest->root_key.objectid,
1971 dentry->d_name.name, 1981 dentry->d_name.name,
1972 dentry->d_name.len); 1982 dentry->d_name.len);
1973 BUG_ON(ret); 1983 if (ret) {
1984 err = ret;
1985 btrfs_abort_transaction(trans, root, ret);
1986 goto out_end_trans;
1987 }
1974 1988
1975 btrfs_record_root_in_trans(trans, dest); 1989 btrfs_record_root_in_trans(trans, dest);
1976 1990
@@ -1983,11 +1997,16 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
1983 ret = btrfs_insert_orphan_item(trans, 1997 ret = btrfs_insert_orphan_item(trans,
1984 root->fs_info->tree_root, 1998 root->fs_info->tree_root,
1985 dest->root_key.objectid); 1999 dest->root_key.objectid);
1986 BUG_ON(ret); 2000 if (ret) {
2001 btrfs_abort_transaction(trans, root, ret);
2002 err = ret;
2003 goto out_end_trans;
2004 }
1987 } 2005 }
1988 2006out_end_trans:
1989 ret = btrfs_end_transaction(trans, root); 2007 ret = btrfs_end_transaction(trans, root);
1990 BUG_ON(ret); 2008 if (ret && !err)
2009 err = ret;
1991 inode->i_flags |= S_DEAD; 2010 inode->i_flags |= S_DEAD;
1992out_up_write: 2011out_up_write:
1993 up_write(&root->fs_info->subvol_sem); 2012 up_write(&root->fs_info->subvol_sem);
@@ -2451,11 +2470,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2451 new_key.offset, 2470 new_key.offset,
2452 new_key.offset + datal, 2471 new_key.offset + datal,
2453 &hint_byte, 1); 2472 &hint_byte, 1);
2454 BUG_ON(ret); 2473 if (ret) {
2474 btrfs_abort_transaction(trans, root,
2475 ret);
2476 btrfs_end_transaction(trans, root);
2477 goto out;
2478 }
2455 2479
2456 ret = btrfs_insert_empty_item(trans, root, path, 2480 ret = btrfs_insert_empty_item(trans, root, path,
2457 &new_key, size); 2481 &new_key, size);
2458 BUG_ON(ret); 2482 if (ret) {
2483 btrfs_abort_transaction(trans, root,
2484 ret);
2485 btrfs_end_transaction(trans, root);
2486 goto out;
2487 }
2459 2488
2460 leaf = path->nodes[0]; 2489 leaf = path->nodes[0];
2461 slot = path->slots[0]; 2490 slot = path->slots[0];
@@ -2482,7 +2511,15 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2482 btrfs_ino(inode), 2511 btrfs_ino(inode),
2483 new_key.offset - datao, 2512 new_key.offset - datao,
2484 0); 2513 0);
2485 BUG_ON(ret); 2514 if (ret) {
2515 btrfs_abort_transaction(trans,
2516 root,
2517 ret);
2518 btrfs_end_transaction(trans,
2519 root);
2520 goto out;
2521
2522 }
2486 } 2523 }
2487 } else if (type == BTRFS_FILE_EXTENT_INLINE) { 2524 } else if (type == BTRFS_FILE_EXTENT_INLINE) {
2488 u64 skip = 0; 2525 u64 skip = 0;
@@ -2507,11 +2544,21 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2507 new_key.offset, 2544 new_key.offset,
2508 new_key.offset + datal, 2545 new_key.offset + datal,
2509 &hint_byte, 1); 2546 &hint_byte, 1);
2510 BUG_ON(ret); 2547 if (ret) {
2548 btrfs_abort_transaction(trans, root,
2549 ret);
2550 btrfs_end_transaction(trans, root);
2551 goto out;
2552 }
2511 2553
2512 ret = btrfs_insert_empty_item(trans, root, path, 2554 ret = btrfs_insert_empty_item(trans, root, path,
2513 &new_key, size); 2555 &new_key, size);
2514 BUG_ON(ret); 2556 if (ret) {
2557 btrfs_abort_transaction(trans, root,
2558 ret);
2559 btrfs_end_transaction(trans, root);
2560 goto out;
2561 }
2515 2562
2516 if (skip) { 2563 if (skip) {
2517 u32 start = 2564 u32 start =
@@ -2545,8 +2592,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
2545 btrfs_i_size_write(inode, endoff); 2592 btrfs_i_size_write(inode, endoff);
2546 2593
2547 ret = btrfs_update_inode(trans, root, inode); 2594 ret = btrfs_update_inode(trans, root, inode);
2548 BUG_ON(ret); 2595 if (ret) {
2549 btrfs_end_transaction(trans, root); 2596 btrfs_abort_transaction(trans, root, ret);
2597 btrfs_end_transaction(trans, root);
2598 goto out;
2599 }
2600 ret = btrfs_end_transaction(trans, root);
2550 } 2601 }
2551next: 2602next:
2552 btrfs_release_path(path); 2603 btrfs_release_path(path);