diff options
author | Chris Mason <chris.mason@fusionio.com> | 2013-03-06 19:46:29 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-03-06 19:46:29 -0500 |
commit | 2cc65e3e57d636a159d92945655b1574e47dba63 (patch) | |
tree | a86ebdd6cb7c7cfbf1d4a547df6254a1a9849ff1 /fs | |
parent | 154ea2893002618bc3f9a1e2d8186c65490968b1 (diff) | |
parent | 9b53157aac7366cea413ee29b629f83225829e87 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next into for-linus-3.9
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/disk-io.c | 16 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 18 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 74 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 65 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 5 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 9 |
6 files changed, 120 insertions, 67 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 02369a3c162e..7d84651e850b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -62,7 +62,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | |||
62 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); | 62 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); |
63 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | 63 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, |
64 | struct btrfs_root *root); | 64 | struct btrfs_root *root); |
65 | static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t); | 65 | static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t); |
66 | static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); | 66 | static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); |
67 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, | 67 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, |
68 | struct extent_io_tree *dirty_pages, | 68 | struct extent_io_tree *dirty_pages, |
@@ -3687,7 +3687,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
3687 | return ret; | 3687 | return ret; |
3688 | } | 3688 | } |
3689 | 3689 | ||
3690 | static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) | 3690 | static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t) |
3691 | { | 3691 | { |
3692 | struct btrfs_pending_snapshot *snapshot; | 3692 | struct btrfs_pending_snapshot *snapshot; |
3693 | struct list_head splice; | 3693 | struct list_head splice; |
@@ -3700,10 +3700,8 @@ static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) | |||
3700 | snapshot = list_entry(splice.next, | 3700 | snapshot = list_entry(splice.next, |
3701 | struct btrfs_pending_snapshot, | 3701 | struct btrfs_pending_snapshot, |
3702 | list); | 3702 | list); |
3703 | 3703 | snapshot->error = -ECANCELED; | |
3704 | list_del_init(&snapshot->list); | 3704 | list_del_init(&snapshot->list); |
3705 | |||
3706 | kfree(snapshot); | ||
3707 | } | 3705 | } |
3708 | } | 3706 | } |
3709 | 3707 | ||
@@ -3840,6 +3838,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
3840 | cur_trans->blocked = 1; | 3838 | cur_trans->blocked = 1; |
3841 | wake_up(&root->fs_info->transaction_blocked_wait); | 3839 | wake_up(&root->fs_info->transaction_blocked_wait); |
3842 | 3840 | ||
3841 | btrfs_evict_pending_snapshots(cur_trans); | ||
3842 | |||
3843 | cur_trans->blocked = 0; | 3843 | cur_trans->blocked = 0; |
3844 | wake_up(&root->fs_info->transaction_wait); | 3844 | wake_up(&root->fs_info->transaction_wait); |
3845 | 3845 | ||
@@ -3849,8 +3849,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
3849 | btrfs_destroy_delayed_inodes(root); | 3849 | btrfs_destroy_delayed_inodes(root); |
3850 | btrfs_assert_delayed_root_empty(root); | 3850 | btrfs_assert_delayed_root_empty(root); |
3851 | 3851 | ||
3852 | btrfs_destroy_pending_snapshots(cur_trans); | ||
3853 | |||
3854 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, | 3852 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, |
3855 | EXTENT_DIRTY); | 3853 | EXTENT_DIRTY); |
3856 | btrfs_destroy_pinned_extent(root, | 3854 | btrfs_destroy_pinned_extent(root, |
@@ -3894,6 +3892,8 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3894 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3892 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) |
3895 | wake_up(&root->fs_info->transaction_blocked_wait); | 3893 | wake_up(&root->fs_info->transaction_blocked_wait); |
3896 | 3894 | ||
3895 | btrfs_evict_pending_snapshots(t); | ||
3896 | |||
3897 | t->blocked = 0; | 3897 | t->blocked = 0; |
3898 | smp_mb(); | 3898 | smp_mb(); |
3899 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3899 | if (waitqueue_active(&root->fs_info->transaction_wait)) |
@@ -3907,8 +3907,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3907 | btrfs_destroy_delayed_inodes(root); | 3907 | btrfs_destroy_delayed_inodes(root); |
3908 | btrfs_assert_delayed_root_empty(root); | 3908 | btrfs_assert_delayed_root_empty(root); |
3909 | 3909 | ||
3910 | btrfs_destroy_pending_snapshots(t); | ||
3911 | |||
3912 | btrfs_destroy_delalloc_inodes(root); | 3910 | btrfs_destroy_delalloc_inodes(root); |
3913 | 3911 | ||
3914 | spin_lock(&root->fs_info->trans_lock); | 3912 | spin_lock(&root->fs_info->trans_lock); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b908960c9746..898c5729e7e5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -527,6 +527,8 @@ fail: | |||
527 | if (async_transid) { | 527 | if (async_transid) { |
528 | *async_transid = trans->transid; | 528 | *async_transid = trans->transid; |
529 | err = btrfs_commit_transaction_async(trans, root, 1); | 529 | err = btrfs_commit_transaction_async(trans, root, 1); |
530 | if (err) | ||
531 | err = btrfs_commit_transaction(trans, root); | ||
530 | } else { | 532 | } else { |
531 | err = btrfs_commit_transaction(trans, root); | 533 | err = btrfs_commit_transaction(trans, root); |
532 | } | 534 | } |
@@ -592,16 +594,14 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
592 | *async_transid = trans->transid; | 594 | *async_transid = trans->transid; |
593 | ret = btrfs_commit_transaction_async(trans, | 595 | ret = btrfs_commit_transaction_async(trans, |
594 | root->fs_info->extent_root, 1); | 596 | root->fs_info->extent_root, 1); |
597 | if (ret) | ||
598 | ret = btrfs_commit_transaction(trans, root); | ||
595 | } else { | 599 | } else { |
596 | ret = btrfs_commit_transaction(trans, | 600 | ret = btrfs_commit_transaction(trans, |
597 | root->fs_info->extent_root); | 601 | root->fs_info->extent_root); |
598 | } | 602 | } |
599 | if (ret) { | 603 | if (ret) |
600 | /* cleanup_transaction has freed this for us */ | ||
601 | if (trans->aborted) | ||
602 | pending_snapshot = NULL; | ||
603 | goto fail; | 604 | goto fail; |
604 | } | ||
605 | 605 | ||
606 | ret = pending_snapshot->error; | 606 | ret = pending_snapshot->error; |
607 | if (ret) | 607 | if (ret) |
@@ -2245,13 +2245,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2245 | if (ret) | 2245 | if (ret) |
2246 | return ret; | 2246 | return ret; |
2247 | 2247 | ||
2248 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | ||
2249 | 1)) { | ||
2250 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
2251 | mnt_drop_write_file(file); | ||
2252 | return -EINVAL; | ||
2253 | } | ||
2254 | |||
2255 | if (btrfs_root_readonly(root)) { | 2248 | if (btrfs_root_readonly(root)) { |
2256 | ret = -EROFS; | 2249 | ret = -EROFS; |
2257 | goto out; | 2250 | goto out; |
@@ -2306,7 +2299,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2306 | ret = -EINVAL; | 2299 | ret = -EINVAL; |
2307 | } | 2300 | } |
2308 | out: | 2301 | out: |
2309 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2310 | mnt_drop_write_file(file); | 2302 | mnt_drop_write_file(file); |
2311 | return ret; | 2303 | return ret; |
2312 | } | 2304 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index ba5a3210da9a..3ebe87977aae 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1269,6 +1269,8 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
1269 | } | 1269 | } |
1270 | spin_unlock(&rc->reloc_root_tree.lock); | 1270 | spin_unlock(&rc->reloc_root_tree.lock); |
1271 | 1271 | ||
1272 | if (!node) | ||
1273 | return 0; | ||
1272 | BUG_ON((struct btrfs_root *)node->data != root); | 1274 | BUG_ON((struct btrfs_root *)node->data != root); |
1273 | 1275 | ||
1274 | if (!del) { | 1276 | if (!del) { |
@@ -2238,13 +2240,28 @@ again: | |||
2238 | } | 2240 | } |
2239 | 2241 | ||
2240 | static noinline_for_stack | 2242 | static noinline_for_stack |
2243 | void free_reloc_roots(struct list_head *list) | ||
2244 | { | ||
2245 | struct btrfs_root *reloc_root; | ||
2246 | |||
2247 | while (!list_empty(list)) { | ||
2248 | reloc_root = list_entry(list->next, struct btrfs_root, | ||
2249 | root_list); | ||
2250 | __update_reloc_root(reloc_root, 1); | ||
2251 | free_extent_buffer(reloc_root->node); | ||
2252 | free_extent_buffer(reloc_root->commit_root); | ||
2253 | kfree(reloc_root); | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2257 | static noinline_for_stack | ||
2241 | int merge_reloc_roots(struct reloc_control *rc) | 2258 | int merge_reloc_roots(struct reloc_control *rc) |
2242 | { | 2259 | { |
2243 | struct btrfs_root *root; | 2260 | struct btrfs_root *root; |
2244 | struct btrfs_root *reloc_root; | 2261 | struct btrfs_root *reloc_root; |
2245 | LIST_HEAD(reloc_roots); | 2262 | LIST_HEAD(reloc_roots); |
2246 | int found = 0; | 2263 | int found = 0; |
2247 | int ret; | 2264 | int ret = 0; |
2248 | again: | 2265 | again: |
2249 | root = rc->extent_root; | 2266 | root = rc->extent_root; |
2250 | 2267 | ||
@@ -2270,20 +2287,33 @@ again: | |||
2270 | BUG_ON(root->reloc_root != reloc_root); | 2287 | BUG_ON(root->reloc_root != reloc_root); |
2271 | 2288 | ||
2272 | ret = merge_reloc_root(rc, root); | 2289 | ret = merge_reloc_root(rc, root); |
2273 | BUG_ON(ret); | 2290 | if (ret) |
2291 | goto out; | ||
2274 | } else { | 2292 | } else { |
2275 | list_del_init(&reloc_root->root_list); | 2293 | list_del_init(&reloc_root->root_list); |
2276 | } | 2294 | } |
2277 | ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); | 2295 | ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); |
2278 | BUG_ON(ret < 0); | 2296 | if (ret < 0) { |
2297 | if (list_empty(&reloc_root->root_list)) | ||
2298 | list_add_tail(&reloc_root->root_list, | ||
2299 | &reloc_roots); | ||
2300 | goto out; | ||
2301 | } | ||
2279 | } | 2302 | } |
2280 | 2303 | ||
2281 | if (found) { | 2304 | if (found) { |
2282 | found = 0; | 2305 | found = 0; |
2283 | goto again; | 2306 | goto again; |
2284 | } | 2307 | } |
2308 | out: | ||
2309 | if (ret) { | ||
2310 | btrfs_std_error(root->fs_info, ret); | ||
2311 | if (!list_empty(&reloc_roots)) | ||
2312 | free_reloc_roots(&reloc_roots); | ||
2313 | } | ||
2314 | |||
2285 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); | 2315 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); |
2286 | return 0; | 2316 | return ret; |
2287 | } | 2317 | } |
2288 | 2318 | ||
2289 | static void free_block_list(struct rb_root *blocks) | 2319 | static void free_block_list(struct rb_root *blocks) |
@@ -2818,8 +2848,10 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans, | |||
2818 | int err = 0; | 2848 | int err = 0; |
2819 | 2849 | ||
2820 | path = btrfs_alloc_path(); | 2850 | path = btrfs_alloc_path(); |
2821 | if (!path) | 2851 | if (!path) { |
2822 | return -ENOMEM; | 2852 | err = -ENOMEM; |
2853 | goto out_path; | ||
2854 | } | ||
2823 | 2855 | ||
2824 | rb_node = rb_first(blocks); | 2856 | rb_node = rb_first(blocks); |
2825 | while (rb_node) { | 2857 | while (rb_node) { |
@@ -2858,10 +2890,11 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans, | |||
2858 | rb_node = rb_next(rb_node); | 2890 | rb_node = rb_next(rb_node); |
2859 | } | 2891 | } |
2860 | out: | 2892 | out: |
2861 | free_block_list(blocks); | ||
2862 | err = finish_pending_nodes(trans, rc, path, err); | 2893 | err = finish_pending_nodes(trans, rc, path, err); |
2863 | 2894 | ||
2864 | btrfs_free_path(path); | 2895 | btrfs_free_path(path); |
2896 | out_path: | ||
2897 | free_block_list(blocks); | ||
2865 | return err; | 2898 | return err; |
2866 | } | 2899 | } |
2867 | 2900 | ||
@@ -3698,7 +3731,15 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
3698 | set_reloc_control(rc); | 3731 | set_reloc_control(rc); |
3699 | 3732 | ||
3700 | trans = btrfs_join_transaction(rc->extent_root); | 3733 | trans = btrfs_join_transaction(rc->extent_root); |
3701 | BUG_ON(IS_ERR(trans)); | 3734 | if (IS_ERR(trans)) { |
3735 | unset_reloc_control(rc); | ||
3736 | /* | ||
3737 | * extent tree is not a ref_cow tree and has no reloc_root to | ||
3738 | * cleanup. And callers are responsible to free the above | ||
3739 | * block rsv. | ||
3740 | */ | ||
3741 | return PTR_ERR(trans); | ||
3742 | } | ||
3702 | btrfs_commit_transaction(trans, rc->extent_root); | 3743 | btrfs_commit_transaction(trans, rc->extent_root); |
3703 | return 0; | 3744 | return 0; |
3704 | } | 3745 | } |
@@ -3730,7 +3771,11 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3730 | while (1) { | 3771 | while (1) { |
3731 | progress++; | 3772 | progress++; |
3732 | trans = btrfs_start_transaction(rc->extent_root, 0); | 3773 | trans = btrfs_start_transaction(rc->extent_root, 0); |
3733 | BUG_ON(IS_ERR(trans)); | 3774 | if (IS_ERR(trans)) { |
3775 | err = PTR_ERR(trans); | ||
3776 | trans = NULL; | ||
3777 | break; | ||
3778 | } | ||
3734 | restart: | 3779 | restart: |
3735 | if (update_backref_cache(trans, &rc->backref_cache)) { | 3780 | if (update_backref_cache(trans, &rc->backref_cache)) { |
3736 | btrfs_end_transaction(trans, rc->extent_root); | 3781 | btrfs_end_transaction(trans, rc->extent_root); |
@@ -4264,14 +4309,9 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4264 | out_free: | 4309 | out_free: |
4265 | kfree(rc); | 4310 | kfree(rc); |
4266 | out: | 4311 | out: |
4267 | while (!list_empty(&reloc_roots)) { | 4312 | if (!list_empty(&reloc_roots)) |
4268 | reloc_root = list_entry(reloc_roots.next, | 4313 | free_reloc_roots(&reloc_roots); |
4269 | struct btrfs_root, root_list); | 4314 | |
4270 | list_del(&reloc_root->root_list); | ||
4271 | free_extent_buffer(reloc_root->node); | ||
4272 | free_extent_buffer(reloc_root->commit_root); | ||
4273 | kfree(reloc_root); | ||
4274 | } | ||
4275 | btrfs_free_path(path); | 4315 | btrfs_free_path(path); |
4276 | 4316 | ||
4277 | if (err == 0) { | 4317 | if (err == 0) { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f11c2e0a3746..fedede1fe178 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1053,7 +1053,12 @@ int btrfs_defrag_root(struct btrfs_root *root) | |||
1053 | 1053 | ||
1054 | /* | 1054 | /* |
1055 | * new snapshots need to be created at a very specific time in the | 1055 | * new snapshots need to be created at a very specific time in the |
1056 | * transaction commit. This does the actual creation | 1056 | * transaction commit. This does the actual creation. |
1057 | * | ||
1058 | * Note: | ||
1059 | * If the error which may affect the commitment of the current transaction | ||
1060 | * happens, we should return the error number. If the error which just affect | ||
1061 | * the creation of the pending snapshots, just return 0. | ||
1057 | */ | 1062 | */ |
1058 | static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | 1063 | static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, |
1059 | struct btrfs_fs_info *fs_info, | 1064 | struct btrfs_fs_info *fs_info, |
@@ -1072,7 +1077,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1072 | struct extent_buffer *tmp; | 1077 | struct extent_buffer *tmp; |
1073 | struct extent_buffer *old; | 1078 | struct extent_buffer *old; |
1074 | struct timespec cur_time = CURRENT_TIME; | 1079 | struct timespec cur_time = CURRENT_TIME; |
1075 | int ret; | 1080 | int ret = 0; |
1076 | u64 to_reserve = 0; | 1081 | u64 to_reserve = 0; |
1077 | u64 index = 0; | 1082 | u64 index = 0; |
1078 | u64 objectid; | 1083 | u64 objectid; |
@@ -1081,40 +1086,36 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1081 | 1086 | ||
1082 | path = btrfs_alloc_path(); | 1087 | path = btrfs_alloc_path(); |
1083 | if (!path) { | 1088 | if (!path) { |
1084 | ret = pending->error = -ENOMEM; | 1089 | pending->error = -ENOMEM; |
1085 | return ret; | 1090 | return 0; |
1086 | } | 1091 | } |
1087 | 1092 | ||
1088 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 1093 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
1089 | if (!new_root_item) { | 1094 | if (!new_root_item) { |
1090 | ret = pending->error = -ENOMEM; | 1095 | pending->error = -ENOMEM; |
1091 | goto root_item_alloc_fail; | 1096 | goto root_item_alloc_fail; |
1092 | } | 1097 | } |
1093 | 1098 | ||
1094 | ret = btrfs_find_free_objectid(tree_root, &objectid); | 1099 | pending->error = btrfs_find_free_objectid(tree_root, &objectid); |
1095 | if (ret) { | 1100 | if (pending->error) |
1096 | pending->error = ret; | ||
1097 | goto no_free_objectid; | 1101 | goto no_free_objectid; |
1098 | } | ||
1099 | 1102 | ||
1100 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); | 1103 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); |
1101 | 1104 | ||
1102 | if (to_reserve > 0) { | 1105 | if (to_reserve > 0) { |
1103 | ret = btrfs_block_rsv_add(root, &pending->block_rsv, | 1106 | pending->error = btrfs_block_rsv_add(root, |
1104 | to_reserve, | 1107 | &pending->block_rsv, |
1105 | BTRFS_RESERVE_NO_FLUSH); | 1108 | to_reserve, |
1106 | if (ret) { | 1109 | BTRFS_RESERVE_NO_FLUSH); |
1107 | pending->error = ret; | 1110 | if (pending->error) |
1108 | goto no_free_objectid; | 1111 | goto no_free_objectid; |
1109 | } | ||
1110 | } | 1112 | } |
1111 | 1113 | ||
1112 | ret = btrfs_qgroup_inherit(trans, fs_info, root->root_key.objectid, | 1114 | pending->error = btrfs_qgroup_inherit(trans, fs_info, |
1113 | objectid, pending->inherit); | 1115 | root->root_key.objectid, |
1114 | if (ret) { | 1116 | objectid, pending->inherit); |
1115 | pending->error = ret; | 1117 | if (pending->error) |
1116 | goto no_free_objectid; | 1118 | goto no_free_objectid; |
1117 | } | ||
1118 | 1119 | ||
1119 | key.objectid = objectid; | 1120 | key.objectid = objectid; |
1120 | key.offset = (u64)-1; | 1121 | key.offset = (u64)-1; |
@@ -1142,7 +1143,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1142 | dentry->d_name.len, 0); | 1143 | dentry->d_name.len, 0); |
1143 | if (dir_item != NULL && !IS_ERR(dir_item)) { | 1144 | if (dir_item != NULL && !IS_ERR(dir_item)) { |
1144 | pending->error = -EEXIST; | 1145 | pending->error = -EEXIST; |
1145 | goto fail; | 1146 | goto dir_item_existed; |
1146 | } else if (IS_ERR(dir_item)) { | 1147 | } else if (IS_ERR(dir_item)) { |
1147 | ret = PTR_ERR(dir_item); | 1148 | ret = PTR_ERR(dir_item); |
1148 | btrfs_abort_transaction(trans, root, ret); | 1149 | btrfs_abort_transaction(trans, root, ret); |
@@ -1273,6 +1274,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1273 | if (ret) | 1274 | if (ret) |
1274 | btrfs_abort_transaction(trans, root, ret); | 1275 | btrfs_abort_transaction(trans, root, ret); |
1275 | fail: | 1276 | fail: |
1277 | pending->error = ret; | ||
1278 | dir_item_existed: | ||
1276 | trans->block_rsv = rsv; | 1279 | trans->block_rsv = rsv; |
1277 | trans->bytes_reserved = 0; | 1280 | trans->bytes_reserved = 0; |
1278 | no_free_objectid: | 1281 | no_free_objectid: |
@@ -1288,12 +1291,17 @@ root_item_alloc_fail: | |||
1288 | static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | 1291 | static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, |
1289 | struct btrfs_fs_info *fs_info) | 1292 | struct btrfs_fs_info *fs_info) |
1290 | { | 1293 | { |
1291 | struct btrfs_pending_snapshot *pending; | 1294 | struct btrfs_pending_snapshot *pending, *next; |
1292 | struct list_head *head = &trans->transaction->pending_snapshots; | 1295 | struct list_head *head = &trans->transaction->pending_snapshots; |
1296 | int ret = 0; | ||
1293 | 1297 | ||
1294 | list_for_each_entry(pending, head, list) | 1298 | list_for_each_entry_safe(pending, next, head, list) { |
1295 | create_pending_snapshot(trans, fs_info, pending); | 1299 | list_del(&pending->list); |
1296 | return 0; | 1300 | ret = create_pending_snapshot(trans, fs_info, pending); |
1301 | if (ret) | ||
1302 | break; | ||
1303 | } | ||
1304 | return ret; | ||
1297 | } | 1305 | } |
1298 | 1306 | ||
1299 | static void update_super_roots(struct btrfs_root *root) | 1307 | static void update_super_roots(struct btrfs_root *root) |
@@ -1449,6 +1457,13 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, | |||
1449 | btrfs_abort_transaction(trans, root, err); | 1457 | btrfs_abort_transaction(trans, root, err); |
1450 | 1458 | ||
1451 | spin_lock(&root->fs_info->trans_lock); | 1459 | spin_lock(&root->fs_info->trans_lock); |
1460 | |||
1461 | if (list_empty(&cur_trans->list)) { | ||
1462 | spin_unlock(&root->fs_info->trans_lock); | ||
1463 | btrfs_end_transaction(trans, root); | ||
1464 | return; | ||
1465 | } | ||
1466 | |||
1452 | list_del_init(&cur_trans->list); | 1467 | list_del_init(&cur_trans->list); |
1453 | if (cur_trans == root->fs_info->running_transaction) { | 1468 | if (cur_trans == root->fs_info->running_transaction) { |
1454 | root->fs_info->trans_no_join = 1; | 1469 | root->fs_info->trans_no_join = 1; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c7ef569eb22a..451fad96ecd1 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -1382,7 +1382,10 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans, | |||
1382 | 1382 | ||
1383 | btrfs_release_path(path); | 1383 | btrfs_release_path(path); |
1384 | if (ret == 0) { | 1384 | if (ret == 0) { |
1385 | btrfs_inc_nlink(inode); | 1385 | if (!inode->i_nlink) |
1386 | set_nlink(inode, 1); | ||
1387 | else | ||
1388 | btrfs_inc_nlink(inode); | ||
1386 | ret = btrfs_update_inode(trans, root, inode); | 1389 | ret = btrfs_update_inode(trans, root, inode); |
1387 | } else if (ret == -EEXIST) { | 1390 | } else if (ret == -EEXIST) { |
1388 | ret = 0; | 1391 | ret = 0; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 35bb2d4ed29f..9ff454df6756 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2379,7 +2379,11 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
2379 | return ret; | 2379 | return ret; |
2380 | 2380 | ||
2381 | trans = btrfs_start_transaction(root, 0); | 2381 | trans = btrfs_start_transaction(root, 0); |
2382 | BUG_ON(IS_ERR(trans)); | 2382 | if (IS_ERR(trans)) { |
2383 | ret = PTR_ERR(trans); | ||
2384 | btrfs_std_error(root->fs_info, ret); | ||
2385 | return ret; | ||
2386 | } | ||
2383 | 2387 | ||
2384 | lock_chunks(root); | 2388 | lock_chunks(root); |
2385 | 2389 | ||
@@ -3050,7 +3054,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) | |||
3050 | 3054 | ||
3051 | unset_balance_control(fs_info); | 3055 | unset_balance_control(fs_info); |
3052 | ret = del_balance_item(fs_info->tree_root); | 3056 | ret = del_balance_item(fs_info->tree_root); |
3053 | BUG_ON(ret); | 3057 | if (ret) |
3058 | btrfs_std_error(fs_info, ret); | ||
3054 | 3059 | ||
3055 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | 3060 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); |
3056 | } | 3061 | } |