diff options
author | Chris Mason <chris.mason@oracle.com> | 2012-02-20 08:40:56 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-02-23 10:43:45 -0500 |
commit | fe66a05a06795bd3b788404d69ea7709f46a1609 (patch) | |
tree | 8d576c0c69ef44a253370bbec135efe2477d18d2 | |
parent | 692e5759a43b916f0b66bcb39b2957499992381e (diff) |
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>
-rw-r--r-- | fs/btrfs/inode.c | 20 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 13 |
2 files changed, 26 insertions, 7 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6e0ee9b0d742..cbeb2e36cebc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4585,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4585 | ret = btrfs_insert_dir_item(trans, root, name, name_len, | 4585 | ret = btrfs_insert_dir_item(trans, root, name, name_len, |
4586 | parent_inode, &key, | 4586 | parent_inode, &key, |
4587 | btrfs_inode_type(inode), index); | 4587 | btrfs_inode_type(inode), index); |
4588 | BUG_ON(ret); | 4588 | if (ret) |
4589 | goto fail_dir_item; | ||
4589 | 4590 | ||
4590 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 4591 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
4591 | name_len * 2); | 4592 | name_len * 2); |
@@ -4593,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4593 | ret = btrfs_update_inode(trans, root, parent_inode); | 4594 | ret = btrfs_update_inode(trans, root, parent_inode); |
4594 | } | 4595 | } |
4595 | return ret; | 4596 | return ret; |
4597 | |||
4598 | fail_dir_item: | ||
4599 | if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) { | ||
4600 | u64 local_index; | ||
4601 | int err; | ||
4602 | err = btrfs_del_root_ref(trans, root->fs_info->tree_root, | ||
4603 | key.objectid, root->root_key.objectid, | ||
4604 | parent_ino, &local_index, name, name_len); | ||
4605 | |||
4606 | } else if (add_backref) { | ||
4607 | u64 local_index; | ||
4608 | int err; | ||
4609 | |||
4610 | err = btrfs_del_inode_ref(trans, root, name, name_len, | ||
4611 | ino, parent_ino, &local_index); | ||
4612 | } | ||
4613 | return ret; | ||
4596 | } | 4614 | } |
4597 | 4615 | ||
4598 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | 4616 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 287a6728b1ad..016977beee5c 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -915,7 +915,11 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
915 | dentry->d_name.name, dentry->d_name.len, | 915 | dentry->d_name.name, dentry->d_name.len, |
916 | parent_inode, &key, | 916 | parent_inode, &key, |
917 | BTRFS_FT_DIR, index); | 917 | BTRFS_FT_DIR, index); |
918 | BUG_ON(ret); | 918 | if (ret) { |
919 | pending->error = -EEXIST; | ||
920 | dput(parent); | ||
921 | goto fail; | ||
922 | } | ||
919 | 923 | ||
920 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 924 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
921 | dentry->d_name.len * 2); | 925 | dentry->d_name.len * 2); |
@@ -993,12 +997,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
993 | { | 997 | { |
994 | struct btrfs_pending_snapshot *pending; | 998 | struct btrfs_pending_snapshot *pending; |
995 | struct list_head *head = &trans->transaction->pending_snapshots; | 999 | struct list_head *head = &trans->transaction->pending_snapshots; |
996 | int ret; | ||
997 | 1000 | ||
998 | list_for_each_entry(pending, head, list) { | 1001 | list_for_each_entry(pending, head, list) |
999 | ret = create_pending_snapshot(trans, fs_info, pending); | 1002 | create_pending_snapshot(trans, fs_info, pending); |
1000 | BUG_ON(ret); | ||
1001 | } | ||
1002 | return 0; | 1003 | return 0; |
1003 | } | 1004 | } |
1004 | 1005 | ||