forked from mirrors/linux
		
	btrfs: scrub: remove the old writeback infrastructure
Since the whole scrub path has been switched to scrub_stripe based solution, the old writeback path can be removed completely, which involves: - scrub_ctx::wr_curr_bio member - scrub_ctx::flush_all_writes member - function scrub_write_block_to_dev_replace() - function scrub_write_sector_to_dev_replace() - function scrub_add_sector_to_wr_bio() - function scrub_wr_submit() - function scrub_wr_bio_end_io() - function scrub_wr_bio_end_io_worker() And one more function needs to be exported temporarily: - scrub_sector_get() Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									5dc96f8d5d
								
							
						
					
					
						commit
						16f9399349
					
				
					 2 changed files with 3 additions and 219 deletions
				
			
		
							
								
								
									
										221
									
								
								fs/btrfs/scrub.c
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								fs/btrfs/scrub.c
									
									
									
									
									
								
							| 
						 | 
					@ -275,10 +275,8 @@ struct scrub_ctx {
 | 
				
			||||||
	int			is_dev_replace;
 | 
						int			is_dev_replace;
 | 
				
			||||||
	u64			write_pointer;
 | 
						u64			write_pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct scrub_bio        *wr_curr_bio;
 | 
					 | 
				
			||||||
	struct mutex            wr_lock;
 | 
						struct mutex            wr_lock;
 | 
				
			||||||
	struct btrfs_device     *wr_tgtdev;
 | 
						struct btrfs_device     *wr_tgtdev;
 | 
				
			||||||
	bool                    flush_all_writes;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * statistics
 | 
						 * statistics
 | 
				
			||||||
| 
						 | 
					@ -547,23 +545,14 @@ static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
 | 
				
			||||||
static int scrub_repair_sector_from_good_copy(struct scrub_block *sblock_bad,
 | 
					static int scrub_repair_sector_from_good_copy(struct scrub_block *sblock_bad,
 | 
				
			||||||
					    struct scrub_block *sblock_good,
 | 
										    struct scrub_block *sblock_good,
 | 
				
			||||||
					    int sector_num, int force_write);
 | 
										    int sector_num, int force_write);
 | 
				
			||||||
static void scrub_write_block_to_dev_replace(struct scrub_block *sblock);
 | 
					 | 
				
			||||||
static int scrub_write_sector_to_dev_replace(struct scrub_block *sblock,
 | 
					 | 
				
			||||||
					     int sector_num);
 | 
					 | 
				
			||||||
static int scrub_checksum_data(struct scrub_block *sblock);
 | 
					static int scrub_checksum_data(struct scrub_block *sblock);
 | 
				
			||||||
static int scrub_checksum_tree_block(struct scrub_block *sblock);
 | 
					static int scrub_checksum_tree_block(struct scrub_block *sblock);
 | 
				
			||||||
static int scrub_checksum_super(struct scrub_block *sblock);
 | 
					static int scrub_checksum_super(struct scrub_block *sblock);
 | 
				
			||||||
static void scrub_block_put(struct scrub_block *sblock);
 | 
					static void scrub_block_put(struct scrub_block *sblock);
 | 
				
			||||||
static void scrub_sector_get(struct scrub_sector *sector);
 | 
					 | 
				
			||||||
static void scrub_sector_put(struct scrub_sector *sector);
 | 
					static void scrub_sector_put(struct scrub_sector *sector);
 | 
				
			||||||
static void scrub_bio_end_io(struct bio *bio);
 | 
					static void scrub_bio_end_io(struct bio *bio);
 | 
				
			||||||
static void scrub_bio_end_io_worker(struct work_struct *work);
 | 
					static void scrub_bio_end_io_worker(struct work_struct *work);
 | 
				
			||||||
static void scrub_block_complete(struct scrub_block *sblock);
 | 
					static void scrub_block_complete(struct scrub_block *sblock);
 | 
				
			||||||
static int scrub_add_sector_to_wr_bio(struct scrub_ctx *sctx,
 | 
					 | 
				
			||||||
				      struct scrub_sector *sector);
 | 
					 | 
				
			||||||
static void scrub_wr_submit(struct scrub_ctx *sctx);
 | 
					 | 
				
			||||||
static void scrub_wr_bio_end_io(struct bio *bio);
 | 
					 | 
				
			||||||
static void scrub_wr_bio_end_io_worker(struct work_struct *work);
 | 
					 | 
				
			||||||
static void scrub_put_ctx(struct scrub_ctx *sctx);
 | 
					static void scrub_put_ctx(struct scrub_ctx *sctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int scrub_is_page_on_raid56(struct scrub_sector *sector)
 | 
					static inline int scrub_is_page_on_raid56(struct scrub_sector *sector)
 | 
				
			||||||
| 
						 | 
					@ -872,7 +861,6 @@ static noinline_for_stack void scrub_free_ctx(struct scrub_ctx *sctx)
 | 
				
			||||||
	for (i = 0; i < SCRUB_STRIPES_PER_SCTX; i++)
 | 
						for (i = 0; i < SCRUB_STRIPES_PER_SCTX; i++)
 | 
				
			||||||
		release_scrub_stripe(&sctx->stripes[i]);
 | 
							release_scrub_stripe(&sctx->stripes[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kfree(sctx->wr_curr_bio);
 | 
					 | 
				
			||||||
	scrub_free_csums(sctx);
 | 
						scrub_free_csums(sctx);
 | 
				
			||||||
	kfree(sctx);
 | 
						kfree(sctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -934,13 +922,10 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
 | 
				
			||||||
	init_waitqueue_head(&sctx->list_wait);
 | 
						init_waitqueue_head(&sctx->list_wait);
 | 
				
			||||||
	sctx->throttle_deadline = 0;
 | 
						sctx->throttle_deadline = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WARN_ON(sctx->wr_curr_bio != NULL);
 | 
					 | 
				
			||||||
	mutex_init(&sctx->wr_lock);
 | 
						mutex_init(&sctx->wr_lock);
 | 
				
			||||||
	sctx->wr_curr_bio = NULL;
 | 
					 | 
				
			||||||
	if (is_dev_replace) {
 | 
						if (is_dev_replace) {
 | 
				
			||||||
		WARN_ON(!fs_info->dev_replace.tgtdev);
 | 
							WARN_ON(!fs_info->dev_replace.tgtdev);
 | 
				
			||||||
		sctx->wr_tgtdev = fs_info->dev_replace.tgtdev;
 | 
							sctx->wr_tgtdev = fs_info->dev_replace.tgtdev;
 | 
				
			||||||
		sctx->flush_all_writes = false;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sctx;
 | 
						return sctx;
 | 
				
			||||||
| 
						 | 
					@ -1304,8 +1289,6 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
 | 
				
			||||||
		sblock_to_check->data_corrected = 1;
 | 
							sblock_to_check->data_corrected = 1;
 | 
				
			||||||
		spin_unlock(&sctx->stat_lock);
 | 
							spin_unlock(&sctx->stat_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sctx->is_dev_replace)
 | 
					 | 
				
			||||||
			scrub_write_block_to_dev_replace(sblock_bad);
 | 
					 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1394,7 +1377,6 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
 | 
				
			||||||
		    !sblock_other->checksum_error &&
 | 
							    !sblock_other->checksum_error &&
 | 
				
			||||||
		    sblock_other->no_io_error_seen) {
 | 
							    sblock_other->no_io_error_seen) {
 | 
				
			||||||
			if (sctx->is_dev_replace) {
 | 
								if (sctx->is_dev_replace) {
 | 
				
			||||||
				scrub_write_block_to_dev_replace(sblock_other);
 | 
					 | 
				
			||||||
				goto corrected_error;
 | 
									goto corrected_error;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				ret = scrub_repair_block_from_good_copy(
 | 
									ret = scrub_repair_block_from_good_copy(
 | 
				
			||||||
| 
						 | 
					@ -1476,13 +1458,6 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (!sblock_other)
 | 
								if (!sblock_other)
 | 
				
			||||||
				sblock_other = sblock_bad;
 | 
									sblock_other = sblock_bad;
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (scrub_write_sector_to_dev_replace(sblock_other,
 | 
					 | 
				
			||||||
							      sector_num) != 0) {
 | 
					 | 
				
			||||||
				atomic64_inc(
 | 
					 | 
				
			||||||
					&fs_info->dev_replace.num_write_errors);
 | 
					 | 
				
			||||||
				success = 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else if (sblock_other) {
 | 
							} else if (sblock_other) {
 | 
				
			||||||
			ret = scrub_repair_sector_from_good_copy(sblock_bad,
 | 
								ret = scrub_repair_sector_from_good_copy(sblock_bad,
 | 
				
			||||||
								 sblock_other,
 | 
													 sblock_other,
 | 
				
			||||||
| 
						 | 
					@ -1904,31 +1879,6 @@ static int scrub_repair_sector_from_good_copy(struct scrub_block *sblock_bad,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void scrub_write_block_to_dev_replace(struct scrub_block *sblock)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct btrfs_fs_info *fs_info = sblock->sctx->fs_info;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < sblock->sector_count; i++) {
 | 
					 | 
				
			||||||
		int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = scrub_write_sector_to_dev_replace(sblock, i);
 | 
					 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			atomic64_inc(&fs_info->dev_replace.num_write_errors);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int scrub_write_sector_to_dev_replace(struct scrub_block *sblock, int sector_num)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const u32 sectorsize = sblock->sctx->fs_info->sectorsize;
 | 
					 | 
				
			||||||
	struct scrub_sector *sector = sblock->sectors[sector_num];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sector->io_error)
 | 
					 | 
				
			||||||
		memset(scrub_sector_get_kaddr(sector), 0, sectorsize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return scrub_add_sector_to_wr_bio(sblock->sctx, sector);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int fill_writer_pointer_gap(struct scrub_ctx *sctx, u64 physical)
 | 
					static int fill_writer_pointer_gap(struct scrub_ctx *sctx, u64 physical)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
| 
						 | 
					@ -1956,150 +1906,6 @@ static void scrub_block_get(struct scrub_block *sblock)
 | 
				
			||||||
	refcount_inc(&sblock->refs);
 | 
						refcount_inc(&sblock->refs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int scrub_add_sector_to_wr_bio(struct scrub_ctx *sctx,
 | 
					 | 
				
			||||||
				      struct scrub_sector *sector)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct scrub_block *sblock = sector->sblock;
 | 
					 | 
				
			||||||
	struct scrub_bio *sbio;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	const u32 sectorsize = sctx->fs_info->sectorsize;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
again:
 | 
					 | 
				
			||||||
	if (!sctx->wr_curr_bio) {
 | 
					 | 
				
			||||||
		sctx->wr_curr_bio = kzalloc(sizeof(*sctx->wr_curr_bio),
 | 
					 | 
				
			||||||
					      GFP_KERNEL);
 | 
					 | 
				
			||||||
		if (!sctx->wr_curr_bio) {
 | 
					 | 
				
			||||||
			mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
			return -ENOMEM;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sctx->wr_curr_bio->sctx = sctx;
 | 
					 | 
				
			||||||
		sctx->wr_curr_bio->sector_count = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sbio = sctx->wr_curr_bio;
 | 
					 | 
				
			||||||
	if (sbio->sector_count == 0) {
 | 
					 | 
				
			||||||
		ret = fill_writer_pointer_gap(sctx, sector->offset +
 | 
					 | 
				
			||||||
					      sblock->physical_for_dev_replace);
 | 
					 | 
				
			||||||
		if (ret) {
 | 
					 | 
				
			||||||
			mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sbio->physical = sblock->physical_for_dev_replace + sector->offset;
 | 
					 | 
				
			||||||
		sbio->logical = sblock->logical + sector->offset;
 | 
					 | 
				
			||||||
		sbio->dev = sctx->wr_tgtdev;
 | 
					 | 
				
			||||||
		if (!sbio->bio) {
 | 
					 | 
				
			||||||
			sbio->bio = bio_alloc(sbio->dev->bdev, sctx->sectors_per_bio,
 | 
					 | 
				
			||||||
					      REQ_OP_WRITE, GFP_NOFS);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sbio->bio->bi_private = sbio;
 | 
					 | 
				
			||||||
		sbio->bio->bi_end_io = scrub_wr_bio_end_io;
 | 
					 | 
				
			||||||
		sbio->bio->bi_iter.bi_sector = sbio->physical >> 9;
 | 
					 | 
				
			||||||
		sbio->status = 0;
 | 
					 | 
				
			||||||
	} else if (sbio->physical + sbio->sector_count * sectorsize !=
 | 
					 | 
				
			||||||
		   sblock->physical_for_dev_replace + sector->offset ||
 | 
					 | 
				
			||||||
		   sbio->logical + sbio->sector_count * sectorsize !=
 | 
					 | 
				
			||||||
		   sblock->logical + sector->offset) {
 | 
					 | 
				
			||||||
		scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
		goto again;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = bio_add_scrub_sector(sbio->bio, sector, sectorsize);
 | 
					 | 
				
			||||||
	if (ret != sectorsize) {
 | 
					 | 
				
			||||||
		if (sbio->sector_count < 1) {
 | 
					 | 
				
			||||||
			bio_put(sbio->bio);
 | 
					 | 
				
			||||||
			sbio->bio = NULL;
 | 
					 | 
				
			||||||
			mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
			return -EIO;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
		goto again;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sbio->sectors[sbio->sector_count] = sector;
 | 
					 | 
				
			||||||
	scrub_sector_get(sector);
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Since ssector no longer holds a page, but uses sblock::pages, we
 | 
					 | 
				
			||||||
	 * have to ensure the sblock had not been freed before our write bio
 | 
					 | 
				
			||||||
	 * finished.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	scrub_block_get(sector->sblock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sbio->sector_count++;
 | 
					 | 
				
			||||||
	if (sbio->sector_count == sctx->sectors_per_bio)
 | 
					 | 
				
			||||||
		scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
	mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scrub_wr_submit(struct scrub_ctx *sctx)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct scrub_bio *sbio;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sctx->wr_curr_bio)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sbio = sctx->wr_curr_bio;
 | 
					 | 
				
			||||||
	sctx->wr_curr_bio = NULL;
 | 
					 | 
				
			||||||
	scrub_pending_bio_inc(sctx);
 | 
					 | 
				
			||||||
	/* process all writes in a single worker thread. Then the block layer
 | 
					 | 
				
			||||||
	 * orders the requests before sending them to the driver which
 | 
					 | 
				
			||||||
	 * doubled the write performance on spinning disks when measured
 | 
					 | 
				
			||||||
	 * with Linux 3.5 */
 | 
					 | 
				
			||||||
	btrfsic_check_bio(sbio->bio);
 | 
					 | 
				
			||||||
	submit_bio(sbio->bio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (btrfs_is_zoned(sctx->fs_info))
 | 
					 | 
				
			||||||
		sctx->write_pointer = sbio->physical + sbio->sector_count *
 | 
					 | 
				
			||||||
			sctx->fs_info->sectorsize;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scrub_wr_bio_end_io(struct bio *bio)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct scrub_bio *sbio = bio->bi_private;
 | 
					 | 
				
			||||||
	struct btrfs_fs_info *fs_info = sbio->dev->fs_info;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sbio->status = bio->bi_status;
 | 
					 | 
				
			||||||
	sbio->bio = bio;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	INIT_WORK(&sbio->work, scrub_wr_bio_end_io_worker);
 | 
					 | 
				
			||||||
	queue_work(fs_info->scrub_wr_completion_workers, &sbio->work);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void scrub_wr_bio_end_io_worker(struct work_struct *work)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct scrub_bio *sbio = container_of(work, struct scrub_bio, work);
 | 
					 | 
				
			||||||
	struct scrub_ctx *sctx = sbio->sctx;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ASSERT(sbio->sector_count <= SCRUB_SECTORS_PER_BIO);
 | 
					 | 
				
			||||||
	if (sbio->status) {
 | 
					 | 
				
			||||||
		struct btrfs_dev_replace *dev_replace =
 | 
					 | 
				
			||||||
			&sbio->sctx->fs_info->dev_replace;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < sbio->sector_count; i++) {
 | 
					 | 
				
			||||||
			struct scrub_sector *sector = sbio->sectors[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sector->io_error = 1;
 | 
					 | 
				
			||||||
			atomic64_inc(&dev_replace->num_write_errors);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * In scrub_add_sector_to_wr_bio() we grab extra ref for sblock, now in
 | 
					 | 
				
			||||||
	 * endio we should put the sblock.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	for (i = 0; i < sbio->sector_count; i++) {
 | 
					 | 
				
			||||||
		scrub_block_put(sbio->sectors[i]->sblock);
 | 
					 | 
				
			||||||
		scrub_sector_put(sbio->sectors[i]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bio_put(sbio->bio);
 | 
					 | 
				
			||||||
	kfree(sbio);
 | 
					 | 
				
			||||||
	scrub_pending_bio_dec(sctx);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int scrub_checksum(struct scrub_block *sblock)
 | 
					static int scrub_checksum(struct scrub_block *sblock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 flags;
 | 
						u64 flags;
 | 
				
			||||||
| 
						 | 
					@ -2904,7 +2710,7 @@ static void scrub_block_put(struct scrub_block *sblock)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void scrub_sector_get(struct scrub_sector *sector)
 | 
					void scrub_sector_get(struct scrub_sector *sector)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	atomic_inc(§or->refs);
 | 
						atomic_inc(§or->refs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3105,21 +2911,12 @@ static void scrub_bio_end_io_worker(struct work_struct *work)
 | 
				
			||||||
	sctx->first_free = sbio->index;
 | 
						sctx->first_free = sbio->index;
 | 
				
			||||||
	spin_unlock(&sctx->list_lock);
 | 
						spin_unlock(&sctx->list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sctx->is_dev_replace && sctx->flush_all_writes) {
 | 
					 | 
				
			||||||
		mutex_lock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
		scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
		mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scrub_pending_bio_dec(sctx);
 | 
						scrub_pending_bio_dec(sctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void scrub_block_complete(struct scrub_block *sblock)
 | 
					static void scrub_block_complete(struct scrub_block *sblock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int corrupted = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sblock->no_io_error_seen) {
 | 
						if (!sblock->no_io_error_seen) {
 | 
				
			||||||
		corrupted = 1;
 | 
					 | 
				
			||||||
		scrub_handle_errored_block(sblock);
 | 
							scrub_handle_errored_block(sblock);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -3127,9 +2924,7 @@ static void scrub_block_complete(struct scrub_block *sblock)
 | 
				
			||||||
		 * dev replace case, otherwise write here in dev replace
 | 
							 * dev replace case, otherwise write here in dev replace
 | 
				
			||||||
		 * case.
 | 
							 * case.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		corrupted = scrub_checksum(sblock);
 | 
							scrub_checksum(sblock);
 | 
				
			||||||
		if (!corrupted && sblock->sctx->is_dev_replace)
 | 
					 | 
				
			||||||
			scrub_write_block_to_dev_replace(sblock);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3904,14 +3699,11 @@ static int scrub_simple_mirror(struct scrub_ctx *sctx,
 | 
				
			||||||
		/* Paused? */
 | 
							/* Paused? */
 | 
				
			||||||
		if (atomic_read(&fs_info->scrub_pause_req)) {
 | 
							if (atomic_read(&fs_info->scrub_pause_req)) {
 | 
				
			||||||
			/* Push queued extents */
 | 
								/* Push queued extents */
 | 
				
			||||||
			sctx->flush_all_writes = true;
 | 
					 | 
				
			||||||
			scrub_submit(sctx);
 | 
								scrub_submit(sctx);
 | 
				
			||||||
			mutex_lock(&sctx->wr_lock);
 | 
								mutex_lock(&sctx->wr_lock);
 | 
				
			||||||
			scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
			mutex_unlock(&sctx->wr_lock);
 | 
								mutex_unlock(&sctx->wr_lock);
 | 
				
			||||||
			wait_event(sctx->list_wait,
 | 
								wait_event(sctx->list_wait,
 | 
				
			||||||
				   atomic_read(&sctx->bios_in_flight) == 0);
 | 
									   atomic_read(&sctx->bios_in_flight) == 0);
 | 
				
			||||||
			sctx->flush_all_writes = false;
 | 
					 | 
				
			||||||
			scrub_blocked_if_needed(fs_info);
 | 
								scrub_blocked_if_needed(fs_info);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* Block group removed? */
 | 
							/* Block group removed? */
 | 
				
			||||||
| 
						 | 
					@ -4048,7 +3840,6 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 | 
				
			||||||
		mutex_lock(&sctx->wr_lock);
 | 
							mutex_lock(&sctx->wr_lock);
 | 
				
			||||||
		sctx->write_pointer = physical;
 | 
							sctx->write_pointer = physical;
 | 
				
			||||||
		mutex_unlock(&sctx->wr_lock);
 | 
							mutex_unlock(&sctx->wr_lock);
 | 
				
			||||||
		sctx->flush_all_writes = true;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Prepare the extra data stripes used by RAID56. */
 | 
						/* Prepare the extra data stripes used by RAID56. */
 | 
				
			||||||
| 
						 | 
					@ -4159,9 +3950,6 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	/* push queued extents */
 | 
						/* push queued extents */
 | 
				
			||||||
	scrub_submit(sctx);
 | 
						scrub_submit(sctx);
 | 
				
			||||||
	mutex_lock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
	scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
	mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
	flush_scrub_stripes(sctx);
 | 
						flush_scrub_stripes(sctx);
 | 
				
			||||||
	if (sctx->raid56_data_stripes) {
 | 
						if (sctx->raid56_data_stripes) {
 | 
				
			||||||
		for (int i = 0; i < nr_data_stripes(map); i++)
 | 
							for (int i = 0; i < nr_data_stripes(map); i++)
 | 
				
			||||||
| 
						 | 
					@ -4497,11 +4285,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 | 
				
			||||||
		 * write requests are really completed when bios_in_flight
 | 
							 * write requests are really completed when bios_in_flight
 | 
				
			||||||
		 * changes to 0.
 | 
							 * changes to 0.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		sctx->flush_all_writes = true;
 | 
					 | 
				
			||||||
		scrub_submit(sctx);
 | 
							scrub_submit(sctx);
 | 
				
			||||||
		mutex_lock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
		scrub_wr_submit(sctx);
 | 
					 | 
				
			||||||
		mutex_unlock(&sctx->wr_lock);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wait_event(sctx->list_wait,
 | 
							wait_event(sctx->list_wait,
 | 
				
			||||||
			   atomic_read(&sctx->bios_in_flight) == 0);
 | 
								   atomic_read(&sctx->bios_in_flight) == 0);
 | 
				
			||||||
| 
						 | 
					@ -4515,7 +4299,6 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		wait_event(sctx->list_wait,
 | 
							wait_event(sctx->list_wait,
 | 
				
			||||||
			   atomic_read(&sctx->workers_pending) == 0);
 | 
								   atomic_read(&sctx->workers_pending) == 0);
 | 
				
			||||||
		sctx->flush_all_writes = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		scrub_pause_off(fs_info);
 | 
							scrub_pause_off(fs_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,5 +19,6 @@ struct scrub_sector;
 | 
				
			||||||
int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum);
 | 
					int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum);
 | 
				
			||||||
int scrub_add_sector_to_rd_bio(struct scrub_ctx *sctx,
 | 
					int scrub_add_sector_to_rd_bio(struct scrub_ctx *sctx,
 | 
				
			||||||
			       struct scrub_sector *sector);
 | 
								       struct scrub_sector *sector);
 | 
				
			||||||
 | 
					void scrub_sector_get(struct scrub_sector *sector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue