diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 16 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 6 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 58 |
3 files changed, 41 insertions, 39 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..94c0e42dfa1e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -596,12 +596,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
596 | ret = btrfs_commit_transaction(trans, | 596 | ret = btrfs_commit_transaction(trans, |
597 | root->fs_info->extent_root); | 597 | root->fs_info->extent_root); |
598 | } | 598 | } |
599 | if (ret) { | 599 | if (ret) |
600 | /* cleanup_transaction has freed this for us */ | ||
601 | if (trans->aborted) | ||
602 | pending_snapshot = NULL; | ||
603 | goto fail; | 600 | goto fail; |
604 | } | ||
605 | 601 | ||
606 | ret = pending_snapshot->error; | 602 | ret = pending_snapshot->error; |
607 | if (ret) | 603 | if (ret) |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f11c2e0a3746..d8fce6fe9cf8 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) |