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

Commit 087a76d3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs updates from Chris Mason:
 "Jeff Mahoney and Dave Sterba have a really nice set of cleanups in
  here, and Christoph pitched in corrections/improvements to make btrfs
  use proper helpers for bio walking instead of doing it by hand.

  There are some key fixes as well, including some long standing bugs
  that took forever to track down in btrfs_drop_extents and during
  balance"

* 'for-linus-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (77 commits)
  btrfs: limit async_work allocation and worker func duration
  Revert "Btrfs: adjust len of writes if following a preallocated extent"
  Btrfs: don't WARN() in btrfs_transaction_abort() for IO errors
  btrfs: opencode chunk locking, remove helpers
  btrfs: remove root parameter from transaction commit/end routines
  btrfs: split btrfs_wait_marked_extents into normal and tree log functions
  btrfs: take an fs_info directly when the root is not used otherwise
  btrfs: simplify btrfs_wait_cache_io prototype
  btrfs: convert extent-tree tracepoints to use fs_info
  btrfs: root->fs_info cleanup, access fs_info->delayed_root directly
  btrfs: root->fs_info cleanup, add fs_info convenience variables
  btrfs: root->fs_info cleanup, update_block_group{,flags}
  btrfs: root->fs_info cleanup, lock/unlock_chunks
  btrfs: root->fs_info cleanup, btrfs_calc_{trans,trunc}_metadata_size
  btrfs: pull node/sector/stripe sizes out of root and into fs_info
  btrfs: root->fs_info cleanup, io_ctl_init
  btrfs: root->fs_info cleanup, use fs_info->dev_root everywhere
  btrfs: struct reada_control.root -> reada_control.fs_info
  btrfs: struct btrfsic_state->root should be an fs_info
  btrfs: alloc_reserved_file_extent trace point should use extent_root
  ...
parents 759b2656 2939e1a8
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -86,6 +86,20 @@ btrfs_work_owner(struct btrfs_work *work)
	return work->wq->fs_info;
}

bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq)
{
	/*
	 * We could compare wq->normal->pending with num_online_cpus()
	 * to support "thresh == NO_THRESHOLD" case, but it requires
	 * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's
	 * postpone it until someone needs the support of that case.
	 */
	if (wq->normal->thresh == NO_THRESHOLD)
		return false;

	return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2;
}

BTRFS_WORK_HELPER(worker_helper);
BTRFS_WORK_HELPER(delalloc_helper);
BTRFS_WORK_HELPER(flush_delalloc_helper);
+1 −0
Original line number Diff line number Diff line
@@ -84,4 +84,5 @@ void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
void btrfs_set_work_high_priority(struct btrfs_work *work);
struct btrfs_fs_info *btrfs_work_owner(struct btrfs_work *work);
struct btrfs_fs_info *btrfs_workqueue_owner(struct __btrfs_workqueue *wq);
bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq);
#endif
+4 −6
Original line number Diff line number Diff line
@@ -788,8 +788,7 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
		if (ref->key_for_search.type)
			continue;
		BUG_ON(!ref->wanted_disk_byte);
		eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte,
				     0);
		eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0);
		if (IS_ERR(eb)) {
			return PTR_ERR(eb);
		} else if (!extent_buffer_uptodate(eb)) {
@@ -1405,8 +1404,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
			    ref->level == 0) {
				struct extent_buffer *eb;

				eb = read_tree_block(fs_info->extent_root,
							   ref->parent, 0);
				eb = read_tree_block(fs_info, ref->parent, 0);
				if (IS_ERR(eb)) {
					ret = PTR_ERR(eb);
					goto out;
@@ -1829,7 +1827,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
	}
	btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]);
	if (found_key->type == BTRFS_METADATA_ITEM_KEY)
		size = fs_info->extent_root->nodesize;
		size = fs_info->nodesize;
	else if (found_key->type == BTRFS_EXTENT_ITEM_KEY)
		size = found_key->offset;

@@ -2058,7 +2056,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
out:
	if (!search_commit_root) {
		btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem);
		btrfs_end_transaction(trans, fs_info->extent_root);
		btrfs_end_transaction(trans);
	} else {
		up_read(&fs_info->commit_root_sem);
	}
+48 −55
Original line number Diff line number Diff line
@@ -254,7 +254,7 @@ struct btrfsic_state {
	struct list_head all_blocks_list;
	struct btrfsic_block_hashtable block_hashtable;
	struct btrfsic_block_link_hashtable block_link_hashtable;
	struct btrfs_root *root;
	struct btrfs_fs_info *fs_info;
	u64 max_superblock_generation;
	struct btrfsic_block *latest_superblock;
	u32 metablock_size;
@@ -646,11 +646,12 @@ static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(
static int btrfsic_process_superblock(struct btrfsic_state *state,
				      struct btrfs_fs_devices *fs_devices)
{
	int ret = 0;
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfs_super_block *selected_super;
	struct list_head *dev_head = &fs_devices->devices;
	struct btrfs_device *device;
	struct btrfsic_dev_state *selected_dev_state = NULL;
	int ret = 0;
	int pass;

	BUG_ON(NULL == state);
@@ -716,9 +717,8 @@ static int btrfsic_process_superblock(struct btrfsic_state *state,
			break;
		}

		num_copies =
		    btrfs_num_copies(state->root->fs_info,
				     next_bytenr, state->metablock_size);
		num_copies = btrfs_num_copies(fs_info, next_bytenr,
					      state->metablock_size);
		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
			pr_info("num_copies(log_bytenr=%llu) = %d\n",
			       next_bytenr, num_copies);
@@ -783,6 +783,7 @@ static int btrfsic_process_superblock_dev_mirror(
		struct btrfsic_dev_state **selected_dev_state,
		struct btrfs_super_block *selected_super)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfs_super_block *super_tmp;
	u64 dev_bytenr;
	struct buffer_head *bh;
@@ -832,7 +833,7 @@ static int btrfsic_process_superblock_dev_mirror(
		superblock_tmp->never_written = 0;
		superblock_tmp->mirror_num = 1 + superblock_mirror_num;
		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
			btrfs_info_in_rcu(device->dev_root->fs_info,
			btrfs_info_in_rcu(fs_info,
				"new initial S-block (bdev %p, %s) @%llu (%s/%llu/%d)",
				     superblock_bdev,
				     rcu_str_deref(device->name), dev_bytenr,
@@ -887,9 +888,8 @@ static int btrfsic_process_superblock_dev_mirror(
			break;
		}

		num_copies =
		    btrfs_num_copies(state->root->fs_info,
				     next_bytenr, state->metablock_size);
		num_copies = btrfs_num_copies(fs_info, next_bytenr,
					      state->metablock_size);
		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
			pr_info("num_copies(log_bytenr=%llu) = %d\n",
			       next_bytenr, num_copies);
@@ -1254,6 +1254,7 @@ static int btrfsic_create_link_to_next_block(
		struct btrfs_disk_key *disk_key,
		u64 parent_generation)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfsic_block *next_block = NULL;
	int ret;
	struct btrfsic_block_link *l;
@@ -1262,9 +1263,8 @@ static int btrfsic_create_link_to_next_block(

	*next_blockp = NULL;
	if (0 == *num_copiesp) {
		*num_copiesp =
		    btrfs_num_copies(state->root->fs_info,
				     next_bytenr, state->metablock_size);
		*num_copiesp = btrfs_num_copies(fs_info, next_bytenr,
						state->metablock_size);
		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
			pr_info("num_copies(log_bytenr=%llu) = %d\n",
			       next_bytenr, *num_copiesp);
@@ -1390,13 +1390,14 @@ static int btrfsic_handle_extent_data(
		struct btrfsic_block_data_ctx *block_ctx,
		u32 item_offset, int force_iodone_flag)
{
	int ret;
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfs_file_extent_item file_extent_item;
	u64 file_extent_item_offset;
	u64 next_bytenr;
	u64 num_bytes;
	u64 generation;
	struct btrfsic_block_link *l;
	int ret;

	file_extent_item_offset = offsetof(struct btrfs_leaf, items) +
				  item_offset;
@@ -1456,9 +1457,8 @@ static int btrfsic_handle_extent_data(
		else
			chunk_len = num_bytes;

		num_copies =
		    btrfs_num_copies(state->root->fs_info,
				     next_bytenr, state->datablock_size);
		num_copies = btrfs_num_copies(fs_info, next_bytenr,
					      state->datablock_size);
		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
			pr_info("num_copies(log_bytenr=%llu) = %d\n",
			       next_bytenr, num_copies);
@@ -1533,13 +1533,14 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
			     struct btrfsic_block_data_ctx *block_ctx_out,
			     int mirror_num)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	int ret;
	u64 length;
	struct btrfs_bio *multi = NULL;
	struct btrfs_device *device;

	length = len;
	ret = btrfs_map_block(state->root->fs_info, READ,
	ret = btrfs_map_block(fs_info, BTRFS_MAP_READ,
			      bytenr, &length, &multi, mirror_num);

	if (ret) {
@@ -1731,6 +1732,7 @@ static void btrfsic_dump_database(struct btrfsic_state *state)
static int btrfsic_test_for_metadata(struct btrfsic_state *state,
				     char **datav, unsigned int num_pages)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfs_header *h;
	u8 csum[BTRFS_CSUM_SIZE];
	u32 crc = ~(u32)0;
@@ -1741,7 +1743,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state,
	num_pages = state->metablock_size >> PAGE_SHIFT;
	h = (struct btrfs_header *)datav[0];

	if (memcmp(h->fsid, state->root->fs_info->fsid, BTRFS_UUID_SIZE))
	if (memcmp(h->fsid, fs_info->fsid, BTRFS_UUID_SIZE))
		return 1;

	for (i = 0; i < num_pages; i++) {
@@ -2202,6 +2204,7 @@ static int btrfsic_process_written_superblock(
		struct btrfsic_block *const superblock,
		struct btrfs_super_block *const super_hdr)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	int pass;

	superblock->generation = btrfs_super_generation(super_hdr);
@@ -2275,9 +2278,8 @@ static int btrfsic_process_written_superblock(
			break;
		}

		num_copies =
		    btrfs_num_copies(state->root->fs_info,
				     next_bytenr, BTRFS_SUPER_INFO_SIZE);
		num_copies = btrfs_num_copies(fs_info, next_bytenr,
					      BTRFS_SUPER_INFO_SIZE);
		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
			pr_info("num_copies(log_bytenr=%llu) = %d\n",
			       next_bytenr, num_copies);
@@ -2699,14 +2701,14 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
					   struct btrfsic_dev_state *dev_state,
					   u64 dev_bytenr)
{
	struct btrfs_fs_info *fs_info = state->fs_info;
	struct btrfsic_block_data_ctx block_ctx;
	int num_copies;
	int mirror_num;
	int ret;
	struct btrfsic_block_data_ctx block_ctx;
	int match = 0;
	int ret;

	num_copies = btrfs_num_copies(state->root->fs_info,
				      bytenr, state->metablock_size);
	num_copies = btrfs_num_copies(fs_info, bytenr, state->metablock_size);

	for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
		ret = btrfsic_map_block(state, bytenr, state->metablock_size,
@@ -2819,10 +2821,11 @@ static void __btrfsic_submit_bio(struct bio *bio)
	 * btrfsic_mount(), this might return NULL */
	dev_state = btrfsic_dev_state_lookup(bio->bi_bdev);
	if (NULL != dev_state &&
	    (bio_op(bio) == REQ_OP_WRITE) && NULL != bio->bi_io_vec) {
	    (bio_op(bio) == REQ_OP_WRITE) && bio_has_data(bio)) {
		unsigned int i;
		u64 dev_bytenr;
		u64 cur_bytenr;
		struct bio_vec *bvec;
		int bio_is_patched;
		char **mapped_datav;

@@ -2840,32 +2843,23 @@ static void __btrfsic_submit_bio(struct bio *bio)
		if (!mapped_datav)
			goto leave;
		cur_bytenr = dev_bytenr;
		for (i = 0; i < bio->bi_vcnt; i++) {
			BUG_ON(bio->bi_io_vec[i].bv_len != PAGE_SIZE);
			mapped_datav[i] = kmap(bio->bi_io_vec[i].bv_page);
			if (!mapped_datav[i]) {
				while (i > 0) {
					i--;
					kunmap(bio->bi_io_vec[i].bv_page);
				}
				kfree(mapped_datav);
				goto leave;
			}

		bio_for_each_segment_all(bvec, bio, i) {
			BUG_ON(bvec->bv_len != PAGE_SIZE);
			mapped_datav[i] = kmap(bvec->bv_page);

			if (dev_state->state->print_mask &
			    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE)
				pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n",
				       i, cur_bytenr, bio->bi_io_vec[i].bv_len,
				       bio->bi_io_vec[i].bv_offset);
			cur_bytenr += bio->bi_io_vec[i].bv_len;
				       i, cur_bytenr, bvec->bv_len, bvec->bv_offset);
			cur_bytenr += bvec->bv_len;
		}
		btrfsic_process_written_block(dev_state, dev_bytenr,
					      mapped_datav, bio->bi_vcnt,
					      bio, &bio_is_patched,
					      NULL, bio->bi_opf);
		while (i > 0) {
			i--;
			kunmap(bio->bi_io_vec[i].bv_page);
		}
		bio_for_each_segment_all(bvec, bio, i)
			kunmap(bvec->bv_page);
		kfree(mapped_datav);
	} else if (NULL != dev_state && (bio->bi_opf & REQ_PREFLUSH)) {
		if (dev_state->state->print_mask &
@@ -2910,7 +2904,7 @@ int btrfsic_submit_bio_wait(struct bio *bio)
	return submit_bio_wait(bio);
}

int btrfsic_mount(struct btrfs_root *root,
int btrfsic_mount(struct btrfs_fs_info *fs_info,
		  struct btrfs_fs_devices *fs_devices,
		  int including_extent_data, u32 print_mask)
{
@@ -2919,14 +2913,14 @@ int btrfsic_mount(struct btrfs_root *root,
	struct list_head *dev_head = &fs_devices->devices;
	struct btrfs_device *device;

	if (root->nodesize & ((u64)PAGE_SIZE - 1)) {
	if (fs_info->nodesize & ((u64)PAGE_SIZE - 1)) {
		pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n",
		       root->nodesize, PAGE_SIZE);
		       fs_info->nodesize, PAGE_SIZE);
		return -1;
	}
	if (root->sectorsize & ((u64)PAGE_SIZE - 1)) {
	if (fs_info->sectorsize & ((u64)PAGE_SIZE - 1)) {
		pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n",
		       root->sectorsize, PAGE_SIZE);
		       fs_info->sectorsize, PAGE_SIZE);
		return -1;
	}
	state = kzalloc(sizeof(*state), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
@@ -2944,12 +2938,12 @@ int btrfsic_mount(struct btrfs_root *root,
		btrfsic_is_initialized = 1;
	}
	mutex_lock(&btrfsic_mutex);
	state->root = root;
	state->fs_info = fs_info;
	state->print_mask = print_mask;
	state->include_extent_data = including_extent_data;
	state->csum_size = 0;
	state->metablock_size = root->nodesize;
	state->datablock_size = root->sectorsize;
	state->metablock_size = fs_info->nodesize;
	state->datablock_size = fs_info->sectorsize;
	INIT_LIST_HEAD(&state->all_blocks_list);
	btrfsic_block_hashtable_init(&state->block_hashtable);
	btrfsic_block_link_hashtable_init(&state->block_link_hashtable);
@@ -2982,7 +2976,7 @@ int btrfsic_mount(struct btrfs_root *root,
	ret = btrfsic_process_superblock(state, fs_devices);
	if (0 != ret) {
		mutex_unlock(&btrfsic_mutex);
		btrfsic_unmount(root, fs_devices);
		btrfsic_unmount(fs_devices);
		return ret;
	}

@@ -2995,8 +2989,7 @@ int btrfsic_mount(struct btrfs_root *root,
	return 0;
}

void btrfsic_unmount(struct btrfs_root *root,
		     struct btrfs_fs_devices *fs_devices)
void btrfsic_unmount(struct btrfs_fs_devices *fs_devices)
{
	struct btrfsic_block *b_all, *tmp_all;
	struct btrfsic_state *state;
+2 −3
Original line number Diff line number Diff line
@@ -29,10 +29,9 @@ int btrfsic_submit_bio_wait(struct bio *bio);
#define btrfsic_submit_bio_wait submit_bio_wait
#endif

int btrfsic_mount(struct btrfs_root *root,
int btrfsic_mount(struct btrfs_fs_info *fs_info,
		  struct btrfs_fs_devices *fs_devices,
		  int including_extent_data, u32 print_mask);
void btrfsic_unmount(struct btrfs_root *root,
		     struct btrfs_fs_devices *fs_devices);
void btrfsic_unmount(struct btrfs_fs_devices *fs_devices);

#endif
Loading