aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-04-05 16:51:15 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:34 -0400
commit09a2a8f96e3009273bed1833b3f210e2c68728a5 (patch)
treef4742a6e962991e9f7b0252805186466f5a005c6
parentcc95bef635a649d595cf8d1cd4fcff5b6bf13023 (diff)
Btrfs: fix bad extent logging
A user sent me a btrfs-image of a file system that was panicing on mount during the log recovery. I had originally thought these problems were from a bug in the free space cache code, but that was just a symptom of the problem. The problem is if your application does something like this [prealloc][prealloc][prealloc] the internal extent maps will merge those all together into one extent map, even though on disk they are 3 separate extents. So if you go to write into one of these ranges the extent map will be right since we use the physical extent when doing the write, but when we log the extents they will use the wrong sizes for the remainder prealloc space. If this doesn't happen to trip up the free space cache (which it won't in a lot of cases) then you will get bogus entries in your extent tree which will screw stuff up later. The data and such will still work, but everything else is broken. This patch fixes this by not allowing extents that are on the modified list to be merged. This has the side effect that we are no longer adding everything to the modified list all the time, which means we now have to call btrfs_drop_extents every time we log an extent into the tree. So this allows me to drop all this speciality code I was using to get around calling btrfs_drop_extents. With this patch the testcase I've created no longer creates a bogus file system after replaying the log. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
-rw-r--r--fs/btrfs/ctree.c140
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent_map.c18
-rw-r--r--fs/btrfs/extent_map.h2
-rw-r--r--fs/btrfs/file.c14
-rw-r--r--fs/btrfs/inode.c34
-rw-r--r--fs/btrfs/relocation.c2
-rw-r--r--fs/btrfs/tree-log.c144
-rw-r--r--fs/btrfs/volumes.c4
10 files changed, 40 insertions, 324 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index fe032ab6bd8a..9ca0f6aefa22 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2211,9 +2211,6 @@ static noinline void unlock_up(struct btrfs_path *path, int level,
2211 int no_skips = 0; 2211 int no_skips = 0;
2212 struct extent_buffer *t; 2212 struct extent_buffer *t;
2213 2213
2214 if (path->really_keep_locks)
2215 return;
2216
2217 for (i = level; i < BTRFS_MAX_LEVEL; i++) { 2214 for (i = level; i < BTRFS_MAX_LEVEL; i++) {
2218 if (!path->nodes[i]) 2215 if (!path->nodes[i])
2219 break; 2216 break;
@@ -2261,7 +2258,7 @@ noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level)
2261{ 2258{
2262 int i; 2259 int i;
2263 2260
2264 if (path->keep_locks || path->really_keep_locks) 2261 if (path->keep_locks)
2265 return; 2262 return;
2266 2263
2267 for (i = level; i < BTRFS_MAX_LEVEL; i++) { 2264 for (i = level; i < BTRFS_MAX_LEVEL; i++) {
@@ -2494,7 +2491,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
2494 if (!cow) 2491 if (!cow)
2495 write_lock_level = -1; 2492 write_lock_level = -1;
2496 2493
2497 if (cow && (p->really_keep_locks || p->keep_locks || p->lowest_level)) 2494 if (cow && (p->keep_locks || p->lowest_level))
2498 write_lock_level = BTRFS_MAX_LEVEL; 2495 write_lock_level = BTRFS_MAX_LEVEL;
2499 2496
2500 min_write_lock_level = write_lock_level; 2497 min_write_lock_level = write_lock_level;
@@ -5465,139 +5462,6 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
5465 return btrfs_next_old_leaf(root, path, 0); 5462 return btrfs_next_old_leaf(root, path, 0);
5466} 5463}
5467 5464
5468/* Release the path up to but not including the given level */
5469static void btrfs_release_level(struct btrfs_path *path, int level)
5470{
5471 int i;
5472
5473 for (i = 0; i < level; i++) {
5474 path->slots[i] = 0;
5475 if (!path->nodes[i])
5476 continue;
5477 if (path->locks[i]) {
5478 btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
5479 path->locks[i] = 0;
5480 }
5481 free_extent_buffer(path->nodes[i]);
5482 path->nodes[i] = NULL;
5483 }
5484}
5485
5486/*
5487 * This function assumes 2 things
5488 *
5489 * 1) You are using path->keep_locks
5490 * 2) You are not inserting items.
5491 *
5492 * If either of these are not true do not use this function. If you need a next
5493 * leaf with either of these not being true then this function can be easily
5494 * adapted to do that, but at the moment these are the limitations.
5495 */
5496int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
5497 struct btrfs_root *root, struct btrfs_path *path,
5498 int del)
5499{
5500 struct extent_buffer *b;
5501 struct btrfs_key key;
5502 u32 nritems;
5503 int level = 1;
5504 int slot;
5505 int ret = 1;
5506 int write_lock_level = BTRFS_MAX_LEVEL;
5507 int ins_len = del ? -1 : 0;
5508
5509 WARN_ON(!(path->keep_locks || path->really_keep_locks));
5510
5511 nritems = btrfs_header_nritems(path->nodes[0]);
5512 btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
5513
5514 while (path->nodes[level]) {
5515 nritems = btrfs_header_nritems(path->nodes[level]);
5516 if (!(path->locks[level] & BTRFS_WRITE_LOCK)) {
5517search:
5518 btrfs_release_path(path);
5519 ret = btrfs_search_slot(trans, root, &key, path,
5520 ins_len, 1);
5521 if (ret < 0)
5522 goto out;
5523 level = 1;
5524 continue;
5525 }
5526
5527 if (path->slots[level] >= nritems - 1) {
5528 level++;
5529 continue;
5530 }
5531
5532 btrfs_release_level(path, level);
5533 break;
5534 }
5535
5536 if (!path->nodes[level]) {
5537 ret = 1;
5538 goto out;
5539 }
5540
5541 path->slots[level]++;
5542 b = path->nodes[level];
5543
5544 while (b) {
5545 level = btrfs_header_level(b);
5546
5547 if (!should_cow_block(trans, root, b))
5548 goto cow_done;
5549
5550 btrfs_set_path_blocking(path);
5551 ret = btrfs_cow_block(trans, root, b,
5552 path->nodes[level + 1],
5553 path->slots[level + 1], &b);
5554 if (ret)
5555 goto out;
5556cow_done:
5557 path->nodes[level] = b;
5558 btrfs_clear_path_blocking(path, NULL, 0);
5559 if (level != 0) {
5560 ret = setup_nodes_for_search(trans, root, path, b,
5561 level, ins_len,
5562 &write_lock_level);
5563 if (ret == -EAGAIN)
5564 goto search;
5565 if (ret)
5566 goto out;
5567
5568 b = path->nodes[level];
5569 slot = path->slots[level];
5570
5571 ret = read_block_for_search(trans, root, path,
5572 &b, level, slot, &key, 0);
5573 if (ret == -EAGAIN)
5574 goto search;
5575 if (ret)
5576 goto out;
5577 level = btrfs_header_level(b);
5578 if (!btrfs_try_tree_write_lock(b)) {
5579 btrfs_set_path_blocking(path);
5580 btrfs_tree_lock(b);
5581 btrfs_clear_path_blocking(path, b,
5582 BTRFS_WRITE_LOCK);
5583 }
5584 path->locks[level] = BTRFS_WRITE_LOCK;
5585 path->nodes[level] = b;
5586 path->slots[level] = 0;
5587 } else {
5588 path->slots[level] = 0;
5589 ret = 0;
5590 break;
5591 }
5592 }
5593
5594out:
5595 if (ret)
5596 btrfs_release_path(path);
5597
5598 return ret;
5599}
5600
5601int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, 5465int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
5602 u64 time_seq) 5466 u64 time_seq)
5603{ 5467{
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 5060990336a8..075a8a0e49c4 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -586,7 +586,6 @@ struct btrfs_path {
586 unsigned int skip_locking:1; 586 unsigned int skip_locking:1;
587 unsigned int leave_spinning:1; 587 unsigned int leave_spinning:1;
588 unsigned int search_commit_root:1; 588 unsigned int search_commit_root:1;
589 unsigned int really_keep_locks:1;
590}; 589};
591 590
592/* 591/*
@@ -3273,9 +3272,6 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
3273} 3272}
3274 3273
3275int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); 3274int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
3276int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
3277 struct btrfs_root *root, struct btrfs_path *path,
3278 int del);
3279int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, 3275int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
3280 u64 time_seq); 3276 u64 time_seq);
3281static inline int btrfs_next_old_item(struct btrfs_root *root, 3277static inline int btrfs_next_old_item(struct btrfs_root *root,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b8ed1d4fe509..70e6b0c32db2 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -222,7 +222,7 @@ static struct extent_map *btree_get_extent(struct inode *inode,
222 em->bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; 222 em->bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
223 223
224 write_lock(&em_tree->lock); 224 write_lock(&em_tree->lock);
225 ret = add_extent_mapping(em_tree, em); 225 ret = add_extent_mapping(em_tree, em, 0);
226 if (ret == -EEXIST) { 226 if (ret == -EEXIST) {
227 free_extent_map(em); 227 free_extent_map(em);
228 em = lookup_extent_mapping(em_tree, start, len); 228 em = lookup_extent_mapping(em_tree, start, len);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 2834ca5768ea..ca968742c3db 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -174,6 +174,14 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next)
174 test_bit(EXTENT_FLAG_LOGGING, &next->flags)) 174 test_bit(EXTENT_FLAG_LOGGING, &next->flags))
175 return 0; 175 return 0;
176 176
177 /*
178 * We don't want to merge stuff that hasn't been written to the log yet
179 * since it may not reflect exactly what is on disk, and that would be
180 * bad.
181 */
182 if (!list_empty(&prev->list) || !list_empty(&next->list))
183 return 0;
184
177 if (extent_map_end(prev) == next->start && 185 if (extent_map_end(prev) == next->start &&
178 prev->flags == next->flags && 186 prev->flags == next->flags &&
179 prev->bdev == next->bdev && 187 prev->bdev == next->bdev &&
@@ -209,9 +217,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
209 em->mod_len = (em->mod_len + em->mod_start) - merge->mod_start; 217 em->mod_len = (em->mod_len + em->mod_start) - merge->mod_start;
210 em->mod_start = merge->mod_start; 218 em->mod_start = merge->mod_start;
211 em->generation = max(em->generation, merge->generation); 219 em->generation = max(em->generation, merge->generation);
212 list_move(&em->list, &tree->modified_extents);
213 220
214 list_del_init(&merge->list);
215 rb_erase(&merge->rb_node, &tree->map); 221 rb_erase(&merge->rb_node, &tree->map);
216 free_extent_map(merge); 222 free_extent_map(merge);
217 } 223 }
@@ -227,7 +233,6 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
227 merge->in_tree = 0; 233 merge->in_tree = 0;
228 em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start; 234 em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
229 em->generation = max(em->generation, merge->generation); 235 em->generation = max(em->generation, merge->generation);
230 list_del_init(&merge->list);
231 free_extent_map(merge); 236 free_extent_map(merge);
232 } 237 }
233} 238}
@@ -302,7 +307,7 @@ void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)
302 * reference dropped if the merge attempt was successful. 307 * reference dropped if the merge attempt was successful.
303 */ 308 */
304int add_extent_mapping(struct extent_map_tree *tree, 309int add_extent_mapping(struct extent_map_tree *tree,
305 struct extent_map *em) 310 struct extent_map *em, int modified)
306{ 311{
307 int ret = 0; 312 int ret = 0;
308 struct rb_node *rb; 313 struct rb_node *rb;
@@ -324,7 +329,10 @@ int add_extent_mapping(struct extent_map_tree *tree,
324 em->mod_start = em->start; 329 em->mod_start = em->start;
325 em->mod_len = em->len; 330 em->mod_len = em->len;
326 331
327 try_merge_map(tree, em); 332 if (modified)
333 list_move(&em->list, &tree->modified_extents);
334 else
335 try_merge_map(tree, em);
328out: 336out:
329 return ret; 337 return ret;
330} 338}
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index b18314bc5a6e..61adc44b7805 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -62,7 +62,7 @@ void extent_map_tree_init(struct extent_map_tree *tree);
62struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, 62struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree,
63 u64 start, u64 len); 63 u64 start, u64 len);
64int add_extent_mapping(struct extent_map_tree *tree, 64int add_extent_mapping(struct extent_map_tree *tree,
65 struct extent_map *em); 65 struct extent_map *em, int modified);
66int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); 66int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em);
67 67
68struct extent_map *alloc_extent_map(void); 68struct extent_map *alloc_extent_map(void);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index e81e428a8840..a56abed78104 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -552,6 +552,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
552 int testend = 1; 552 int testend = 1;
553 unsigned long flags; 553 unsigned long flags;
554 int compressed = 0; 554 int compressed = 0;
555 bool modified;
555 556
556 WARN_ON(end < start); 557 WARN_ON(end < start);
557 if (end == (u64)-1) { 558 if (end == (u64)-1) {
@@ -561,6 +562,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
561 while (1) { 562 while (1) {
562 int no_splits = 0; 563 int no_splits = 0;
563 564
565 modified = false;
564 if (!split) 566 if (!split)
565 split = alloc_extent_map(); 567 split = alloc_extent_map();
566 if (!split2) 568 if (!split2)
@@ -592,6 +594,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
592 compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); 594 compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
593 clear_bit(EXTENT_FLAG_PINNED, &em->flags); 595 clear_bit(EXTENT_FLAG_PINNED, &em->flags);
594 clear_bit(EXTENT_FLAG_LOGGING, &flags); 596 clear_bit(EXTENT_FLAG_LOGGING, &flags);
597 modified = !list_empty(&em->list);
595 remove_extent_mapping(em_tree, em); 598 remove_extent_mapping(em_tree, em);
596 if (no_splits) 599 if (no_splits)
597 goto next; 600 goto next;
@@ -614,9 +617,8 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
614 split->bdev = em->bdev; 617 split->bdev = em->bdev;
615 split->flags = flags; 618 split->flags = flags;
616 split->compress_type = em->compress_type; 619 split->compress_type = em->compress_type;
617 ret = add_extent_mapping(em_tree, split); 620 ret = add_extent_mapping(em_tree, split, modified);
618 BUG_ON(ret); /* Logic error */ 621 BUG_ON(ret); /* Logic error */
619 list_move(&split->list, &em_tree->modified_extents);
620 free_extent_map(split); 622 free_extent_map(split);
621 split = split2; 623 split = split2;
622 split2 = NULL; 624 split2 = NULL;
@@ -645,9 +647,8 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
645 split->orig_start = em->orig_start; 647 split->orig_start = em->orig_start;
646 } 648 }
647 649
648 ret = add_extent_mapping(em_tree, split); 650 ret = add_extent_mapping(em_tree, split, modified);
649 BUG_ON(ret); /* Logic error */ 651 BUG_ON(ret); /* Logic error */
650 list_move(&split->list, &em_tree->modified_extents);
651 free_extent_map(split); 652 free_extent_map(split);
652 split = NULL; 653 split = NULL;
653 } 654 }
@@ -1930,10 +1931,7 @@ out:
1930 do { 1931 do {
1931 btrfs_drop_extent_cache(inode, offset, end - 1, 0); 1932 btrfs_drop_extent_cache(inode, offset, end - 1, 0);
1932 write_lock(&em_tree->lock); 1933 write_lock(&em_tree->lock);
1933 ret = add_extent_mapping(em_tree, hole_em); 1934 ret = add_extent_mapping(em_tree, hole_em, 1);
1934 if (!ret)
1935 list_move(&hole_em->list,
1936 &em_tree->modified_extents);
1937 write_unlock(&em_tree->lock); 1935 write_unlock(&em_tree->lock);
1938 } while (ret == -EEXIST); 1936 } while (ret == -EEXIST);
1939 free_extent_map(hole_em); 1937 free_extent_map(hole_em);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 456667b04fe6..c41637a1ed38 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -732,10 +732,7 @@ retry:
732 732
733 while (1) { 733 while (1) {
734 write_lock(&em_tree->lock); 734 write_lock(&em_tree->lock);
735 ret = add_extent_mapping(em_tree, em); 735 ret = add_extent_mapping(em_tree, em, 1);
736 if (!ret)
737 list_move(&em->list,
738 &em_tree->modified_extents);
739 write_unlock(&em_tree->lock); 736 write_unlock(&em_tree->lock);
740 if (ret != -EEXIST) { 737 if (ret != -EEXIST) {
741 free_extent_map(em); 738 free_extent_map(em);
@@ -941,10 +938,7 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
941 938
942 while (1) { 939 while (1) {
943 write_lock(&em_tree->lock); 940 write_lock(&em_tree->lock);
944 ret = add_extent_mapping(em_tree, em); 941 ret = add_extent_mapping(em_tree, em, 1);
945 if (!ret)
946 list_move(&em->list,
947 &em_tree->modified_extents);
948 write_unlock(&em_tree->lock); 942 write_unlock(&em_tree->lock);
949 if (ret != -EEXIST) { 943 if (ret != -EEXIST) {
950 free_extent_map(em); 944 free_extent_map(em);
@@ -1387,10 +1381,7 @@ out_check:
1387 em->generation = -1; 1381 em->generation = -1;
1388 while (1) { 1382 while (1) {
1389 write_lock(&em_tree->lock); 1383 write_lock(&em_tree->lock);
1390 ret = add_extent_mapping(em_tree, em); 1384 ret = add_extent_mapping(em_tree, em, 1);
1391 if (!ret)
1392 list_move(&em->list,
1393 &em_tree->modified_extents);
1394 write_unlock(&em_tree->lock); 1385 write_unlock(&em_tree->lock);
1395 if (ret != -EEXIST) { 1386 if (ret != -EEXIST) {
1396 free_extent_map(em); 1387 free_extent_map(em);
@@ -4467,10 +4458,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
4467 4458
4468 while (1) { 4459 while (1) {
4469 write_lock(&em_tree->lock); 4460 write_lock(&em_tree->lock);
4470 err = add_extent_mapping(em_tree, hole_em); 4461 err = add_extent_mapping(em_tree, hole_em, 1);
4471 if (!err)
4472 list_move(&hole_em->list,
4473 &em_tree->modified_extents);
4474 write_unlock(&em_tree->lock); 4462 write_unlock(&em_tree->lock);
4475 if (err != -EEXIST) 4463 if (err != -EEXIST)
4476 break; 4464 break;
@@ -5989,7 +5977,7 @@ static int merge_extent_mapping(struct extent_map_tree *em_tree,
5989 em->block_start += start_diff; 5977 em->block_start += start_diff;
5990 em->block_len -= start_diff; 5978 em->block_len -= start_diff;
5991 } 5979 }
5992 return add_extent_mapping(em_tree, em); 5980 return add_extent_mapping(em_tree, em, 0);
5993} 5981}
5994 5982
5995static noinline int uncompress_inline(struct btrfs_path *path, 5983static noinline int uncompress_inline(struct btrfs_path *path,
@@ -6283,7 +6271,7 @@ insert:
6283 6271
6284 err = 0; 6272 err = 0;
6285 write_lock(&em_tree->lock); 6273 write_lock(&em_tree->lock);
6286 ret = add_extent_mapping(em_tree, em); 6274 ret = add_extent_mapping(em_tree, em, 0);
6287 /* it is possible that someone inserted the extent into the tree 6275 /* it is possible that someone inserted the extent into the tree
6288 * while we had the lock dropped. It is also possible that 6276 * while we had the lock dropped. It is also possible that
6289 * an overlapping map exists in the tree 6277 * an overlapping map exists in the tree
@@ -6706,10 +6694,7 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
6706 btrfs_drop_extent_cache(inode, em->start, 6694 btrfs_drop_extent_cache(inode, em->start,
6707 em->start + em->len - 1, 0); 6695 em->start + em->len - 1, 0);
6708 write_lock(&em_tree->lock); 6696 write_lock(&em_tree->lock);
6709 ret = add_extent_mapping(em_tree, em); 6697 ret = add_extent_mapping(em_tree, em, 1);
6710 if (!ret)
6711 list_move(&em->list,
6712 &em_tree->modified_extents);
6713 write_unlock(&em_tree->lock); 6698 write_unlock(&em_tree->lock);
6714 } while (ret == -EEXIST); 6699 } while (ret == -EEXIST);
6715 6700
@@ -8593,10 +8578,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
8593 8578
8594 while (1) { 8579 while (1) {
8595 write_lock(&em_tree->lock); 8580 write_lock(&em_tree->lock);
8596 ret = add_extent_mapping(em_tree, em); 8581 ret = add_extent_mapping(em_tree, em, 1);
8597 if (!ret)
8598 list_move(&em->list,
8599 &em_tree->modified_extents);
8600 write_unlock(&em_tree->lock); 8582 write_unlock(&em_tree->lock);
8601 if (ret != -EEXIST) 8583 if (ret != -EEXIST)
8602 break; 8584 break;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 4ef5f7455fb3..208154986c4c 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2979,7 +2979,7 @@ int setup_extent_mapping(struct inode *inode, u64 start, u64 end,
2979 lock_extent(&BTRFS_I(inode)->io_tree, start, end); 2979 lock_extent(&BTRFS_I(inode)->io_tree, start, end);
2980 while (1) { 2980 while (1) {
2981 write_lock(&em_tree->lock); 2981 write_lock(&em_tree->lock);
2982 ret = add_extent_mapping(em_tree, em); 2982 ret = add_extent_mapping(em_tree, em, 0);
2983 write_unlock(&em_tree->lock); 2983 write_unlock(&em_tree->lock);
2984 if (ret != -EEXIST) { 2984 if (ret != -EEXIST) {
2985 free_extent_map(em); 2985 free_extent_map(em);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 592aa654b5f3..b069fafbc3de 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3209,115 +3209,6 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)
3209 return 0; 3209 return 0;
3210} 3210}
3211 3211
3212static int drop_adjacent_extents(struct btrfs_trans_handle *trans,
3213 struct btrfs_root *root, struct inode *inode,
3214 struct extent_map *em,
3215 struct btrfs_path *path)
3216{
3217 struct btrfs_file_extent_item *fi;
3218 struct extent_buffer *leaf;
3219 struct btrfs_key key, new_key;
3220 struct btrfs_map_token token;
3221 u64 extent_end;
3222 u64 extent_offset = 0;
3223 int extent_type;
3224 int del_slot = 0;
3225 int del_nr = 0;
3226 int ret = 0;
3227
3228 while (1) {
3229 btrfs_init_map_token(&token);
3230 leaf = path->nodes[0];
3231 path->slots[0]++;
3232 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
3233 if (del_nr) {
3234 ret = btrfs_del_items(trans, root, path,
3235 del_slot, del_nr);
3236 if (ret)
3237 return ret;
3238 del_nr = 0;
3239 }
3240
3241 ret = btrfs_next_leaf_write(trans, root, path, 1);
3242 if (ret < 0)
3243 return ret;
3244 if (ret > 0)
3245 return 0;
3246 leaf = path->nodes[0];
3247 }
3248
3249 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
3250 if (key.objectid != btrfs_ino(inode) ||
3251 key.type != BTRFS_EXTENT_DATA_KEY ||
3252 key.offset >= em->start + em->len)
3253 break;
3254
3255 fi = btrfs_item_ptr(leaf, path->slots[0],
3256 struct btrfs_file_extent_item);
3257 extent_type = btrfs_token_file_extent_type(leaf, fi, &token);
3258 if (extent_type == BTRFS_FILE_EXTENT_REG ||
3259 extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
3260 extent_offset = btrfs_token_file_extent_offset(leaf,
3261 fi, &token);
3262 extent_end = key.offset +
3263 btrfs_token_file_extent_num_bytes(leaf, fi,
3264 &token);
3265 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
3266 extent_end = key.offset +
3267 btrfs_file_extent_inline_len(leaf, fi);
3268 } else {
3269 BUG();
3270 }
3271
3272 if (extent_end <= em->len + em->start) {
3273 if (!del_nr) {
3274 del_slot = path->slots[0];
3275 }
3276 del_nr++;
3277 continue;
3278 }
3279
3280 /*
3281 * Ok so we'll ignore previous items if we log a new extent,
3282 * which can lead to overlapping extents, so if we have an
3283 * existing extent we want to adjust we _have_ to check the next
3284 * guy to make sure we even need this extent anymore, this keeps
3285 * us from panicing in set_item_key_safe.
3286 */
3287 if (path->slots[0] < btrfs_header_nritems(leaf) - 1) {
3288 struct btrfs_key tmp_key;
3289
3290 btrfs_item_key_to_cpu(leaf, &tmp_key,
3291 path->slots[0] + 1);
3292 if (tmp_key.objectid == btrfs_ino(inode) &&
3293 tmp_key.type == BTRFS_EXTENT_DATA_KEY &&
3294 tmp_key.offset <= em->start + em->len) {
3295 if (!del_nr)
3296 del_slot = path->slots[0];
3297 del_nr++;
3298 continue;
3299 }
3300 }
3301
3302 BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
3303 memcpy(&new_key, &key, sizeof(new_key));
3304 new_key.offset = em->start + em->len;
3305 btrfs_set_item_key_safe(trans, root, path, &new_key);
3306 extent_offset += em->start + em->len - key.offset;
3307 btrfs_set_token_file_extent_offset(leaf, fi, extent_offset,
3308 &token);
3309 btrfs_set_token_file_extent_num_bytes(leaf, fi, extent_end -
3310 (em->start + em->len),
3311 &token);
3312 btrfs_mark_buffer_dirty(leaf);
3313 }
3314
3315 if (del_nr)
3316 ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
3317
3318 return ret;
3319}
3320
3321static int log_one_extent(struct btrfs_trans_handle *trans, 3212static int log_one_extent(struct btrfs_trans_handle *trans,
3322 struct inode *inode, struct btrfs_root *root, 3213 struct inode *inode, struct btrfs_root *root,
3323 struct extent_map *em, struct btrfs_path *path) 3214 struct extent_map *em, struct btrfs_path *path)
@@ -3339,39 +3230,24 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
3339 int index = log->log_transid % 2; 3230 int index = log->log_transid % 2;
3340 bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; 3231 bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
3341 3232
3342insert: 3233 ret = __btrfs_drop_extents(trans, log, inode, path, em->start,
3234 em->start + em->len, NULL, 0);
3235 if (ret)
3236 return ret;
3237
3343 INIT_LIST_HEAD(&ordered_sums); 3238 INIT_LIST_HEAD(&ordered_sums);
3344 btrfs_init_map_token(&token); 3239 btrfs_init_map_token(&token);
3345 key.objectid = btrfs_ino(inode); 3240 key.objectid = btrfs_ino(inode);
3346 key.type = BTRFS_EXTENT_DATA_KEY; 3241 key.type = BTRFS_EXTENT_DATA_KEY;
3347 key.offset = em->start; 3242 key.offset = em->start;
3348 path->really_keep_locks = 1;
3349 3243
3350 ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi)); 3244 ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi));
3351 if (ret && ret != -EEXIST) { 3245 if (ret)
3352 path->really_keep_locks = 0;
3353 return ret; 3246 return ret;
3354 }
3355 leaf = path->nodes[0]; 3247 leaf = path->nodes[0];
3356 fi = btrfs_item_ptr(leaf, path->slots[0], 3248 fi = btrfs_item_ptr(leaf, path->slots[0],
3357 struct btrfs_file_extent_item); 3249 struct btrfs_file_extent_item);
3358 3250
3359 /*
3360 * If we are overwriting an inline extent with a real one then we need
3361 * to just delete the inline extent as it may not be large enough to
3362 * have the entire file_extent_item.
3363 */
3364 if (ret && btrfs_token_file_extent_type(leaf, fi, &token) ==
3365 BTRFS_FILE_EXTENT_INLINE) {
3366 ret = btrfs_del_item(trans, log, path);
3367 btrfs_release_path(path);
3368 if (ret) {
3369 path->really_keep_locks = 0;
3370 return ret;
3371 }
3372 goto insert;
3373 }
3374
3375 btrfs_set_token_file_extent_generation(leaf, fi, em->generation, 3251 btrfs_set_token_file_extent_generation(leaf, fi, em->generation,
3376 &token); 3252 &token);
3377 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) { 3253 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
@@ -3417,15 +3293,7 @@ insert:
3417 btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token); 3293 btrfs_set_token_file_extent_other_encoding(leaf, fi, 0, &token);
3418 btrfs_mark_buffer_dirty(leaf); 3294 btrfs_mark_buffer_dirty(leaf);
3419 3295
3420 /*
3421 * Have to check the extent to the right of us to make sure it doesn't
3422 * fall in our current range. We're ok if the previous extent is in our
3423 * range since the recovery stuff will run us in key order and thus just
3424 * drop the part we overwrote.
3425 */
3426 ret = drop_adjacent_extents(trans, log, inode, em, path);
3427 btrfs_release_path(path); 3296 btrfs_release_path(path);
3428 path->really_keep_locks = 0;
3429 if (ret) { 3297 if (ret) {
3430 return ret; 3298 return ret;
3431 } 3299 }
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 3994767ece4d..0d7ab7eab2a2 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3932,7 +3932,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
3932 3932
3933 em_tree = &extent_root->fs_info->mapping_tree.map_tree; 3933 em_tree = &extent_root->fs_info->mapping_tree.map_tree;
3934 write_lock(&em_tree->lock); 3934 write_lock(&em_tree->lock);
3935 ret = add_extent_mapping(em_tree, em); 3935 ret = add_extent_mapping(em_tree, em, 0);
3936 write_unlock(&em_tree->lock); 3936 write_unlock(&em_tree->lock);
3937 if (ret) { 3937 if (ret) {
3938 free_extent_map(em); 3938 free_extent_map(em);
@@ -5476,7 +5476,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
5476 } 5476 }
5477 5477
5478 write_lock(&map_tree->map_tree.lock); 5478 write_lock(&map_tree->map_tree.lock);
5479 ret = add_extent_mapping(&map_tree->map_tree, em); 5479 ret = add_extent_mapping(&map_tree->map_tree, em, 0);
5480 write_unlock(&map_tree->map_tree.lock); 5480 write_unlock(&map_tree->map_tree.lock);
5481 BUG_ON(ret); /* Tree corruption */ 5481 BUG_ON(ret); /* Tree corruption */
5482 free_extent_map(em); 5482 free_extent_map(em);