Commit f382e465 authored by Stefan Behrens's avatar Stefan Behrens Committed by Chris Mason
Browse files

Btrfs: check_int: use the known block location



The xfstest btrfs/014 which tests the balance operation caused issues with
the check_int module. The attempt was made to use btrfs_map_block() to
find the physical location for a written block. However, this was not
at all needed since the location of the written block was known since
a hook to submit_bio() was the reason for entering the check_int module.
Additionally, after a block relocation it happened that btrfs_map_block()
failed causing misleading error messages afterwards.

This patch changes the check_int module to use the known information of
the physical location from the bio.

Reported-by: default avatarWang Shilong <wangshilong1991@gmail.com>
Signed-off-by: default avatarStefan Behrens <sbehrens@giantdisaster.de>
Tested-by: default avatarWang Shilong <wangshilong1991@gmail.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent c8fd3de7
Loading
Loading
Loading
Loading
+11 −55
Original line number Diff line number Diff line
@@ -326,9 +326,6 @@ static int btrfsic_handle_extent_data(struct btrfsic_state *state,
static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
			     struct btrfsic_block_data_ctx *block_ctx_out,
			     int mirror_num);
static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr,
				  u32 len, struct block_device *bdev,
				  struct btrfsic_block_data_ctx *block_ctx_out);
static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
static int btrfsic_read_block(struct btrfsic_state *state,
			      struct btrfsic_block_data_ctx *block_ctx);
@@ -1607,25 +1604,6 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
	return ret;
}

static int btrfsic_map_superblock(struct btrfsic_state *state, u64 bytenr,
				  u32 len, struct block_device *bdev,
				  struct btrfsic_block_data_ctx *block_ctx_out)
{
	block_ctx_out->dev = btrfsic_dev_state_lookup(bdev);
	block_ctx_out->dev_bytenr = bytenr;
	block_ctx_out->start = bytenr;
	block_ctx_out->len = len;
	block_ctx_out->datav = NULL;
	block_ctx_out->pagev = NULL;
	block_ctx_out->mem_to_free = NULL;
	if (NULL != block_ctx_out->dev) {
		return 0;
	} else {
		printk(KERN_INFO "btrfsic: error, cannot lookup dev (#2)!\n");
		return -ENXIO;
	}
}

static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx)
{
	if (block_ctx->mem_to_free) {
@@ -2002,24 +1980,13 @@ again:
			}
		}

		if (block->is_superblock)
			ret = btrfsic_map_superblock(state, bytenr,
						     processed_len,
						     bdev, &block_ctx);
		else
			ret = btrfsic_map_block(state, bytenr, processed_len,
						&block_ctx, 0);
		if (ret) {
			printk(KERN_INFO
			       "btrfsic: btrfsic_map_block(root @%llu)"
			       " failed!\n", bytenr);
			goto continue_loop;
		}
		block_ctx.datav = mapped_datav;
		/* the following is required in case of writes to mirrors,
		 * use the same that was used for the lookup */
		block_ctx.dev = dev_state;
		block_ctx.dev_bytenr = dev_bytenr;
		block_ctx.start = bytenr;
		block_ctx.len = processed_len;
		block_ctx.pagev = NULL;
		block_ctx.mem_to_free = NULL;
		block_ctx.datav = mapped_datav;

		if (is_metadata || state->include_extent_data) {
			block->never_written = 0;
@@ -2133,10 +2100,6 @@ again:
			/* this is getting ugly for the
			 * include_extent_data case... */
			bytenr = 0;	/* unknown */
			block_ctx.start = bytenr;
			block_ctx.len = processed_len;
			block_ctx.mem_to_free = NULL;
			block_ctx.pagev = NULL;
		} else {
			processed_len = state->metablock_size;
			bytenr = btrfs_stack_header_bytenr(
@@ -2149,22 +2112,15 @@ again:
				       "Written block @%llu (%s/%llu/?)"
				       " !found in hash table, M.\n",
				       bytenr, dev_state->name, dev_bytenr);

			ret = btrfsic_map_block(state, bytenr, processed_len,
						&block_ctx, 0);
			if (ret) {
				printk(KERN_INFO
				       "btrfsic: btrfsic_map_block(root @%llu)"
				       " failed!\n",
				       dev_bytenr);
				goto continue_loop;
			}
		}
		block_ctx.datav = mapped_datav;
		/* the following is required in case of writes to mirrors,
		 * use the same that was used for the lookup */

		block_ctx.dev = dev_state;
		block_ctx.dev_bytenr = dev_bytenr;
		block_ctx.start = bytenr;
		block_ctx.len = processed_len;
		block_ctx.pagev = NULL;
		block_ctx.mem_to_free = NULL;
		block_ctx.datav = mapped_datav;

		block = btrfsic_block_alloc();
		if (NULL == block) {