diff options
Diffstat (limited to 'fs/btrfs/check-integrity.c')
| -rw-r--r-- | fs/btrfs/check-integrity.c | 104 | 
1 files changed, 56 insertions, 48 deletions
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 1c47be18724..ce92ae30250 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -77,17 +77,26 @@   * the integrity of (super)-block write requests, do not   * enable the config option BTRFS_FS_CHECK_INTEGRITY to   * include and compile the integrity check tool. + * + * Expect millions of lines of information in the kernel log with an + * enabled check_int_print_mask. Therefore set LOG_BUF_SHIFT in the + * kernel config to at least 26 (which is 64MB). Usually the value is + * limited to 21 (which is 2MB) in init/Kconfig. The file needs to be + * changed like this before LOG_BUF_SHIFT can be set to a high value: + * config LOG_BUF_SHIFT + *       int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" + *       range 12 30   */  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/buffer_head.h>  #include <linux/mutex.h> -#include <linux/crc32c.h>  #include <linux/genhd.h>  #include <linux/blkdev.h>  #include "ctree.h"  #include "disk-io.h" +#include "hash.h"  #include "transaction.h"  #include "extent_io.h"  #include "volumes.h" @@ -124,6 +133,7 @@  #define BTRFSIC_PRINT_MASK_INITIAL_DATABASE			0x00000400  #define BTRFSIC_PRINT_MASK_NUM_COPIES				0x00000800  #define BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS		0x00001000 +#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE		0x00002000  struct btrfsic_dev_state;  struct btrfsic_state; @@ -323,7 +333,6 @@ 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);  static void btrfsic_dump_database(struct btrfsic_state *state); -static void btrfsic_complete_bio_end_io(struct bio *bio, int err);  static int btrfsic_test_for_metadata(struct btrfsic_state *state,  				     char **datav, unsigned int num_pages);  static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, @@ -1038,7 +1047,7 @@ leaf_item_out_of_bounce_error:  						     disk_item_offset,  						     sizeof(struct btrfs_item));  			item_offset = btrfs_stack_item_offset(&disk_item); -			item_size = btrfs_stack_item_offset(&disk_item); +			item_size = btrfs_stack_item_size(&disk_item);  			disk_key = &disk_item.key;  			type = btrfs_disk_key_type(disk_key); @@ -1084,6 +1093,7 @@ leaf_item_out_of_bounce_error:  					next_stack =  					    btrfsic_stack_frame_alloc();  					if (NULL == next_stack) { +						sf->error = -1;  						btrfsic_release_block_ctx(  								&sf->  								next_block_ctx); @@ -1181,8 +1191,10 @@ continue_with_current_node_stack_frame:  				    sf->next_block_ctx.datav[0];  				next_stack = btrfsic_stack_frame_alloc(); -				if (NULL == next_stack) +				if (NULL == next_stack) { +					sf->error = -1;  					goto one_stack_frame_backwards; +				}  				next_stack->i = -1;  				next_stack->block = sf->next_block; @@ -1447,10 +1459,14 @@ static int btrfsic_handle_extent_data(  	btrfsic_read_from_block_data(block_ctx, &file_extent_item,  				     file_extent_item_offset,  				     sizeof(struct btrfs_file_extent_item)); -	next_bytenr = btrfs_stack_file_extent_disk_bytenr(&file_extent_item) + -		      btrfs_stack_file_extent_offset(&file_extent_item); -	generation = btrfs_stack_file_extent_generation(&file_extent_item); -	num_bytes = btrfs_stack_file_extent_num_bytes(&file_extent_item); +	next_bytenr = btrfs_stack_file_extent_disk_bytenr(&file_extent_item); +	if (btrfs_stack_file_extent_compression(&file_extent_item) == +	    BTRFS_COMPRESS_NONE) { +		next_bytenr += btrfs_stack_file_extent_offset(&file_extent_item); +		num_bytes = btrfs_stack_file_extent_num_bytes(&file_extent_item); +	} else { +		num_bytes = btrfs_stack_file_extent_disk_num_bytes(&file_extent_item); +	}  	generation = btrfs_stack_file_extent_generation(&file_extent_item);  	if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE) @@ -1677,7 +1693,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,  	for (i = 0; i < num_pages;) {  		struct bio *bio;  		unsigned int j; -		DECLARE_COMPLETION_ONSTACK(complete);  		bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);  		if (!bio) { @@ -1687,9 +1702,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,  			return -1;  		}  		bio->bi_bdev = block_ctx->dev->bdev; -		bio->bi_sector = dev_bytenr >> 9; -		bio->bi_end_io = btrfsic_complete_bio_end_io; -		bio->bi_private = &complete; +		bio->bi_iter.bi_sector = dev_bytenr >> 9;  		for (j = i; j < num_pages; j++) {  			ret = bio_add_page(bio, block_ctx->pagev[j], @@ -1702,12 +1715,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,  			       "btrfsic: error, failed to add a single page!\n");  			return -1;  		} -		submit_bio(READ, bio); - -		/* this will also unplug the queue */ -		wait_for_completion(&complete); - -		if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { +		if (submit_bio_wait(READ, bio)) {  			printk(KERN_INFO  			       "btrfsic: read error at logical %llu dev %s!\n",  			       block_ctx->start, block_ctx->dev->name); @@ -1730,11 +1738,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,  	return block_ctx->len;  } -static void btrfsic_complete_bio_end_io(struct bio *bio, int err) -{ -	complete((struct completion *)bio->bi_private); -} -  static void btrfsic_dump_database(struct btrfsic_state *state)  {  	struct list_head *elem_all; @@ -1823,7 +1826,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state,  		size_t sublen = i ? PAGE_CACHE_SIZE :  				    (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE); -		crc = crc32c(crc, data, sublen); +		crc = btrfs_crc32c(crc, data, sublen);  	}  	btrfs_csum_final(crc, csum);  	if (memcmp(csum, h->csum, state->csum_size)) @@ -1900,7 +1903,9 @@ again:  							       dev_state,  							       dev_bytenr);  			} -			if (block->logical_bytenr != bytenr) { +			if (block->logical_bytenr != bytenr && +			    !(!block->is_metadata && +			      block->logical_bytenr == 0))  				printk(KERN_INFO  				       "Written block @%llu (%s/%llu/%d)"  				       " found in hash table, %c," @@ -1910,15 +1915,14 @@ again:  				       block->mirror_num,  				       btrfsic_get_block_type(state, block),  				       block->logical_bytenr); -				block->logical_bytenr = bytenr; -			} else if (state->print_mask & -				   BTRFSIC_PRINT_MASK_VERBOSE) +			else if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)  				printk(KERN_INFO  				       "Written block @%llu (%s/%llu/%d)"  				       " found in hash table, %c.\n",  				       bytenr, dev_state->name, dev_bytenr,  				       block->mirror_num,  				       btrfsic_get_block_type(state, block)); +			block->logical_bytenr = bytenr;  		} else {  			if (num_pages * PAGE_CACHE_SIZE <  			    state->datablock_size) { @@ -2463,10 +2467,8 @@ static int btrfsic_process_written_superblock(  		}  	} -	if (-1 == btrfsic_check_all_ref_blocks(state, superblock, 0)) { -		WARN_ON(1); +	if (WARN_ON(-1 == btrfsic_check_all_ref_blocks(state, superblock, 0)))  		btrfsic_dump_tree(state); -	}  	return 0;  } @@ -2906,7 +2908,7 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,  		btrfsic_release_block_ctx(&block_ctx);  	} -	if (!match) { +	if (WARN_ON(!match)) {  		printk(KERN_INFO "btrfs: attempt to write M-block which contains logical bytenr that doesn't map to dev+physical bytenr of submit_bio,"  		       " buffer->log_bytenr=%llu, submit_bio(bdev=%s,"  		       " phys_bytenr=%llu)!\n", @@ -2923,7 +2925,6 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,  			       bytenr, block_ctx.dev->name,  			       block_ctx.dev_bytenr, mirror_num);  		} -		WARN_ON(1);  	}  } @@ -3000,14 +3001,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh)  	return submit_bh(rw, bh);  } -void btrfsic_submit_bio(int rw, struct bio *bio) +static void __btrfsic_submit_bio(int rw, struct bio *bio)  {  	struct btrfsic_dev_state *dev_state; -	if (!btrfsic_is_initialized) { -		submit_bio(rw, bio); +	if (!btrfsic_is_initialized)  		return; -	}  	mutex_lock(&btrfsic_mutex);  	/* since btrfsic_submit_bio() is also called before @@ -3017,10 +3016,11 @@ void btrfsic_submit_bio(int rw, struct bio *bio)  	    (rw & WRITE) && NULL != bio->bi_io_vec) {  		unsigned int i;  		u64 dev_bytenr; +		u64 cur_bytenr;  		int bio_is_patched;  		char **mapped_datav; -		dev_bytenr = 512 * bio->bi_sector; +		dev_bytenr = 512 * bio->bi_iter.bi_sector;  		bio_is_patched = 0;  		if (dev_state->state->print_mask &  		    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) @@ -3028,13 +3028,14 @@ void btrfsic_submit_bio(int rw, struct bio *bio)  			       "submit_bio(rw=0x%x, bi_vcnt=%u,"  			       " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",  			       rw, bio->bi_vcnt, -			       (unsigned long long)bio->bi_sector, dev_bytenr, -			       bio->bi_bdev); +			       (unsigned long long)bio->bi_iter.bi_sector, +			       dev_bytenr, bio->bi_bdev);  		mapped_datav = kmalloc(sizeof(*mapped_datav) * bio->bi_vcnt,  				       GFP_NOFS);  		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_CACHE_SIZE);  			mapped_datav[i] = kmap(bio->bi_io_vec[i].bv_page); @@ -3046,16 +3047,13 @@ void btrfsic_submit_bio(int rw, struct bio *bio)  				kfree(mapped_datav);  				goto leave;  			} -			if ((BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | -			     BTRFSIC_PRINT_MASK_VERBOSE) == -			    (dev_state->state->print_mask & -			     (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | -			      BTRFSIC_PRINT_MASK_VERBOSE))) +			if (dev_state->state->print_mask & +			    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE)  				printk(KERN_INFO -				       "#%u: page=%p, len=%u, offset=%u\n", -				       i, bio->bi_io_vec[i].bv_page, -				       bio->bi_io_vec[i].bv_len, +				       "#%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;  		}  		btrfsic_process_written_block(dev_state, dev_bytenr,  					      mapped_datav, bio->bi_vcnt, @@ -3099,10 +3097,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio)  	}  leave:  	mutex_unlock(&btrfsic_mutex); +} +void btrfsic_submit_bio(int rw, struct bio *bio) +{ +	__btrfsic_submit_bio(rw, bio);  	submit_bio(rw, bio);  } +int btrfsic_submit_bio_wait(int rw, struct bio *bio) +{ +	__btrfsic_submit_bio(rw, bio); +	return submit_bio_wait(rw, bio); +} +  int btrfsic_mount(struct btrfs_root *root,  		  struct btrfs_fs_devices *fs_devices,  		  int including_extent_data, u32 print_mask)  | 
