Skip to content

Commit d9ed71e

Browse files
committed
Merge branch 'fst-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus-4.9
Signed-off-by: Chris Mason <clm@fb.com>
2 parents 19c4d2f + 0e67578 commit d9ed71e

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)