diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 62 | 
1 files changed, 44 insertions, 18 deletions
| diff --git a/drivers/md/md.c b/drivers/md/md.c index 5111ed966947..5881d05a76eb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -418,6 +418,12 @@ check_suspended:  	rcu_read_lock();  	if (is_suspended(mddev, bio)) {  		DEFINE_WAIT(__wait); +		/* Bail out if REQ_NOWAIT is set for the bio */ +		if (bio->bi_opf & REQ_NOWAIT) { +			rcu_read_unlock(); +			bio_wouldblock_error(bio); +			return; +		}  		for (;;) {  			prepare_to_wait(&mddev->sb_wait, &__wait,  					TASK_UNINTERRUPTIBLE); @@ -2189,6 +2195,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)  		if (!num_sectors || num_sectors > max_sectors)  			num_sectors = max_sectors; +		rdev->sb_start = sb_start;  	}  	sb = page_address(rdev->sb_page);  	sb->data_size = cpu_to_le64(num_sectors); @@ -3602,6 +3609,7 @@ static struct attribute *rdev_default_attrs[] = {  	&rdev_ppl_size.attr,  	NULL,  }; +ATTRIBUTE_GROUPS(rdev_default);  static ssize_t  rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page)  { @@ -3651,7 +3659,7 @@ static const struct sysfs_ops rdev_sysfs_ops = {  static struct kobj_type rdev_ktype = {  	.release	= rdev_free,  	.sysfs_ops	= &rdev_sysfs_ops, -	.default_attrs	= rdev_default_attrs, +	.default_groups	= rdev_default_groups,  };  int md_rdev_init(struct md_rdev *rdev) @@ -5707,11 +5715,6 @@ static int md_alloc(dev_t dev, char *name)  	mddev->queue = disk->queue;  	blk_set_stacking_limits(&mddev->queue->limits);  	blk_queue_write_cache(mddev->queue, true, true); -	/* Allow extended partitions.  This makes the -	 * 'mdp' device redundant, but we can't really -	 * remove it now. -	 */ -	disk->flags |= GENHD_FL_EXT_DEVT;  	disk->events |= DISK_EVENT_MEDIA_CHANGE;  	mddev->gendisk = disk;  	error = add_disk(disk); @@ -5792,6 +5795,7 @@ int md_run(struct mddev *mddev)  	int err;  	struct md_rdev *rdev;  	struct md_personality *pers; +	bool nowait = true;  	if (list_empty(&mddev->disks))  		/* cannot run an array with no devices.. */ @@ -5862,8 +5866,13 @@ int md_run(struct mddev *mddev)  			}  		}  		sysfs_notify_dirent_safe(rdev->sysfs_state); +		nowait = nowait && blk_queue_nowait(bdev_get_queue(rdev->bdev));  	} +	/* Set the NOWAIT flags if all underlying devices support it */ +	if (nowait) +		blk_queue_flag_set(QUEUE_FLAG_NOWAIT, mddev->queue); +  	if (!bioset_initialized(&mddev->bio_set)) {  		err = bioset_init(&mddev->bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);  		if (err) @@ -5874,13 +5883,6 @@ int md_run(struct mddev *mddev)  		if (err)  			goto exit_bio_set;  	} -	if (mddev->level != 1 && mddev->level != 10 && -	    !bioset_initialized(&mddev->io_acct_set)) { -		err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE, -				  offsetof(struct md_io_acct, bio_clone), 0); -		if (err) -			goto exit_sync_set; -	}  	spin_lock(&pers_lock);  	pers = find_pers(mddev->level, mddev->clevel); @@ -6057,9 +6059,6 @@ bitmap_abort:  	module_put(pers->owner);  	md_bitmap_destroy(mddev);  abort: -	if (mddev->level != 1 && mddev->level != 10) -		bioset_exit(&mddev->io_acct_set); -exit_sync_set:  	bioset_exit(&mddev->sync_set);  exit_bio_set:  	bioset_exit(&mddev->bio_set); @@ -6270,7 +6269,8 @@ static void __md_stop(struct mddev *mddev)  	spin_lock(&mddev->lock);  	mddev->pers = NULL;  	spin_unlock(&mddev->lock); -	pers->free(mddev, mddev->private); +	if (mddev->private) +		pers->free(mddev, mddev->private);  	mddev->private = NULL;  	if (pers->sync_request && mddev->to_remove == NULL)  		mddev->to_remove = &md_redundancy_group; @@ -7008,6 +7008,15 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)  	if (!mddev->thread)  		md_update_sb(mddev, 1);  	/* +	 * If the new disk does not support REQ_NOWAIT, +	 * disable on the whole MD. +	 */ +	if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) { +		pr_info("%s: Disabling nowait because %s does not support nowait\n", +			mdname(mddev), bdevname(rdev->bdev, b)); +		blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue); +	} +	/*  	 * Kick recovery, maybe this spare has to be added to the  	 * array immediately.  	 */ @@ -8405,7 +8414,7 @@ int md_setup_cluster(struct mddev *mddev, int nodes)  	spin_lock(&pers_lock);  	/* ensure module won't be unloaded */  	if (!md_cluster_ops || !try_module_get(md_cluster_mod)) { -		pr_warn("can't find md-cluster module or get it's reference.\n"); +		pr_warn("can't find md-cluster module or get its reference.\n");  		spin_unlock(&pers_lock);  		return -ENOENT;  	} @@ -8592,6 +8601,23 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,  }  EXPORT_SYMBOL_GPL(md_submit_discard_bio); +int acct_bioset_init(struct mddev *mddev) +{ +	int err = 0; + +	if (!bioset_initialized(&mddev->io_acct_set)) +		err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE, +			offsetof(struct md_io_acct, bio_clone), 0); +	return err; +} +EXPORT_SYMBOL_GPL(acct_bioset_init); + +void acct_bioset_exit(struct mddev *mddev) +{ +	bioset_exit(&mddev->io_acct_set); +} +EXPORT_SYMBOL_GPL(acct_bioset_exit); +  static void md_end_io_acct(struct bio *bio)  {  	struct md_io_acct *md_io_acct = bio->bi_private; |