diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 20:44:56 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 20:44:56 -0400 |
| commit | d3304cadb2e24517938e24efd58fd9ee6504fefe (patch) | |
| tree | 5bf53a560d3df9c89b5b0d5ed095fc386c91fca4 | |
| parent | 1a892b485f328224b4882818f84fcc0a3208677d (diff) | |
| parent | d9ed71e5457c8c5bf1dc706e06468eab9e2aa87e (diff) | |
Merge branch 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason:
"Some fixes from Omar and Dave Sterba for our new free space tree.
This isn't heavily used yet, but as we move toward making it the new
default we wanted to nail down an endian bug"
* 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
btrfs: tests: uninline member definitions in free_space_extent
btrfs: tests: constify free space extent specs
Btrfs: expand free space tree sanity tests to catch endianness bug
Btrfs: fix extent buffer bitmap tests on big-endian systems
Btrfs: catch invalid free space trees
Btrfs: fix mount -o clear_cache,space_cache=v2
Btrfs: fix free space tree bitmaps on big-endian systems
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 33 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 64 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 22 | ||||
| -rw-r--r-- | fs/btrfs/free-space-tree.c | 19 | ||||
| -rw-r--r-- | fs/btrfs/tests/extent-io-tests.c | 87 | ||||
| -rw-r--r-- | fs/btrfs/tests/free-space-tree-tests.c | 189 | ||||
| -rw-r--r-- | include/uapi/linux/btrfs.h | 12 |
8 files changed, 272 insertions, 157 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6c21bad26a27..0b8ce2b9f7d0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -252,7 +252,8 @@ struct btrfs_super_block { | |||
| 252 | #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL | 252 | #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL |
| 253 | 253 | ||
| 254 | #define BTRFS_FEATURE_COMPAT_RO_SUPP \ | 254 | #define BTRFS_FEATURE_COMPAT_RO_SUPP \ |
| 255 | (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE) | 255 | (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \ |
| 256 | BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID) | ||
| 256 | 257 | ||
| 257 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL | 258 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL |
| 258 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL | 259 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e720d3e6ec20..3a57f99d96aa 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -2586,6 +2586,7 @@ int open_ctree(struct super_block *sb, | |||
| 2586 | int num_backups_tried = 0; | 2586 | int num_backups_tried = 0; |
| 2587 | int backup_index = 0; | 2587 | int backup_index = 0; |
| 2588 | int max_active; | 2588 | int max_active; |
| 2589 | int clear_free_space_tree = 0; | ||
| 2589 | 2590 | ||
| 2590 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL); | 2591 | tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL); |
| 2591 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL); | 2592 | chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL); |
| @@ -3148,6 +3149,26 @@ retry_root_backup: | |||
| 3148 | if (sb->s_flags & MS_RDONLY) | 3149 | if (sb->s_flags & MS_RDONLY) |
| 3149 | return 0; | 3150 | return 0; |
| 3150 | 3151 | ||
| 3152 | if (btrfs_test_opt(fs_info, CLEAR_CACHE) && | ||
| 3153 | btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | ||
| 3154 | clear_free_space_tree = 1; | ||
| 3155 | } else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) && | ||
| 3156 | !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) { | ||
| 3157 | btrfs_warn(fs_info, "free space tree is invalid"); | ||
| 3158 | clear_free_space_tree = 1; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | if (clear_free_space_tree) { | ||
| 3162 | btrfs_info(fs_info, "clearing free space tree"); | ||
| 3163 | ret = btrfs_clear_free_space_tree(fs_info); | ||
| 3164 | if (ret) { | ||
| 3165 | btrfs_warn(fs_info, | ||
| 3166 | "failed to clear free space tree: %d", ret); | ||
| 3167 | close_ctree(tree_root); | ||
| 3168 | return ret; | ||
| 3169 | } | ||
| 3170 | } | ||
| 3171 | |||
| 3151 | if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) && | 3172 | if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) && |
| 3152 | !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | 3173 | !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { |
| 3153 | btrfs_info(fs_info, "creating free space tree"); | 3174 | btrfs_info(fs_info, "creating free space tree"); |
| @@ -3185,18 +3206,6 @@ retry_root_backup: | |||
| 3185 | 3206 | ||
| 3186 | btrfs_qgroup_rescan_resume(fs_info); | 3207 | btrfs_qgroup_rescan_resume(fs_info); |
| 3187 | 3208 | ||
| 3188 | if (btrfs_test_opt(tree_root->fs_info, CLEAR_CACHE) && | ||
| 3189 | btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { | ||
| 3190 | btrfs_info(fs_info, "clearing free space tree"); | ||
| 3191 | ret = btrfs_clear_free_space_tree(fs_info); | ||
| 3192 | if (ret) { | ||
| 3193 | btrfs_warn(fs_info, | ||
| 3194 | "failed to clear free space tree: %d", ret); | ||
| 3195 | close_ctree(tree_root); | ||
| 3196 | return ret; | ||
| 3197 | } | ||
| 3198 | } | ||
| 3199 | |||
| 3200 | if (!fs_info->uuid_root) { | 3209 | if (!fs_info->uuid_root) { |
| 3201 | btrfs_info(fs_info, "creating UUID tree"); | 3210 | btrfs_info(fs_info, "creating UUID tree"); |
| 3202 | ret = btrfs_create_uuid_tree(fs_info); | 3211 | ret = btrfs_create_uuid_tree(fs_info); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index ee40384c394d..66a755150056 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -5558,17 +5558,45 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, | |||
| 5558 | } | 5558 | } |
| 5559 | } | 5559 | } |
| 5560 | 5560 | ||
| 5561 | /* | 5561 | void le_bitmap_set(u8 *map, unsigned int start, int len) |
| 5562 | * The extent buffer bitmap operations are done with byte granularity because | 5562 | { |
| 5563 | * bitmap items are not guaranteed to be aligned to a word and therefore a | 5563 | u8 *p = map + BIT_BYTE(start); |
| 5564 | * single word in a bitmap may straddle two pages in the extent buffer. | 5564 | const unsigned int size = start + len; |
| 5565 | */ | 5565 | int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE); |
| 5566 | #define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE) | 5566 | u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start); |
| 5567 | #define BYTE_MASK ((1 << BITS_PER_BYTE) - 1) | 5567 | |
| 5568 | #define BITMAP_FIRST_BYTE_MASK(start) \ | 5568 | while (len - bits_to_set >= 0) { |
| 5569 | ((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK) | 5569 | *p |= mask_to_set; |
| 5570 | #define BITMAP_LAST_BYTE_MASK(nbits) \ | 5570 | len -= bits_to_set; |
| 5571 | (BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1))) | 5571 | bits_to_set = BITS_PER_BYTE; |
| 5572 | mask_to_set = ~(u8)0; | ||
| 5573 | p++; | ||
| 5574 | } | ||
| 5575 | if (len) { | ||
| 5576 | mask_to_set &= BITMAP_LAST_BYTE_MASK(size); | ||
| 5577 | *p |= mask_to_set; | ||
| 5578 | } | ||
| 5579 | } | ||
| 5580 | |||
| 5581 | void le_bitmap_clear(u8 *map, unsigned int start, int len) | ||
| 5582 | { | ||
| 5583 | u8 *p = map + BIT_BYTE(start); | ||
| 5584 | const unsigned int size = start + len; | ||
| 5585 | int bits_to_clear = BITS_PER_BYTE - (start % BITS_PER_BYTE); | ||
| 5586 | u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(start); | ||
| 5587 | |||
| 5588 | while (len - bits_to_clear >= 0) { | ||
| 5589 | *p &= ~mask_to_clear; | ||
| 5590 | len -= bits_to_clear; | ||
| 5591 | bits_to_clear = BITS_PER_BYTE; | ||
| 5592 | mask_to_clear = ~(u8)0; | ||
| 5593 | p++; | ||
| 5594 | } | ||
| 5595 | if (len) { | ||
| 5596 | mask_to_clear &= BITMAP_LAST_BYTE_MASK(size); | ||
| 5597 | *p &= ~mask_to_clear; | ||
| 5598 | } | ||
| 5599 | } | ||
| 5572 | 5600 | ||
| 5573 | /* | 5601 | /* |
| 5574 | * eb_bitmap_offset() - calculate the page and offset of the byte containing the | 5602 | * eb_bitmap_offset() - calculate the page and offset of the byte containing the |
| @@ -5612,7 +5640,7 @@ static inline void eb_bitmap_offset(struct extent_buffer *eb, | |||
| 5612 | int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start, | 5640 | int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start, |
| 5613 | unsigned long nr) | 5641 | unsigned long nr) |
| 5614 | { | 5642 | { |
| 5615 | char *kaddr; | 5643 | u8 *kaddr; |
| 5616 | struct page *page; | 5644 | struct page *page; |
| 5617 | unsigned long i; | 5645 | unsigned long i; |
| 5618 | size_t offset; | 5646 | size_t offset; |
| @@ -5634,13 +5662,13 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start, | |||
| 5634 | void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, | 5662 | void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, |
| 5635 | unsigned long pos, unsigned long len) | 5663 | unsigned long pos, unsigned long len) |
| 5636 | { | 5664 | { |
| 5637 | char *kaddr; | 5665 | u8 *kaddr; |
| 5638 | struct page *page; | 5666 | struct page *page; |
| 5639 | unsigned long i; | 5667 | unsigned long i; |
| 5640 | size_t offset; | 5668 | size_t offset; |
| 5641 | const unsigned int size = pos + len; | 5669 | const unsigned int size = pos + len; |
| 5642 | int bits_to_set = BITS_PER_BYTE - (pos % BITS_PER_BYTE); | 5670 | int bits_to_set = BITS_PER_BYTE - (pos % BITS_PER_BYTE); |
| 5643 | unsigned int mask_to_set = BITMAP_FIRST_BYTE_MASK(pos); | 5671 | u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(pos); |
| 5644 | 5672 | ||
| 5645 | eb_bitmap_offset(eb, start, pos, &i, &offset); | 5673 | eb_bitmap_offset(eb, start, pos, &i, &offset); |
| 5646 | page = eb->pages[i]; | 5674 | page = eb->pages[i]; |
| @@ -5651,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, | |||
| 5651 | kaddr[offset] |= mask_to_set; | 5679 | kaddr[offset] |= mask_to_set; |
| 5652 | len -= bits_to_set; | 5680 | len -= bits_to_set; |
| 5653 | bits_to_set = BITS_PER_BYTE; | 5681 | bits_to_set = BITS_PER_BYTE; |
| 5654 | mask_to_set = ~0U; | 5682 | mask_to_set = ~(u8)0; |
| 5655 | if (++offset >= PAGE_SIZE && len > 0) { | 5683 | if (++offset >= PAGE_SIZE && len > 0) { |
| 5656 | offset = 0; | 5684 | offset = 0; |
| 5657 | page = eb->pages[++i]; | 5685 | page = eb->pages[++i]; |
| @@ -5676,13 +5704,13 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, | |||
| 5676 | void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start, | 5704 | void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start, |
| 5677 | unsigned long pos, unsigned long len) | 5705 | unsigned long pos, unsigned long len) |
| 5678 | { | 5706 | { |
| 5679 | char *kaddr; | 5707 | u8 *kaddr; |
| 5680 | struct page *page; | 5708 | struct page *page; |
| 5681 | unsigned long i; | 5709 | unsigned long i; |
| 5682 | size_t offset; | 5710 | size_t offset; |
| 5683 | const unsigned int size = pos + len; | 5711 | const unsigned int size = pos + len; |
| 5684 | int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE); | 5712 | int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE); |
| 5685 | unsigned int mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos); | ||
