diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 202008ec367d..81296c57405a 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -33,6 +33,8 @@ | |||
33 | 33 | ||
34 | static int link_free_space(struct btrfs_free_space_ctl *ctl, | 34 | static int link_free_space(struct btrfs_free_space_ctl *ctl, |
35 | struct btrfs_free_space *info); | 35 | struct btrfs_free_space *info); |
36 | static void unlink_free_space(struct btrfs_free_space_ctl *ctl, | ||
37 | struct btrfs_free_space *info); | ||
36 | 38 | ||
37 | static struct inode *__lookup_free_space_inode(struct btrfs_root *root, | 39 | static struct inode *__lookup_free_space_inode(struct btrfs_root *root, |
38 | struct btrfs_path *path, | 40 | struct btrfs_path *path, |
@@ -75,7 +77,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root, | |||
75 | return ERR_PTR(-ENOENT); | 77 | return ERR_PTR(-ENOENT); |
76 | } | 78 | } |
77 | 79 | ||
78 | inode->i_mapping->flags &= ~__GFP_FS; | 80 | mapping_set_gfp_mask(inode->i_mapping, |
81 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | ||
79 | 82 | ||
80 | return inode; | 83 | return inode; |
81 | } | 84 | } |
@@ -365,7 +368,7 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode, | |||
365 | 368 | ||
366 | static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) | 369 | static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) |
367 | { | 370 | { |
368 | u64 *val; | 371 | __le64 *val; |
369 | 372 | ||
370 | io_ctl_map_page(io_ctl, 1); | 373 | io_ctl_map_page(io_ctl, 1); |
371 | 374 | ||
@@ -388,7 +391,7 @@ static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) | |||
388 | 391 | ||
389 | static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation) | 392 | static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation) |
390 | { | 393 | { |
391 | u64 *gen; | 394 | __le64 *gen; |
392 | 395 | ||
393 | /* | 396 | /* |
394 | * Skip the crc area. If we don't check crcs then we just have a 64bit | 397 | * Skip the crc area. If we don't check crcs then we just have a 64bit |
@@ -584,6 +587,44 @@ static int io_ctl_read_bitmap(struct io_ctl *io_ctl, | |||
584 | return 0; | 587 | return 0; |
585 | } | 588 | } |
586 | 589 | ||
590 | /* | ||
591 | * Since we attach pinned extents after the fact we can have contiguous sections | ||
592 | * of free space that are split up in entries. This poses a problem with the | ||
593 | * tree logging stuff since it could have allocated across what appears to be 2 | ||
594 | * entries since we would have merged the entries when adding the pinned extents | ||
595 | * back to the free space cache. So run through the space cache that we just | ||
596 | * loaded and merge contiguous entries. This will make the log replay stuff not | ||
597 | * blow up and it will make for nicer allocator behavior. | ||
598 | */ | ||
599 | static void merge_space_tree(struct btrfs_free_space_ctl *ctl) | ||
600 | { | ||
601 | struct btrfs_free_space *e, *prev = NULL; | ||
602 | struct rb_node *n; | ||
603 | |||
604 | again: | ||
605 | spin_lock(&ctl->tree_lock); | ||
606 | for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) { | ||
607 | e = rb_entry(n, struct btrfs_free_space, offset_index); | ||
608 | if (!prev) | ||
609 | goto next; | ||
610 | if (e->bitmap || prev->bitmap) | ||
611 | goto next; | ||
612 | if (prev->offset + prev->bytes == e->offset) { | ||
613 | unlink_free_space(ctl, prev); | ||
614 | unlink_free_space(ctl, e); | ||
615 | prev->bytes += e->bytes; | ||
616 | kmem_cache_free(btrfs_free_space_cachep, e); | ||
617 | link_free_space(ctl, prev); | ||
618 | prev = NULL; | ||
619 | spin_unlock(&ctl->tree_lock); | ||
620 | goto again; | ||
621 | } | ||
622 | next: | ||
623 | prev = e; | ||
624 | } | ||
625 | spin_unlock(&ctl->tree_lock); | ||
626 | } | ||
627 | |||
587 | int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, | 628 | int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, |
588 | struct btrfs_free_space_ctl *ctl, | 629 | struct btrfs_free_space_ctl *ctl, |
589 | struct btrfs_path *path, u64 offset) | 630 | struct btrfs_path *path, u64 offset) |
@@ -726,6 +767,7 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, | |||
726 | } | 767 | } |
727 | 768 | ||
728 | io_ctl_drop_pages(&io_ctl); | 769 | io_ctl_drop_pages(&io_ctl); |
770 | merge_space_tree(ctl); | ||
729 | ret = 1; | 771 | ret = 1; |
730 | out: | 772 | out: |
731 | io_ctl_free(&io_ctl); | 773 | io_ctl_free(&io_ctl); |
@@ -972,9 +1014,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
972 | goto out; | 1014 | goto out; |
973 | 1015 | ||
974 | 1016 | ||
975 | ret = filemap_write_and_wait(inode->i_mapping); | 1017 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
976 | if (ret) | ||
977 | goto out; | ||
978 | 1018 | ||
979 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; | 1019 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
980 | key.offset = offset; | 1020 | key.offset = offset; |