diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 11 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 60 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.c | 16 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.h | 6 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 11 |
7 files changed, 74 insertions, 34 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 116aee21bf7..f90e5a7ac16 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1403,7 +1403,8 @@ static inline struct dentry *fdentry(struct file *file) { | |||
| 1403 | } | 1403 | } |
| 1404 | 1404 | ||
| 1405 | /* extent-tree.c */ | 1405 | /* extent-tree.c */ |
| 1406 | int btrfs_cross_ref_exists(struct btrfs_root *root, | 1406 | int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, |
| 1407 | struct btrfs_root *root, | ||
| 1407 | struct btrfs_key *key, u64 bytenr); | 1408 | struct btrfs_key *key, u64 bytenr); |
| 1408 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, | 1409 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, |
| 1409 | struct btrfs_root *root); | 1410 | struct btrfs_root *root); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 33cb2ac4cb2..fff219ed61d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -893,10 +893,10 @@ out: | |||
| 893 | return ret; | 893 | return ret; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | int btrfs_cross_ref_exists(struct btrfs_root *root, | 896 | int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, |
| 897 | struct btrfs_root *root, | ||
| 897 | struct btrfs_key *key, u64 bytenr) | 898 | struct btrfs_key *key, u64 bytenr) |
| 898 | { | 899 | { |
| 899 | struct btrfs_trans_handle *trans; | ||
| 900 | struct btrfs_root *old_root; | 900 | struct btrfs_root *old_root; |
| 901 | struct btrfs_path *path = NULL; | 901 | struct btrfs_path *path = NULL; |
| 902 | struct extent_buffer *eb; | 902 | struct extent_buffer *eb; |
| @@ -908,6 +908,7 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, | |||
| 908 | int level; | 908 | int level; |
| 909 | int ret; | 909 | int ret; |
| 910 | 910 | ||
| 911 | BUG_ON(trans == NULL); | ||
| 911 | BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY); | 912 | BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY); |
| 912 | ret = get_reference_status(root, bytenr, 0, key->objectid, | 913 | ret = get_reference_status(root, bytenr, 0, key->objectid, |
| 913 | &min_generation, &ref_count); | 914 | &min_generation, &ref_count); |
| @@ -917,7 +918,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, | |||
| 917 | if (ref_count != 1) | 918 | if (ref_count != 1) |
| 918 | return 1; | 919 | return 1; |
| 919 | 920 | ||
| 920 | trans = btrfs_start_transaction(root, 0); | ||
| 921 | old_root = root->dirty_root->root; | 921 | old_root = root->dirty_root->root; |
| 922 | ref_generation = old_root->root_key.offset; | 922 | ref_generation = old_root->root_key.offset; |
| 923 | 923 | ||
| @@ -973,7 +973,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, | |||
| 973 | out: | 973 | out: |
| 974 | if (path) | 974 | if (path) |
| 975 | btrfs_free_path(path); | 975 | btrfs_free_path(path); |
| 976 | btrfs_end_transaction(trans, root); | ||
| 977 | return ret; | 976 | return ret; |
| 978 | } | 977 | } |
| 979 | 978 | ||
| @@ -3320,7 +3319,7 @@ again: | |||
| 3320 | mutex_unlock(&root->fs_info->alloc_mutex); | 3319 | mutex_unlock(&root->fs_info->alloc_mutex); |
| 3321 | 3320 | ||
| 3322 | btrfs_start_delalloc_inodes(root); | 3321 | btrfs_start_delalloc_inodes(root); |
| 3323 | btrfs_wait_ordered_extents(tree_root); | 3322 | btrfs_wait_ordered_extents(tree_root, 0); |
| 3324 | 3323 | ||
| 3325 | mutex_lock(&root->fs_info->alloc_mutex); | 3324 | mutex_lock(&root->fs_info->alloc_mutex); |
| 3326 | 3325 | ||
| @@ -3407,7 +3406,7 @@ next: | |||
| 3407 | btrfs_clean_old_snapshots(tree_root); | 3406 | btrfs_clean_old_snapshots(tree_root); |
| 3408 | 3407 | ||
| 3409 | btrfs_start_delalloc_inodes(root); | 3408 | btrfs_start_delalloc_inodes(root); |
| 3410 | btrfs_wait_ordered_extents(tree_root); | 3409 | btrfs_wait_ordered_extents(tree_root, 0); |
| 3411 | 3410 | ||
| 3412 | trans = btrfs_start_transaction(tree_root, 1); | 3411 | trans = btrfs_start_transaction(tree_root, 1); |
| 3413 | btrfs_commit_transaction(trans, tree_root); | 3412 | btrfs_commit_transaction(trans, tree_root); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4d8ffc01931..c33053ba381 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -166,7 +166,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
| 166 | 166 | ||
| 167 | cur_alloc_size = ins.offset; | 167 | cur_alloc_size = ins.offset; |
| 168 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, | 168 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, |
| 169 | ins.offset); | 169 | ins.offset, 0); |
| 170 | BUG_ON(ret); | 170 | BUG_ON(ret); |
| 171 | if (num_bytes < cur_alloc_size) { | 171 | if (num_bytes < cur_alloc_size) { |
| 172 | printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes, | 172 | printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes, |
| @@ -187,31 +187,32 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) | |||
| 187 | u64 extent_start; | 187 | u64 extent_start; |
| 188 | u64 extent_end; | 188 | u64 extent_end; |
| 189 | u64 bytenr; | 189 | u64 bytenr; |
| 190 | u64 cow_end; | ||
| 191 | u64 loops = 0; | 190 | u64 loops = 0; |
| 192 | u64 total_fs_bytes; | 191 | u64 total_fs_bytes; |
| 193 | struct btrfs_root *root = BTRFS_I(inode)->root; | 192 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 194 | struct btrfs_block_group_cache *block_group; | 193 | struct btrfs_block_group_cache *block_group; |
| 194 | struct btrfs_trans_handle *trans; | ||
| 195 | struct extent_buffer *leaf; | 195 | struct extent_buffer *leaf; |
| 196 | int found_type; | 196 | int found_type; |
| 197 | struct btrfs_path *path; | 197 | struct btrfs_path *path; |
| 198 | struct btrfs_file_extent_item *item; | 198 | struct btrfs_file_extent_item *item; |
| 199 | int ret; | 199 | int ret; |
| 200 | int err; | 200 | int err = 0; |
| 201 | struct btrfs_key found_key; | 201 | struct btrfs_key found_key; |
| 202 | 202 | ||
| 203 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 203 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
| 204 | path = btrfs_alloc_path(); | 204 | path = btrfs_alloc_path(); |
| 205 | BUG_ON(!path); | 205 | BUG_ON(!path); |
| 206 | trans = btrfs_join_transaction(root, 1); | ||
| 207 | BUG_ON(!trans); | ||
| 206 | again: | 208 | again: |
| 207 | ret = btrfs_lookup_file_extent(NULL, root, path, | 209 | ret = btrfs_lookup_file_extent(NULL, root, path, |
| 208 | inode->i_ino, start, 0); | 210 | inode->i_ino, start, 0); |
| 209 | if (ret < 0) { | 211 | if (ret < 0) { |
| 210 | btrfs_free_path(path); | 212 | err = ret; |
| 211 | return ret; | 213 | goto out; |
| 212 | } | 214 | } |
| 213 | 215 | ||
| 214 | cow_end = end; | ||
| 215 | if (ret != 0) { | 216 | if (ret != 0) { |
| 216 | if (path->slots[0] == 0) | 217 | if (path->slots[0] == 0) |
| 217 | goto not_found; | 218 | goto not_found; |
| @@ -244,12 +245,11 @@ again: | |||
| 244 | if (start < extent_start || start >= extent_end) | 245 | if (start < extent_start || start >= extent_end) |
| 245 | goto not_found; | 246 | goto not_found; |
| 246 | 247 | ||
| 247 | cow_end = min(end, extent_end - 1); | ||
| 248 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); | 248 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); |
| 249 | if (bytenr == 0) | 249 | if (bytenr == 0) |
| 250 | goto not_found; | 250 | goto not_found; |
| 251 | 251 | ||
| 252 | if (btrfs_cross_ref_exists(root, &found_key, bytenr)) | 252 | if (btrfs_cross_ref_exists(trans, root, &found_key, bytenr)) |
| 253 | goto not_found; | 253 | goto not_found; |
| 254 | /* | 254 | /* |
| 255 | * we may be called by the resizer, make sure we're inside | 255 | * we may be called by the resizer, make sure we're inside |
| @@ -260,24 +260,32 @@ again: | |||
| 260 | if (!block_group || block_group->ro) | 260 | if (!block_group || block_group->ro) |
| 261 | goto not_found; | 261 | goto not_found; |
| 262 | 262 | ||
| 263 | bytenr += btrfs_file_extent_offset(leaf, item); | ||
| 264 | extent_num_bytes = min(end + 1, extent_end) - start; | ||
| 265 | ret = btrfs_add_ordered_extent(inode, start, bytenr, | ||
| 266 | extent_num_bytes, 1); | ||
| 267 | if (ret) { | ||
| 268 | err = ret; | ||
| 269 | goto out; | ||
| 270 | } | ||
| 271 | |||
| 272 | btrfs_release_path(root, path); | ||
| 263 | start = extent_end; | 273 | start = extent_end; |
| 274 | if (start <= end) { | ||
| 275 | loops++; | ||
| 276 | goto again; | ||
| 277 | } | ||
| 264 | } else { | 278 | } else { |
| 265 | goto not_found; | 279 | not_found: |
| 266 | } | 280 | btrfs_end_transaction(trans, root); |
| 267 | loop: | ||
| 268 | if (start > end) { | ||
| 269 | btrfs_free_path(path); | 281 | btrfs_free_path(path); |
| 270 | return 0; | 282 | return cow_file_range(inode, start, end); |
| 271 | } | 283 | } |
| 272 | btrfs_release_path(root, path); | 284 | out: |
| 273 | loops++; | 285 | WARN_ON(err); |
| 274 | goto again; | 286 | btrfs_end_transaction(trans, root); |
| 275 | 287 | btrfs_free_path(path); | |
| 276 | not_found: | 288 | return err; |
| 277 | btrfs_release_path(root, path); | ||
| 278 | cow_file_range(inode, start, end); | ||
| 279 | start = end + 1; | ||
| 280 | goto loop; | ||
| 281 | } | 289 | } |
| 282 | 290 | ||
| 283 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | 291 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) |
| @@ -385,6 +393,11 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 385 | goto mapit; | 393 | goto mapit; |
| 386 | } | 394 | } |
| 387 | 395 | ||
| 396 | if (btrfs_test_opt(root, NODATASUM) || | ||
| 397 | btrfs_test_flag(inode, NODATASUM)) { | ||
| 398 | goto mapit; | ||
| 399 | } | ||
| 400 | |||
| 388 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | 401 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
| 389 | inode, rw, bio, mirror_num, | 402 | inode, rw, bio, mirror_num, |
| 390 | __btrfs_submit_bio_hook); | 403 | __btrfs_submit_bio_hook); |
| @@ -527,6 +540,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 527 | 540 | ||
| 528 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); | 541 | ordered_extent = btrfs_lookup_ordered_extent(inode, start); |
| 529 | BUG_ON(!ordered_extent); | 542 | BUG_ON(!ordered_extent); |
| 543 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) | ||
| 544 | goto nocow; | ||
| 530 | 545 | ||
| 531 | lock_extent(io_tree, ordered_extent->file_offset, | 546 | lock_extent(io_tree, ordered_extent->file_offset, |
| 532 | ordered_extent->file_offset + ordered_extent->len - 1, | 547 | ordered_extent->file_offset + ordered_extent->len - 1, |
| @@ -567,6 +582,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
| 567 | unlock_extent(io_tree, ordered_extent->file_offset, | 582 | unlock_extent(io_tree, ordered_extent->file_offset, |
| 568 | ordered_extent->file_offset + ordered_extent->len - 1, | 583 | ordered_extent->file_offset + ordered_extent->len - 1, |
| 569 | GFP_NOFS); | 584 | GFP_NOFS); |
| 585 | nocow: | ||
| 570 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 586 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
| 571 | &ordered_extent->list); | 587 | &ordered_extent->list); |
| 572 | 588 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 3932c7cd0fa..59b64c738fd 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/bit_spinlock.h> | 36 | #include <linux/bit_spinlock.h> |
| 37 | #include <linux/version.h> | 37 | #include <linux/version.h> |
| 38 | #include <linux/xattr.h> | 38 | #include <linux/xattr.h> |
| 39 | #include <linux/vmalloc.h> | ||
| 39 | #include "ctree.h" | 40 | #include "ctree.h" |
| 40 | #include "disk-io.h" | 41 | #include "disk-io.h" |
| 41 | #include "transaction.h" | 42 | #include "transaction.h" |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index db200e6baf7..da6d43eb41d 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -152,7 +152,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, | |||
| 152 | * inserted. | 152 | * inserted. |
| 153 | */ | 153 | */ |
| 154 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | 154 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, |
| 155 | u64 start, u64 len) | 155 | u64 start, u64 len, int nocow) |
| 156 | { | 156 | { |
| 157 | struct btrfs_ordered_inode_tree *tree; | 157 | struct btrfs_ordered_inode_tree *tree; |
| 158 | struct rb_node *node; | 158 | struct rb_node *node; |
| @@ -168,6 +168,8 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
| 168 | entry->start = start; | 168 | entry->start = start; |
| 169 | entry->len = len; | 169 | entry->len = len; |
| 170 | entry->inode = inode; | 170 | entry->inode = inode; |
| 171 | if (nocow) | ||
| 172 | set_bit(BTRFS_ORDERED_NOCOW, &entry->flags); | ||
| 171 | 173 | ||
| 172 | /* one ref for the tree */ | 174 | /* one ref for the tree */ |
| 173 | atomic_set(&entry->refs, 1); | 175 | atomic_set(&entry->refs, 1); |
| @@ -303,10 +305,11 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
| 303 | return 0; | 305 | return 0; |
| 304 | } | 306 | } |
| 305 | 307 | ||
| 306 | int btrfs_wait_ordered_extents(struct btrfs_root *root) | 308 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only) |
| 307 | { | 309 | { |
| 308 | struct list_head splice; | 310 | struct list_head splice; |
| 309 | struct list_head *cur; | 311 | struct list_head *cur; |
| 312 | struct list_head *tmp; | ||
| 310 | struct btrfs_ordered_extent *ordered; | 313 | struct btrfs_ordered_extent *ordered; |
| 311 | struct inode *inode; | 314 | struct inode *inode; |
| 312 | 315 | ||
| @@ -314,10 +317,16 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) | |||
| 314 | 317 | ||
| 315 | spin_lock(&root->fs_info->ordered_extent_lock); | 318 | spin_lock(&root->fs_info->ordered_extent_lock); |
| 316 | list_splice_init(&root->fs_info->ordered_extents, &splice); | 319 | list_splice_init(&root->fs_info->ordered_extents, &splice); |
| 317 | while(!list_empty(&splice)) { | 320 | list_for_each_safe(cur, tmp, &splice) { |
| 318 | cur = splice.next; | 321 | cur = splice.next; |
| 319 | ordered = list_entry(cur, struct btrfs_ordered_extent, | 322 | ordered = list_entry(cur, struct btrfs_ordered_extent, |
| 320 | root_extent_list); | 323 | root_extent_list); |
| 324 | if (nocow_only && | ||
| 325 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { | ||
| 326 | cond_resched_lock(&root->fs_info->ordered_extent_lock); | ||
| 327 | continue; | ||
| 328 | } | ||
| 329 | |||
| 321 | list_del_init(&ordered->root_extent_list); | 330 | list_del_init(&ordered->root_extent_list); |
| 322 | atomic_inc(&ordered->refs); | 331 | atomic_inc(&ordered->refs); |
| 323 | inode = ordered->inode; | 332 | inode = ordered->inode; |
| @@ -338,6 +347,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) | |||
| 338 | 347 | ||
| 339 | spin_lock(&root->fs_info->ordered_extent_lock); | 348 | spin_lock(&root->fs_info->ordered_extent_lock); |
| 340 | } | 349 | } |
| 350 | list_splice_init(&splice, &root->fs_info->ordered_extents); | ||
| 341 | spin_unlock(&root->fs_info->ordered_extent_lock); | 351 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 342 | return 0; | 352 | return 0; |
| 343 | } | 353 | } |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 5efe6b63c74..fd45519f30a 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
| @@ -64,6 +64,8 @@ struct btrfs_ordered_sum { | |||
| 64 | 64 | ||
| 65 | #define BTRFS_ORDERED_COMPLETE 1 /* set when removed from the tree */ | 65 | #define BTRFS_ORDERED_COMPLETE 1 /* set when removed from the tree */ |
| 66 | 66 | ||
| 67 | #define BTRFS_ORDERED_NOCOW 2 /* set when we want to write in place */ | ||
| 68 | |||
| 67 | struct btrfs_ordered_extent { | 69 | struct btrfs_ordered_extent { |
| 68 | /* logical offset in the file */ | 70 | /* logical offset in the file */ |
| 69 | u64 file_offset; | 71 | u64 file_offset; |
| @@ -125,7 +127,7 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
| 125 | int btrfs_dec_test_ordered_pending(struct inode *inode, | 127 | int btrfs_dec_test_ordered_pending(struct inode *inode, |
| 126 | u64 file_offset, u64 io_size); | 128 | u64 file_offset, u64 io_size); |
| 127 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | 129 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, |
| 128 | u64 start, u64 len); | 130 | u64 start, u64 len, int nocow); |
| 129 | int btrfs_add_ordered_sum(struct inode *inode, | 131 | int btrfs_add_ordered_sum(struct inode *inode, |
| 130 | struct btrfs_ordered_extent *entry, | 132 | struct btrfs_ordered_extent *entry, |
| 131 | struct btrfs_ordered_sum *sum); | 133 | struct btrfs_ordered_sum *sum); |
| @@ -143,5 +145,5 @@ int btrfs_wait_on_page_writeback_range(struct address_space *mapping, | |||
| 143 | pgoff_t start, pgoff_t end); | 145 | pgoff_t start, pgoff_t end); |
| 144 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, | 146 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, |
| 145 | loff_t end, int sync_mode); | 147 | loff_t end, int sync_mode); |
| 146 | int btrfs_wait_ordered_extents(struct btrfs_root *root); | 148 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only); |
| 147 | #endif | 149 | #endif |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index ebf5362da1d..9d3d08e9f8d 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -438,6 +438,7 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
| 438 | 438 | ||
| 439 | free_extent_buffer(root->commit_root); | 439 | free_extent_buffer(root->commit_root); |
| 440 | root->commit_root = NULL; | 440 | root->commit_root = NULL; |
| 441 | root->dirty_root = NULL; | ||
| 441 | 442 | ||
| 442 | spin_lock(&root->list_lock); | 443 | spin_lock(&root->list_lock); |
| 443 | list_del_init(&dirty->root->dead_list); | 444 | list_del_init(&dirty->root->dead_list); |
| @@ -461,6 +462,7 @@ static noinline int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
| 461 | sizeof(struct btrfs_disk_key)); | 462 | sizeof(struct btrfs_disk_key)); |
| 462 | root->root_item.drop_level = 0; | 463 | root->root_item.drop_level = 0; |
| 463 | root->commit_root = NULL; | 464 | root->commit_root = NULL; |
| 465 | root->dirty_root = NULL; | ||
| 464 | root->root_key.offset = root->fs_info->generation; | 466 | root->root_key.offset = root->fs_info->generation; |
| 465 | btrfs_set_root_bytenr(&root->root_item, | 467 | btrfs_set_root_bytenr(&root->root_item, |
| 466 | root->node->start); | 468 | root->node->start); |
| @@ -762,7 +764,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 762 | } | 764 | } |
| 763 | 765 | ||
| 764 | do { | 766 | do { |
| 767 | int snap_pending = 0; | ||
| 765 | joined = cur_trans->num_joined; | 768 | joined = cur_trans->num_joined; |
| 769 | if (!list_empty(&trans->transaction->pending_snapshots)) | ||
| 770 | snap_pending = 1; | ||
| 771 | |||
| 766 | WARN_ON(cur_trans != trans->transaction); | 772 | WARN_ON(cur_trans != trans->transaction); |
| 767 | prepare_to_wait(&cur_trans->writer_wait, &wait, | 773 | prepare_to_wait(&cur_trans->writer_wait, &wait, |
| 768 | TASK_UNINTERRUPTIBLE); | 774 | TASK_UNINTERRUPTIBLE); |
| @@ -774,6 +780,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 774 | 780 | ||
| 775 | mutex_unlock(&root->fs_info->trans_mutex); | 781 | mutex_unlock(&root->fs_info->trans_mutex); |
| 776 | 782 | ||
| 783 | if (snap_pending) { | ||
| 784 | ret = btrfs_wait_ordered_extents(root, 1); | ||
| 785 | BUG_ON(ret); | ||
| 786 | } | ||
| 787 | |||
| 777 | schedule_timeout(timeout); | 788 | schedule_timeout(timeout); |
| 778 | 789 | ||
| 779 | mutex_lock(&root->fs_info->trans_mutex); | 790 | mutex_lock(&root->fs_info->trans_mutex); |
