diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 190 |
1 files changed, 155 insertions, 35 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index fb5cd5a4adba..5a4999aa8fef 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #define BTRFS_ROOT_TRANS_TAG 0 | 32 | #define BTRFS_ROOT_TRANS_TAG 0 |
33 | 33 | ||
34 | static noinline void put_transaction(struct btrfs_transaction *transaction) | 34 | void put_transaction(struct btrfs_transaction *transaction) |
35 | { | 35 | { |
36 | WARN_ON(atomic_read(&transaction->use_count) == 0); | 36 | WARN_ON(atomic_read(&transaction->use_count) == 0); |
37 | if (atomic_dec_and_test(&transaction->use_count)) { | 37 | if (atomic_dec_and_test(&transaction->use_count)) { |
@@ -58,6 +58,12 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail) | |||
58 | 58 | ||
59 | spin_lock(&root->fs_info->trans_lock); | 59 | spin_lock(&root->fs_info->trans_lock); |
60 | loop: | 60 | loop: |
61 | /* The file system has been taken offline. No new transactions. */ | ||
62 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | ||
63 | spin_unlock(&root->fs_info->trans_lock); | ||
64 | return -EROFS; | ||
65 | } | ||
66 | |||
61 | if (root->fs_info->trans_no_join) { | 67 | if (root->fs_info->trans_no_join) { |
62 | if (!nofail) { | 68 | if (!nofail) { |
63 | spin_unlock(&root->fs_info->trans_lock); | 69 | spin_unlock(&root->fs_info->trans_lock); |
@@ -67,6 +73,8 @@ loop: | |||
67 | 73 | ||
68 | cur_trans = root->fs_info->running_transaction; | 74 | cur_trans = root->fs_info->running_transaction; |
69 | if (cur_trans) { | 75 | if (cur_trans) { |
76 | if (cur_trans->aborted) | ||
77 | return cur_trans->aborted; | ||
70 | atomic_inc(&cur_trans->use_count); | 78 | atomic_inc(&cur_trans->use_count); |
71 | atomic_inc(&cur_trans->num_writers); | 79 | atomic_inc(&cur_trans->num_writers); |
72 | cur_trans->num_joined++; | 80 | cur_trans->num_joined++; |
@@ -123,6 +131,7 @@ loop: | |||
123 | root->fs_info->generation++; | 131 | root->fs_info->generation++; |
124 | cur_trans->transid = root->fs_info->generation; | 132 | cur_trans->transid = root->fs_info->generation; |
125 | root->fs_info->running_transaction = cur_trans; | 133 | root->fs_info->running_transaction = cur_trans; |
134 | cur_trans->aborted = 0; | ||
126 | spin_unlock(&root->fs_info->trans_lock); | 135 | spin_unlock(&root->fs_info->trans_lock); |
127 | 136 | ||
128 | return 0; | 137 | return 0; |
@@ -318,6 +327,7 @@ again: | |||
318 | h->use_count = 1; | 327 | h->use_count = 1; |
319 | h->block_rsv = NULL; | 328 | h->block_rsv = NULL; |
320 | h->orig_rsv = NULL; | 329 | h->orig_rsv = NULL; |
330 | h->aborted = 0; | ||
321 | 331 | ||
322 | smp_mb(); | 332 | smp_mb(); |
323 | if (cur_trans->blocked && may_wait_transaction(root, type)) { | 333 | if (cur_trans->blocked && may_wait_transaction(root, type)) { |
@@ -440,6 +450,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | |||
440 | struct btrfs_transaction *cur_trans = trans->transaction; | 450 | struct btrfs_transaction *cur_trans = trans->transaction; |
441 | struct btrfs_block_rsv *rsv = trans->block_rsv; | 451 | struct btrfs_block_rsv *rsv = trans->block_rsv; |
442 | int updates; | 452 | int updates; |
453 | int err; | ||
443 | 454 | ||
444 | smp_mb(); | 455 | smp_mb(); |
445 | if (cur_trans->blocked || cur_trans->delayed_refs.flushing) | 456 | if (cur_trans->blocked || cur_trans->delayed_refs.flushing) |
@@ -453,8 +464,11 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | |||
453 | 464 | ||
454 | updates = trans->delayed_ref_updates; | 465 | updates = trans->delayed_ref_updates; |
455 | trans->delayed_ref_updates = 0; | 466 | trans->delayed_ref_updates = 0; |
456 | if (updates) | 467 | if (updates) { |
457 | btrfs_run_delayed_refs(trans, root, updates); | 468 | err = btrfs_run_delayed_refs(trans, root, updates); |
469 | if (err) /* Error code will also eval true */ | ||
470 | return err; | ||
471 | } | ||
458 | 472 | ||
459 | trans->block_rsv = rsv; | 473 | trans->block_rsv = rsv; |
460 | 474 | ||
@@ -525,6 +539,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
525 | if (throttle) | 539 | if (throttle) |
526 | btrfs_run_delayed_iputs(root); | 540 | btrfs_run_delayed_iputs(root); |
527 | 541 | ||
542 | if (trans->aborted || | ||
543 | root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | ||
544 | return -EIO; | ||
545 | } | ||
546 | |||
528 | return 0; | 547 | return 0; |
529 | } | 548 | } |
530 | 549 | ||
@@ -690,11 +709,13 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
690 | ret = btrfs_update_root(trans, tree_root, | 709 | ret = btrfs_update_root(trans, tree_root, |
691 | &root->root_key, | 710 | &root->root_key, |
692 | &root->root_item); | 711 | &root->root_item); |
693 | BUG_ON(ret); | 712 | if (ret) |
713 | return ret; | ||
694 | 714 | ||
695 | old_root_used = btrfs_root_used(&root->root_item); | 715 | old_root_used = btrfs_root_used(&root->root_item); |
696 | ret = btrfs_write_dirty_block_groups(trans, root); | 716 | ret = btrfs_write_dirty_block_groups(trans, root); |
697 | BUG_ON(ret); | 717 | if (ret) |
718 | return ret; | ||
698 | } | 719 | } |
699 | 720 | ||
700 | if (root != root->fs_info->extent_root) | 721 | if (root != root->fs_info->extent_root) |
@@ -705,6 +726,10 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
705 | 726 | ||
706 | /* | 727 | /* |
707 | * update all the cowonly tree roots on disk | 728 | * update all the cowonly tree roots on disk |
729 | * | ||
730 | * The error handling in this function may not be obvious. Any of the | ||
731 | * failures will cause the file system to go offline. We still need | ||
732 | * to clean up the delayed refs. | ||
708 | */ | 733 | */ |
709 | static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | 734 | static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, |
710 | struct btrfs_root *root) | 735 | struct btrfs_root *root) |
@@ -715,22 +740,30 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
715 | int ret; | 740 | int ret; |
716 | 741 | ||
717 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 742 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
718 | BUG_ON(ret); | 743 | if (ret) |
744 | return ret; | ||
719 | 745 | ||
720 | eb = btrfs_lock_root_node(fs_info->tree_root); | 746 | eb = btrfs_lock_root_node(fs_info->tree_root); |
721 | btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb); | 747 | ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, |
748 | 0, &eb); | ||
722 | btrfs_tree_unlock(eb); | 749 | btrfs_tree_unlock(eb); |
723 | free_extent_buffer(eb); | 750 | free_extent_buffer(eb); |
724 | 751 | ||
752 | if (ret) | ||
753 | return ret; | ||
754 | |||
725 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 755 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
726 | BUG_ON(ret); | 756 | if (ret) |
757 | return ret; | ||
727 | 758 | ||
728 | while (!list_empty(&fs_info->dirty_cowonly_roots)) { | 759 | while (!list_empty(&fs_info->dirty_cowonly_roots)) { |
729 | next = fs_info->dirty_cowonly_roots.next; | 760 | next = fs_info->dirty_cowonly_roots.next; |
730 | list_del_init(next); | 761 | list_del_init(next); |
731 | root = list_entry(next, struct btrfs_root, dirty_list); | 762 | root = list_entry(next, struct btrfs_root, dirty_list); |
732 | 763 | ||
733 | update_cowonly_root(trans, root); | 764 | ret = update_cowonly_root(trans, root); |
765 | if (ret) | ||
766 | return ret; | ||
734 | } | 767 | } |
735 | 768 | ||
736 | down_write(&fs_info->extent_commit_sem); | 769 | down_write(&fs_info->extent_commit_sem); |
@@ -874,7 +907,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
874 | 907 | ||
875 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 908 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
876 | if (!new_root_item) { | 909 | if (!new_root_item) { |
877 | pending->error = -ENOMEM; | 910 | ret = pending->error = -ENOMEM; |
878 | goto fail; | 911 | goto fail; |
879 | } | 912 | } |
880 | 913 | ||
@@ -911,7 +944,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
911 | * insert the directory item | 944 | * insert the directory item |
912 | */ | 945 | */ |
913 | ret = btrfs_set_inode_index(parent_inode, &index); | 946 | ret = btrfs_set_inode_index(parent_inode, &index); |
914 | BUG_ON(ret); | 947 | BUG_ON(ret); /* -ENOMEM */ |
915 | ret = btrfs_insert_dir_item(trans, parent_root, | 948 | ret = btrfs_insert_dir_item(trans, parent_root, |
916 | dentry->d_name.name, dentry->d_name.len, | 949 | dentry->d_name.name, dentry->d_name.len, |
917 | parent_inode, &key, | 950 | parent_inode, &key, |
@@ -920,12 +953,14 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
920 | pending->error = -EEXIST; | 953 | pending->error = -EEXIST; |
921 | dput(parent); | 954 | dput(parent); |
922 | goto fail; | 955 | goto fail; |
923 | } | 956 | } else if (ret) |
957 | goto abort_trans; | ||
924 | 958 | ||
925 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 959 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
926 | dentry->d_name.len * 2); | 960 | dentry->d_name.len * 2); |
927 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 961 | ret = btrfs_update_inode(trans, parent_root, parent_inode); |
928 | BUG_ON(ret); | 962 | if (ret) |
963 | goto abort_trans; | ||
929 | 964 | ||
930 | /* | 965 | /* |
931 | * pull in the delayed directory update | 966 | * pull in the delayed directory update |
@@ -934,7 +969,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
934 | * snapshot | 969 | * snapshot |
935 | */ | 970 | */ |
936 | ret = btrfs_run_delayed_items(trans, root); | 971 | ret = btrfs_run_delayed_items(trans, root); |
937 | BUG_ON(ret); | 972 | if (ret) /* Transaction aborted */ |
973 | goto fail; | ||
938 | 974 | ||
939 | record_root_in_trans(trans, root); | 975 | record_root_in_trans(trans, root); |
940 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | 976 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); |
@@ -949,10 +985,16 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
949 | btrfs_set_root_flags(new_root_item, root_flags); | 985 | btrfs_set_root_flags(new_root_item, root_flags); |
950 | 986 | ||
951 | old = btrfs_lock_root_node(root); | 987 | old = btrfs_lock_root_node(root); |
952 | btrfs_cow_block(trans, root, old, NULL, 0, &old); | 988 | ret = btrfs_cow_block(trans, root, old, NULL, 0, &old); |
989 | if (ret) | ||
990 | goto abort_trans; | ||
991 | |||
953 | btrfs_set_lock_blocking(old); | 992 | btrfs_set_lock_blocking(old); |
954 | 993 | ||
955 | btrfs_copy_root(trans, root, old, &tmp, objectid); | 994 | ret = btrfs_copy_root(trans, root, old, &tmp, objectid); |
995 | if (ret) | ||
996 | goto abort_trans; | ||
997 | |||
956 | btrfs_tree_unlock(old); | 998 | btrfs_tree_unlock(old); |
957 | free_extent_buffer(old); | 999 | free_extent_buffer(old); |
958 | 1000 | ||
@@ -966,7 +1008,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
966 | ret = btrfs_insert_root(trans, tree_root, &key, new_root_item); | 1008 | ret = btrfs_insert_root(trans, tree_root, &key, new_root_item); |
967 | btrfs_tree_unlock(tmp); | 1009 | btrfs_tree_unlock(tmp); |
968 | free_extent_buffer(tmp); | 1010 | free_extent_buffer(tmp); |
969 | BUG_ON(ret); | 1011 | if (ret) |
1012 | goto abort_trans; | ||
970 | 1013 | ||
971 | /* | 1014 | /* |
972 | * insert root back/forward references | 1015 | * insert root back/forward references |
@@ -975,19 +1018,28 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
975 | parent_root->root_key.objectid, | 1018 | parent_root->root_key.objectid, |
976 | btrfs_ino(parent_inode), index, | 1019 | btrfs_ino(parent_inode), index, |
977 | dentry->d_name.name, dentry->d_name.len); | 1020 | dentry->d_name.name, dentry->d_name.len); |
978 | BUG_ON(ret); | 1021 | if (ret) |
1022 | goto fail; | ||
979 | dput(parent); | 1023 | dput(parent); |
980 | 1024 | ||
981 | key.offset = (u64)-1; | 1025 | key.offset = (u64)-1; |
982 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); | 1026 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); |
983 | BUG_ON(IS_ERR(pending->snap)); | 1027 | if (IS_ERR(pending->snap)) |
1028 | goto abort_trans; | ||
984 | 1029 | ||
985 | btrfs_reloc_post_snapshot(trans, pending); | 1030 | ret = btrfs_reloc_post_snapshot(trans, pending); |
1031 | if (ret) | ||
1032 | goto abort_trans; | ||
1033 | ret = 0; | ||
986 | fail: | 1034 | fail: |
987 | kfree(new_root_item); | 1035 | kfree(new_root_item); |
988 | trans->block_rsv = rsv; | 1036 | trans->block_rsv = rsv; |
989 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); | 1037 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); |
990 | return 0; | 1038 | return ret; |
1039 | |||
1040 | abort_trans: | ||
1041 | btrfs_abort_transaction(trans, root, ret); | ||
1042 | goto fail; | ||
991 | } | 1043 | } |
992 | 1044 | ||
993 | /* | 1045 | /* |
@@ -1124,6 +1176,33 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, | |||
1124 | return 0; | 1176 | return 0; |
1125 | } | 1177 | } |
1126 | 1178 | ||
1179 | |||
1180 | static void cleanup_transaction(struct btrfs_trans_handle *trans, | ||
1181 | struct btrfs_root *root) | ||
1182 | { | ||
1183 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
1184 | |||
1185 | WARN_ON(trans->use_count > 1); | ||
1186 | |||
1187 | spin_lock(&root->fs_info->trans_lock); | ||
1188 | list_del_init(&cur_trans->list); | ||
1189 | spin_unlock(&root->fs_info->trans_lock); | ||
1190 | |||
1191 | btrfs_cleanup_one_transaction(trans->transaction, root); | ||
1192 | |||
1193 | put_transaction(cur_trans); | ||
1194 | put_transaction(cur_trans); | ||
1195 | |||
1196 | trace_btrfs_transaction_commit(root); | ||
1197 | |||
1198 | btrfs_scrub_continue(root); | ||
1199 | |||
1200 | if (current->journal_info == trans) | ||
1201 | current->journal_info = NULL; | ||
1202 | |||
1203 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | ||
1204 | } | ||
1205 | |||
1127 | /* | 1206 | /* |
1128 | * btrfs_transaction state sequence: | 1207 | * btrfs_transaction state sequence: |
1129 | * in_commit = 0, blocked = 0 (initial) | 1208 | * in_commit = 0, blocked = 0 (initial) |
@@ -1135,10 +1214,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1135 | struct btrfs_root *root) | 1214 | struct btrfs_root *root) |
1136 | { | 1215 | { |
1137 | unsigned long joined = 0; | 1216 | unsigned long joined = 0; |
1138 | struct btrfs_transaction *cur_trans; | 1217 | struct btrfs_transaction *cur_trans = trans->transaction; |
1139 | struct btrfs_transaction *prev_trans = NULL; | 1218 | struct btrfs_transaction *prev_trans = NULL; |
1140 | DEFINE_WAIT(wait); | 1219 | DEFINE_WAIT(wait); |
1141 | int ret; | 1220 | int ret = -EIO; |
1142 | int should_grow = 0; | 1221 | int should_grow = 0; |
1143 | unsigned long now = get_seconds(); | 1222 | unsigned long now = get_seconds(); |
1144 | int flush_on_commit = btrfs_test_opt(root, FLUSHONCOMMIT); | 1223 | int flush_on_commit = btrfs_test_opt(root, FLUSHONCOMMIT); |
@@ -1148,13 +1227,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1148 | btrfs_trans_release_metadata(trans, root); | 1227 | btrfs_trans_release_metadata(trans, root); |
1149 | trans->block_rsv = NULL; | 1228 | trans->block_rsv = NULL; |
1150 | 1229 | ||
1230 | if (cur_trans->aborted) | ||
1231 | goto cleanup_transaction; | ||
1232 | |||
1151 | /* make a pass through all the delayed refs we have so far | 1233 | /* make a pass through all the delayed refs we have so far |
1152 | * any runnings procs may add more while we are here | 1234 | * any runnings procs may add more while we are here |
1153 | */ | 1235 | */ |
1154 | ret = btrfs_run_delayed_refs(trans, root, 0); | 1236 | ret = btrfs_run_delayed_refs(trans, root, 0); |
1155 | BUG_ON(ret); | 1237 | if (ret) |
1238 | goto cleanup_transaction; | ||
1156 | 1239 | ||
1157 | cur_trans = trans->transaction; | 1240 | cur_trans = trans->transaction; |
1241 | |||
1158 | /* | 1242 | /* |
1159 | * set the flushing flag so procs in this transaction have to | 1243 | * set the flushing flag so procs in this transaction have to |
1160 | * start sending their work down. | 1244 | * start sending their work down. |
@@ -1162,19 +1246,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1162 | cur_trans->delayed_refs.flushing = 1; | 1246 | cur_trans->delayed_refs.flushing = 1; |
1163 | 1247 | ||
1164 | ret = btrfs_run_delayed_refs(trans, root, 0); | 1248 | ret = btrfs_run_delayed_refs(trans, root, 0); |
1165 | BUG_ON(ret); | 1249 | if (ret) |
1250 | goto cleanup_transaction; | ||
1166 | 1251 | ||
1167 | spin_lock(&cur_trans->commit_lock); | 1252 | spin_lock(&cur_trans->commit_lock); |
1168 | if (cur_trans->in_commit) { | 1253 | if (cur_trans->in_commit) { |
1169 | spin_unlock(&cur_trans->commit_lock); | 1254 | spin_unlock(&cur_trans->commit_lock); |
1170 | atomic_inc(&cur_trans->use_count); | 1255 | atomic_inc(&cur_trans->use_count); |
1171 | btrfs_end_transaction(trans, root); | 1256 | ret = btrfs_end_transaction(trans, root); |
1172 | 1257 | ||
1173 | wait_for_commit(root, cur_trans); | 1258 | wait_for_commit(root, cur_trans); |
1174 | 1259 | ||
1175 | put_transaction(cur_trans); | 1260 | put_transaction(cur_trans); |
1176 | 1261 | ||
1177 | return 0; | 1262 | return ret; |
1178 | } | 1263 | } |
1179 | 1264 | ||
1180 | trans->transaction->in_commit = 1; | 1265 | trans->transaction->in_commit = 1; |
@@ -1218,7 +1303,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1218 | } | 1303 | } |
1219 | 1304 | ||
1220 | ret = btrfs_run_delayed_items(trans, root); | 1305 | ret = btrfs_run_delayed_items(trans, root); |
1221 | BUG_ON(ret); | 1306 | if (ret) |
1307 | goto cleanup_transaction; | ||
1222 | 1308 | ||
1223 | /* | 1309 | /* |
1224 | * rename don't use btrfs_join_transaction, so, once we | 1310 | * rename don't use btrfs_join_transaction, so, once we |
@@ -1260,13 +1346,22 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1260 | mutex_lock(&root->fs_info->reloc_mutex); | 1346 | mutex_lock(&root->fs_info->reloc_mutex); |
1261 | 1347 | ||
1262 | ret = btrfs_run_delayed_items(trans, root); | 1348 | ret = btrfs_run_delayed_items(trans, root); |
1263 | BUG_ON(ret); | 1349 | if (ret) { |
1350 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
1351 | goto cleanup_transaction; | ||
1352 | } | ||
1264 | 1353 | ||
1265 | ret = create_pending_snapshots(trans, root->fs_info); | 1354 | ret = create_pending_snapshots(trans, root->fs_info); |
1266 | BUG_ON(ret); | 1355 | if (ret) { |
1356 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
1357 | goto cleanup_transaction; | ||
1358 | } | ||
1267 | 1359 | ||
1268 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 1360 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
1269 | BUG_ON(ret); | 1361 | if (ret) { |
1362 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
1363 | goto cleanup_transaction; | ||
1364 | } | ||
1270 | 1365 | ||
1271 | /* | 1366 | /* |
1272 | * make sure none of the code above managed to slip in a | 1367 | * make sure none of the code above managed to slip in a |
@@ -1293,7 +1388,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1293 | mutex_lock(&root->fs_info->tree_log_mutex); | 1388 | mutex_lock(&root->fs_info->tree_log_mutex); |
1294 | 1389 | ||
1295 | ret = commit_fs_roots(trans, root); | 1390 | ret = commit_fs_roots(trans, root); |
1296 | BUG_ON(ret); | 1391 | if (ret) { |
1392 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
1393 | goto cleanup_transaction; | ||
1394 | } | ||
1297 | 1395 | ||
1298 | /* commit_fs_roots gets rid of all the tree log roots, it is now | 1396 | /* commit_fs_roots gets rid of all the tree log roots, it is now |
1299 | * safe to free the root of tree log roots | 1397 | * safe to free the root of tree log roots |
@@ -1301,7 +1399,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1301 | btrfs_free_log_root_tree(trans, root->fs_info); | 1399 | btrfs_free_log_root_tree(trans, root->fs_info); |
1302 | 1400 | ||
1303 | ret = commit_cowonly_roots(trans, root); | 1401 | ret = commit_cowonly_roots(trans, root); |
1304 | BUG_ON(ret); | 1402 | if (ret) { |
1403 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
1404 | goto cleanup_transaction; | ||
1405 | } | ||
1305 | 1406 | ||
1306 | btrfs_prepare_extent_commit(trans, root); | 1407 | btrfs_prepare_extent_commit(trans, root); |
1307 | 1408 | ||
@@ -1335,8 +1436,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1335 | wake_up(&root->fs_info->transaction_wait); | 1436 | wake_up(&root->fs_info->transaction_wait); |
1336 | 1437 | ||
1337 | ret = btrfs_write_and_wait_transaction(trans, root); | 1438 | ret = btrfs_write_and_wait_transaction(trans, root); |
1338 | BUG_ON(ret); | 1439 | if (ret) { |
1339 | write_ctree_super(trans, root, 0); | 1440 | btrfs_error(root->fs_info, ret, |
1441 | "Error while writing out transaction."); | ||
1442 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
1443 | goto cleanup_transaction; | ||
1444 | } | ||
1445 | |||
1446 | ret = write_ctree_super(trans, root, 0); | ||
1447 | if (ret) { | ||
1448 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
1449 | goto cleanup_transaction; | ||
1450 | } | ||
1340 | 1451 | ||
1341 | /* | 1452 | /* |
1342 | * the super is written, we can safely allow the tree-loggers | 1453 | * the super is written, we can safely allow the tree-loggers |
@@ -1372,6 +1483,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1372 | btrfs_run_delayed_iputs(root); | 1483 | btrfs_run_delayed_iputs(root); |
1373 | 1484 | ||
1374 | return ret; | 1485 | return ret; |
1486 | |||
1487 | cleanup_transaction: | ||
1488 | btrfs_printk(root->fs_info, "Skipping commit of aborted transaction.\n"); | ||
1489 | // WARN_ON(1); | ||
1490 | if (current->journal_info == trans) | ||
1491 | current->journal_info = NULL; | ||
1492 | cleanup_transaction(trans, root); | ||
1493 | |||
1494 | return ret; | ||
1375 | } | 1495 | } |
1376 | 1496 | ||
1377 | /* | 1497 | /* |