diff options
| -rw-r--r-- | fs/btrfs/extent_map.c | 39 | ||||
| -rw-r--r-- | fs/btrfs/extent_map.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 16 |
3 files changed, 45 insertions, 14 deletions
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 64d08f94485d..1874aee69c86 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
| @@ -318,6 +318,20 @@ void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em) | |||
| 318 | try_merge_map(tree, em); | 318 | try_merge_map(tree, em); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static inline void setup_extent_mapping(struct extent_map_tree *tree, | ||
| 322 | struct extent_map *em, | ||
| 323 | int modified) | ||
| 324 | { | ||
| 325 | atomic_inc(&em->refs); | ||
| 326 | em->mod_start = em->start; | ||
| 327 | em->mod_len = em->len; | ||
| 328 | |||
| 329 | if (modified) | ||
| 330 | list_move(&em->list, &tree->modified_extents); | ||
| 331 | else | ||
| 332 | try_merge_map(tree, em); | ||
| 333 | } | ||
| 334 | |||
| 321 | /** | 335 | /** |
| 322 | * add_extent_mapping - add new extent map to the extent tree | 336 | * add_extent_mapping - add new extent map to the extent tree |
| 323 | * @tree: tree to insert new map in | 337 | * @tree: tree to insert new map in |
| @@ -337,15 +351,7 @@ int add_extent_mapping(struct extent_map_tree *tree, | |||
| 337 | if (ret) | 351 | if (ret) |
| 338 | goto out; | 352 | goto out; |
| 339 | 353 | ||
| 340 | atomic_inc(&em->refs); | 354 | setup_extent_mapping(tree, em, modified); |
| 341 | |||
| 342 | em->mod_start = em->start; | ||
| 343 | em->mod_len = em->len; | ||
| 344 | |||
| 345 | if (modified) | ||
| 346 | list_move(&em->list, &tree->modified_extents); | ||
| 347 | else | ||
| 348 | try_merge_map(tree, em); | ||
| 349 | out: | 355 | out: |
| 350 | return ret; | 356 | return ret; |
| 351 | } | 357 | } |
| @@ -432,3 +438,18 @@ int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) | |||
| 432 | RB_CLEAR_NODE(&em->rb_node); | 438 | RB_CLEAR_NODE(&em->rb_node); |
| 433 | return ret; | 439 | return ret; |
| 434 | } | 440 | } |
| 441 | |||
| 442 | void replace_extent_mapping(struct extent_map_tree *tree, | ||
| 443 | struct extent_map *cur, | ||
| 444 | struct extent_map *new, | ||
| 445 | int modified) | ||
| 446 | { | ||
| 447 | WARN_ON(test_bit(EXTENT_FLAG_PINNED, &cur->flags)); | ||
| 448 | ASSERT(extent_map_in_tree(cur)); | ||
| 449 | if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags)) | ||
| 450 | list_del_init(&cur->list); | ||
| 451 | rb_replace_node(&cur->rb_node, &new->rb_node, &tree->map); | ||
| 452 | RB_CLEAR_NODE(&cur->rb_node); | ||
| 453 | |||
| 454 | setup_extent_mapping(tree, new, modified); | ||
| 455 | } | ||
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index f0a645a14d6e..e7fd8a56a140 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
| @@ -68,6 +68,10 @@ struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, | |||
| 68 | int add_extent_mapping(struct extent_map_tree *tree, | 68 | int add_extent_mapping(struct extent_map_tree *tree, |
| 69 | struct extent_map *em, int modified); | 69 | struct extent_map *em, int modified); |
| 70 | int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); | 70 | int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em); |
| 71 | void replace_extent_mapping(struct extent_map_tree *tree, | ||
| 72 | struct extent_map *cur, | ||
| 73 | struct extent_map *new, | ||
| 74 | int modified); | ||
| 71 | 75 | ||
| 72 | struct extent_map *alloc_extent_map(void); | 76 | struct extent_map *alloc_extent_map(void); |
| 73 | void free_extent_map(struct extent_map *em); | 77 | void free_extent_map(struct extent_map *em); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 762ca32bd988..31e48b947060 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -591,7 +591,6 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 591 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | 591 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); |
| 592 | clear_bit(EXTENT_FLAG_LOGGING, &flags); | 592 | clear_bit(EXTENT_FLAG_LOGGING, &flags); |
| 593 | modified = !list_empty(&em->list); | 593 | modified = !list_empty(&em->list); |
| 594 | remove_extent_mapping(em_tree, em); | ||
| 595 | if (no_splits) | 594 | if (no_splits) |
| 596 | goto next; | 595 | goto next; |
| 597 | 596 | ||
| @@ -622,8 +621,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 622 | split->bdev = em->bdev; | 621 | split->bdev = em->bdev; |
| 623 | split->flags = flags; | 622 | split->flags = flags; |
| 624 | split->compress_type = em->compress_type; | 623 | split->compress_type = em->compress_type; |
| 625 | ret = add_extent_mapping(em_tree, split, modified); | 624 | replace_extent_mapping(em_tree, em, split, modified); |
| 626 | BUG_ON(ret); /* Logic error */ | ||
| 627 | free_extent_map(split); | 625 | free_extent_map(split); |
| 628 | split = split2; | 626 | split = split2; |
| 629 | split2 = NULL; | 627 | split2 = NULL; |
| @@ -661,12 +659,20 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
| 661 | split->orig_block_len = 0; | 659 | split->orig_block_len = 0; |
| 662 | } | 660 | } |
| 663 | 661 | ||
| 664 | ret = add_extent_mapping(em_tree, split, modified); | 662 | if (extent_map_in_tree(em)) { |
| 665 | BUG_ON(ret); /* Logic error */ | 663 | replace_extent_mapping(em_tree, em, split, |
| 664 | modified); | ||
| 665 | } else { | ||
| 666 | ret = add_extent_mapping(em_tree, split, | ||
| 667 | modified); | ||
| 668 | ASSERT(ret == 0); /* Logic error */ | ||
| 669 | } | ||
| 666 | free_extent_map(split); | 670 | free_extent_map(split); |
| 667 | split = NULL; | 671 | split = NULL; |
| 668 | } | 672 | } |
| 669 | next: | 673 | next: |
| 674 | if (extent_map_in_tree(em)) | ||
| 675 | remove_extent_mapping(em_tree, em); | ||
| 670 | write_unlock(&em_tree->lock); | 676 | write_unlock(&em_tree->lock); |
| 671 | 677 | ||
| 672 | /* once for us */ | 678 | /* once for us */ |
