aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-02-20 08:40:56 -0500
committerChris Mason <chris.mason@oracle.com>2012-02-23 10:43:45 -0500
commitfe66a05a06795bd3b788404d69ea7709f46a1609 (patch)
tree8d576c0c69ef44a253370bbec135efe2477d18d2
parent692e5759a43b916f0b66bcb39b2957499992381e (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.c20
-rw-r--r--fs/btrfs/transaction.c13
2 files changed, 26 insertions, 7 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6e0ee9b0d74..cbeb2e36ceb 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
4598fail_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
4598static int btrfs_add_nondir(struct btrfs_trans_handle *trans, 4616static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 287a6728b1a..016977beee5 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