Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9ed71e5 authored by Chris Mason's avatar Chris Mason
Browse files

Merge branch 'fst-fixes' of...

Merge branch 'fst-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

 into for-linus-4.9

Signed-off-by: default avatarChris Mason <clm@fb.com>
parents 19c4d2f9 0e675785
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -252,7 +252,8 @@ struct btrfs_super_block {
#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR		0ULL

#define BTRFS_FEATURE_COMPAT_RO_SUPP			\
	(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)
	(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |	\
	 BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID)

#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET	0ULL
#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR	0ULL
+21 −12
Original line number Diff line number Diff line
@@ -2586,6 +2586,7 @@ int open_ctree(struct super_block *sb,
	int num_backups_tried = 0;
	int backup_index = 0;
	int max_active;
	int clear_free_space_tree = 0;

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

	if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
	    btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
		clear_free_space_tree = 1;
	} else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
		   !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
		btrfs_warn(fs_info, "free space tree is invalid");
		clear_free_space_tree = 1;
	}

	if (clear_free_space_tree) {
		btrfs_info(fs_info, "clearing free space tree");
		ret = btrfs_clear_free_space_tree(fs_info);
		if (ret) {
			btrfs_warn(fs_info,
				   "failed to clear free space tree: %d", ret);
			close_ctree(tree_root);
			return ret;
		}
	}

	if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) &&
	    !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
		btrfs_info(fs_info, "creating free space tree");
@@ -3185,18 +3206,6 @@ int open_ctree(struct super_block *sb,

	btrfs_qgroup_rescan_resume(fs_info);

	if (btrfs_test_opt(tree_root->fs_info, CLEAR_CACHE) &&
	    btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
		btrfs_info(fs_info, "clearing free space tree");
		ret = btrfs_clear_free_space_tree(fs_info);
		if (ret) {
			btrfs_warn(fs_info,
				"failed to clear free space tree: %d", ret);
			close_ctree(tree_root);
			return ret;
		}
	}

	if (!fs_info->uuid_root) {
		btrfs_info(fs_info, "creating UUID tree");
		ret = btrfs_create_uuid_tree(fs_info);
+46 −18
Original line number Diff line number Diff line
@@ -5558,17 +5558,45 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
	}
}

/*
 * The extent buffer bitmap operations are done with byte granularity because
 * bitmap items are not guaranteed to be aligned to a word and therefore a
 * single word in a bitmap may straddle two pages in the extent buffer.
 */
#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
#define BITMAP_FIRST_BYTE_MASK(start) \
	((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
#define BITMAP_LAST_BYTE_MASK(nbits) \
	(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))
void le_bitmap_set(u8 *map, unsigned int start, int len)
{
	u8 *p = map + BIT_BYTE(start);
	const unsigned int size = start + len;
	int bits_to_set = BITS_PER_BYTE - (start % BITS_PER_BYTE);
	u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(start);

	while (len - bits_to_set >= 0) {
		*p |= mask_to_set;
		len -= bits_to_set;
		bits_to_set = BITS_PER_BYTE;
		mask_to_set = ~(u8)0;
		p++;
	}
	if (len) {
		mask_to_set &= BITMAP_LAST_BYTE_MASK(size);
		*p |= mask_to_set;
	}
}

void le_bitmap_clear(u8 *map, unsigned int start, int len)
{
	u8 *p = map + BIT_BYTE(start);
	const unsigned int size = start + len;
	int bits_to_clear = BITS_PER_BYTE - (start % BITS_PER_BYTE);
	u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(start);

	while (len - bits_to_clear >= 0) {
		*p &= ~mask_to_clear;
		len -= bits_to_clear;
		bits_to_clear = BITS_PER_BYTE;
		mask_to_clear = ~(u8)0;
		p++;
	}
	if (len) {
		mask_to_clear &= BITMAP_LAST_BYTE_MASK(size);
		*p &= ~mask_to_clear;
	}
}

/*
 * 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,
int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
			   unsigned long nr)
{
	char *kaddr;
	u8 *kaddr;
	struct page *page;
	unsigned long i;
	size_t offset;
@@ -5634,13 +5662,13 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
			      unsigned long pos, unsigned long len)
{
	char *kaddr;
	u8 *kaddr;
	struct page *page;
	unsigned long i;
	size_t offset;
	const unsigned int size = pos + len;
	int bits_to_set = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
	unsigned int mask_to_set = BITMAP_FIRST_BYTE_MASK(pos);
	u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(pos);

	eb_bitmap_offset(eb, start, pos, &i, &offset);
	page = eb->pages[i];
@@ -5651,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
		kaddr[offset] |= mask_to_set;
		len -= bits_to_set;
		bits_to_set = BITS_PER_BYTE;
		mask_to_set = ~0U;
		mask_to_set = ~(u8)0;
		if (++offset >= PAGE_SIZE && len > 0) {
			offset = 0;
			page = eb->pages[++i];
@@ -5676,13 +5704,13 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,
void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
				unsigned long pos, unsigned long len)
{
	char *kaddr;
	u8 *kaddr;
	struct page *page;
	unsigned long i;
	size_t offset;
	const unsigned int size = pos + len;
	int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
	unsigned int mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
	u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);

	eb_bitmap_offset(eb, start, pos, &i, &offset);
	page = eb->pages[i];
@@ -5693,7 +5721,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
		kaddr[offset] &= ~mask_to_clear;
		len -= bits_to_clear;
		bits_to_clear = BITS_PER_BYTE;
		mask_to_clear = ~0U;
		mask_to_clear = ~(u8)0;
		if (++offset >= PAGE_SIZE && len > 0) {
			offset = 0;
			page = eb->pages[++i];
+22 −0
Original line number Diff line number Diff line
@@ -59,6 +59,28 @@
 */
#define EXTENT_PAGE_PRIVATE 1

/*
 * The extent buffer bitmap operations are done with byte granularity instead of
 * word granularity for two reasons:
 * 1. The bitmaps must be little-endian on disk.
 * 2. Bitmap items are not guaranteed to be aligned to a word and therefore a
 *    single word in a bitmap may straddle two pages in the extent buffer.
 */
#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
#define BYTE_MASK ((1 << BITS_PER_BYTE) - 1)
#define BITMAP_FIRST_BYTE_MASK(start) \
	((BYTE_MASK << ((start) & (BITS_PER_BYTE - 1))) & BYTE_MASK)
#define BITMAP_LAST_BYTE_MASK(nbits) \
	(BYTE_MASK >> (-(nbits) & (BITS_PER_BYTE - 1)))

static inline int le_test_bit(int nr, const u8 *addr)
{
	return 1U & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE-1)));
}

extern void le_bitmap_set(u8 *map, unsigned int start, int len);
extern void le_bitmap_clear(u8 *map, unsigned int start, int len);

struct extent_state;
struct btrfs_root;
struct btrfs_io_bio;
+10 −9
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ static inline u32 free_space_bitmap_size(u64 size, u32 sectorsize)
	return DIV_ROUND_UP((u32)div_u64(size, sectorsize), BITS_PER_BYTE);
}

static unsigned long *alloc_bitmap(u32 bitmap_size)
static u8 *alloc_bitmap(u32 bitmap_size)
{
	void *mem;

@@ -180,8 +180,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
	struct btrfs_free_space_info *info;
	struct btrfs_key key, found_key;
	struct extent_buffer *leaf;
	unsigned long *bitmap;
	char *bitmap_cursor;
	u8 *bitmap, *bitmap_cursor;
	u64 start, end;
	u64 bitmap_range, i;
	u32 bitmap_size, flags, expected_extent_count;
@@ -231,7 +230,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
						block_group->sectorsize);
				last = div_u64(found_key.objectid + found_key.offset - start,
					       block_group->sectorsize);
				bitmap_set(bitmap, first, last - first);
				le_bitmap_set(bitmap, first, last - first);

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

	bitmap_cursor = (char *)bitmap;
	bitmap_cursor = bitmap;
	bitmap_range = block_group->sectorsize * BTRFS_FREE_SPACE_BITMAP_BITS;
	i = start;
	while (i < end) {
@@ -319,7 +318,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
	struct btrfs_free_space_info *info;
	struct btrfs_key key, found_key;
	struct extent_buffer *leaf;
	unsigned long *bitmap;
	u8 *bitmap;
	u64 start, end;
	/* Initialize to silence GCC. */
	u64 extent_start = 0;
@@ -363,7 +362,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
				break;
			} else if (found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) {
				unsigned long ptr;
				char *bitmap_cursor;
				u8 *bitmap_cursor;
				u32 bitmap_pos, data_size;

				ASSERT(found_key.objectid >= start);
@@ -373,7 +372,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
				bitmap_pos = div_u64(found_key.objectid - start,
						     block_group->sectorsize *
						     BITS_PER_BYTE);
				bitmap_cursor = ((char *)bitmap) + bitmap_pos;
				bitmap_cursor = bitmap + bitmap_pos;
				data_size = free_space_bitmap_size(found_key.offset,
								   block_group->sectorsize);

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

	btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
	btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
	clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);

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

	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
	fs_info->free_space_root = NULL;

	ret = clear_free_space_tree(trans, free_space_root);
Loading