Skip to content

Commit d3304ca

Browse files
committed
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
2 parents 1a892b4 + d9ed71e commit d3304ca

8 files changed

Lines changed: 272 additions & 157 deletions

File tree

fs/btrfs/ctree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ struct btrfs_super_block {
252252
#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL
253253

254254
#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)
256257

257258
#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL
258259
#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL

fs/btrfs/disk-io.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,6 +2586,7 @@ int open_ctree(struct super_block *sb,
25862586
int num_backups_tried = 0;
25872587
int backup_index = 0;
25882588
int max_active;
2589+
int clear_free_space_tree = 0;
25892590

25902591
tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
25912592
chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -3148,6 +3149,26 @@ int open_ctree(struct super_block *sb,
31483149
if (sb->s_flags & MS_RDONLY)
31493150
return 0;
31503151

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+
31513172
if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) &&
31523173
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
31533174
btrfs_info(fs_info, "creating free space tree");
@@ -3185,18 +3206,6 @@ int open_ctree(struct super_block *sb,
31853206

31863207
btrfs_qgroup_rescan_resume(fs_info);
31873208

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-
32003209
if (!fs_info->uuid_root) {
32013210
btrfs_info(fs_info, "creating UUID tree");
32023211
ret = btrfs_create_uuid_tree(fs_info);

fs/btrfs/extent_io.c

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5558,17 +5558,45 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
55585558
}
55595559
}
55605560

5561-
/*
5562-
* The extent buffer bitmap operations are done with byte granularity because
5563-
* bitmap items are not guaranteed to be aligned to a word and therefore a
5564-
* single word in a bitmap may straddle two pages in the extent buffer.
5565-
*/
5566-
#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
5567-
#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
5568-
#define BITMAP_FIRST_BYTE_MASK(start) \
5569-
((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
5570-
#define BITMAP_LAST_BYTE_MASK(nbits) \
5571-
(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
5561+
void le_bitmap_set(u8 *map, unsigned int start, int len)
5562+
{
5563+
u8 *p = map + BIT_BYTE(start);
5564+
const unsigned int size = start + len;
5565+
int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE);
5566+
u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start);
5567+
5568+
while (len - bits_to_set >= 0) {
5569+
*p |= mask_to_set;
5570+
len -= bits_to_set;
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+
}
55725600

55735601
/*
55745602
* 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,
56125640
int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
56135641
unsigned long nr)
56145642
{
5615-
char *kaddr;
5643+
u8 *kaddr;
56165644
struct page *page;
56175645
unsigned long i;
56185646
size_t offset;
@@ -5634,13 +5662,13 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
56345662
void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
56355663
unsigned long pos, unsigned long len)
56365664
{
5637-
char *kaddr;
5665+
u8 *kaddr;
56385666
struct page *page;
56395667
unsigned long i;
56405668
size_t offset;
56415669
const unsigned int size = pos + len;
56425670
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);
56445672

56455673
eb_bitmap_offset(eb, start, pos, &i, &offset);
56465674
page = eb->pages[i];
@@ -5651,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
56515679
kaddr[offset] |= mask_to_set;
56525680
len -= bits_to_set;
56535681
bits_to_set = BITS_PER_BYTE;
5654-
mask_to_set = ~0U;
5682+
mask_to_set = ~(u8)0;
56555683
if (++offset >= PAGE_SIZE && len > 0) {
56565684
offset = 0;
56575685
page = eb->pages[++i];
@@ -5676,13 +5704,13 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
56765704
void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
56775705
unsigned long pos, unsigned long len)
56785706
{
5679-
char *kaddr;
5707+
u8 *kaddr;
56805708
struct page *page;
56815709
unsigned long i;
56825710
size_t offset;
56835711
const unsigned int size = pos + len;
56845712
int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
5685-
unsigned int mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
5713+
u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
56865714

56875715
eb_bitmap_offset(eb, start, pos, &i, &offset);
56885716
page = eb->pages[i];
@@ -5693,7 +5721,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
56935721
kaddr[offset] &= ~mask_to_clear;
56945722
len -= bits_to_clear;
56955723
bits_to_clear = BITS_PER_BYTE;
5696-
mask_to_clear = ~0U;
5724+
mask_to_clear = ~(u8)0;
56975725
if (++offset >= PAGE_SIZE && len > 0) {
56985726
offset = 0;
56995727
page = eb->pages[++i];

fs/btrfs/extent_io.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@
5959
*/
6060
#define EXTENT_PAGE_PRIVATE 1
6161

62+
/*
63+
* The extent buffer bitmap operations are done with byte granularity instead of
64+
* word granularity for two reasons:
65+
* 1. The bitmaps must be little-endian on disk.
66+
* 2. Bitmap items are not guaranteed to be aligned to a word and therefore a
67+
* single word in a bitmap may straddle two pages in the extent buffer.
68+
*/
69+
#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
70+
#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
71+
#define BITMAP_FIRST_BYTE_MASK(start) \
72+
((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
73+
#define BITMAP_LAST_BYTE_MASK(nbits) \
74+
(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
75+
76+
static inline int le_test_bit(int nr, const u8 *addr)
77+
{
78+
return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
79+
}
80+
81+
extern void le_bitmap_set(u8 *map, unsigned int start, int len);
82+
extern void le_bitmap_clear(u8 *map, unsigned int start, int len);
83+
6284
struct extent_state;
6385
struct btrfs_root;
6486
struct btrfs_io_bio;

fs/btrfs/free-space-tree.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static inline u32 free_space_bitmap_size(u64 size, u32 sectorsize)
151151
return DIV_ROUND_UP((u32)div_u64(size, sectorsize), BITS_PER_BYTE);
152152
}
153153

154-
static unsigned long *alloc_bitmap(u32 bitmap_size)
154+
static u8 *alloc_bitmap(u32 bitmap_size)
155155
{
156156
void *mem;
157157

@@ -180,8 +180,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
180180
struct btrfs_free_space_info *info;
181181
struct btrfs_key key, found_key;
182182
struct extent_buffer *leaf;
183-
unsigned long *bitmap;
184-
char *bitmap_cursor;
183+
u8 *bitmap, *bitmap_cursor;
185184
u64 start, end;
186185
u64 bitmap_range, i;
187186
u32 bitmap_size, flags, expected_extent_count;
@@ -231,7 +230,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
231230
block_group->sectorsize);
232231
last = div_u64(found_key.objectid + found_key.offset - start,
233232
block_group->sectorsize);
234-
bitmap_set(bitmap, first, last - first);
233+
le_bitmap_set(bitmap, first, last - first);
235234

236235
extent_count++;
237236
nr++;
@@ -270,7 +269,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
270269
goto out;
271270
}
272271

273-
bitmap_cursor = (char *)bitmap;
272+
bitmap_cursor = bitmap;
274273
bitmap_range = block_group->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS;
275274
i = start;
276275
while (i < end) {
@@ -319,7 +318,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
319318
struct btrfs_free_space_info *info;
320319
struct btrfs_key key, found_key;
321320
struct extent_buffer *leaf;
322-
unsigned long *bitmap;
321+
u8 *bitmap;
323322
u64 start, end;
324323
/* Initialize to silence GCC. */
325324
u64 extent_start = 0;
@@ -363,7 +362,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
363362
break;
364363
} else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) {
365364
unsigned long ptr;
366-
char *bitmap_cursor;
365+
u8 *bitmap_cursor;
367366
u32 bitmap_pos, data_size;
368367

369368
ASSERT(found_key.objectid >= start);
@@ -373,7 +372,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
373372
bitmap_pos = div_u64(found_key.objectid - start,
374373
block_group->sectorsize *
375374
BITS_PER_BYTE);
376-
bitmap_cursor = ((char *)bitmap) + bitmap_pos;
375+
bitmap_cursor = bitmap + bitmap_pos;
377376
data_size = free_space_bitmap_size(found_key.offset,
378377
block_group->sectorsize);
379378

@@ -410,7 +409,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
410409
offset = start;
411410
bitnr = 0;
412411
while (offset < end) {
413-
bit = !!test_bit(bitnr, bitmap);
412+
bit = !!le_test_bit(bitnr, bitmap);
414413
if (prev_bit == 0 && bit == 1) {
415414
extent_start = offset;
416415
} else if (prev_bit == 1 && bit == 0) {
@@ -1185,6 +1184,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
11851184
}
11861185

11871186
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
1187+
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
11881188
clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
11891189

11901190
ret = btrfs_commit_transaction(trans, tree_root);
@@ -1253,6 +1253,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
12531253
return PTR_ERR(trans);
12541254

12551255
btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
1256+
btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
12561257
fs_info->free_space_root = NULL;
12571258

12581259
ret = clear_free_space_tree(trans, free_space_root);

0 commit comments

Comments
 (0)