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

Commit 026d15f6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MD update from Shaohua Li:

 - fixed deadlock in MD suspend and a potential bug in bio allocation
   (Neil Brown)

 - fixed signal issue (Mikulas Patocka)

 - fixed typo in FailFast test (Guoqing Jiang)

 - other trival fixes

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md:
  MD: fix sleep in atomic
  MD: fix a null dereference
  md: use a separate bio_set for synchronous IO.
  md: change the initialization value for a spare device spot to MD_DISK_ROLE_SPARE
  md/raid1: remove unused bio in sync_request_write
  md/raid10: fix FailFast test for wrong device
  md: don't use flush_signals in userspace processes
  md: fix deadlock between mddev_suspend() and md_write_start()
parents 43d01209 7184ef8b
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ static void add_sector(struct faulty_conf *conf, sector_t start, int mode)
		conf->nfaults = n+1;
}

static void faulty_make_request(struct mddev *mddev, struct bio *bio)
static bool faulty_make_request(struct mddev *mddev, struct bio *bio)
{
	struct faulty_conf *conf = mddev->private;
	int failit = 0;
@@ -182,7 +182,7 @@ static void faulty_make_request(struct mddev *mddev, struct bio *bio)
			 * just fail immediately
			 */
			bio_io_error(bio);
			return;
			return true;
		}

		if (check_sector(conf, bio->bi_iter.bi_sector,
@@ -224,6 +224,7 @@ static void faulty_make_request(struct mddev *mddev, struct bio *bio)
		bio->bi_bdev = conf->rdev->bdev;

	generic_make_request(bio);
	return true;
}

static void faulty_status(struct seq_file *seq, struct mddev *mddev)
+4 −3
Original line number Diff line number Diff line
@@ -245,7 +245,7 @@ static void linear_free(struct mddev *mddev, void *priv)
	kfree(conf);
}

static void linear_make_request(struct mddev *mddev, struct bio *bio)
static bool linear_make_request(struct mddev *mddev, struct bio *bio)
{
	char b[BDEVNAME_SIZE];
	struct dev_info *tmp_dev;
@@ -254,7 +254,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)

	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
		md_flush_request(mddev, bio);
		return;
		return true;
	}

	tmp_dev = which_dev(mddev, bio_sector);
@@ -292,7 +292,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
		mddev_check_write_zeroes(mddev, bio);
		generic_make_request(bio);
	}
	return;
	return true;

out_of_bounds:
	pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %s: %llu sectors, offset %llu\n",
@@ -302,6 +302,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
	       (unsigned long long)tmp_dev->rdev->sectors,
	       (unsigned long long)start_sector);
	bio_io_error(bio);
	return true;
}

static void linear_status (struct seq_file *seq, struct mddev *mddev)
+38 −9
Original line number Diff line number Diff line
@@ -203,6 +203,14 @@ struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
}
EXPORT_SYMBOL_GPL(bio_alloc_mddev);

static struct bio *md_bio_alloc_sync(struct mddev *mddev)
{
	if (!mddev || !mddev->sync_set)
		return bio_alloc(GFP_NOIO, 1);

	return bio_alloc_bioset(GFP_NOIO, 1, mddev->sync_set);
}

/*
 * We have a system wide 'event count' that is incremented
 * on any 'interesting' event, and readers of /proc/mdstat
@@ -277,7 +285,7 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
		bio_endio(bio);
		return BLK_QC_T_NONE;
	}
	smp_rmb(); /* Ensure implications of  'active' are visible */
check_suspended:
	rcu_read_lock();
	if (mddev->suspended) {
		DEFINE_WAIT(__wait);
@@ -302,7 +310,11 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
	sectors = bio_sectors(bio);
	/* bio could be mergeable after passing to underlayer */
	bio->bi_opf &= ~REQ_NOMERGE;
	mddev->pers->make_request(mddev, bio);
	if (!mddev->pers->make_request(mddev, bio)) {
		atomic_dec(&mddev->active_io);
		wake_up(&mddev->sb_wait);
		goto check_suspended;
	}

	cpu = part_stat_lock();
	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
@@ -327,6 +339,7 @@ void mddev_suspend(struct mddev *mddev)
	if (mddev->suspended++)
		return;
	synchronize_rcu();
	wake_up(&mddev->sb_wait);
	wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
	mddev->pers->quiesce(mddev, 1);

@@ -462,7 +475,7 @@ static void mddev_delayed_delete(struct work_struct *ws);

static void mddev_put(struct mddev *mddev)
{
	struct bio_set *bs = NULL;
	struct bio_set *bs = NULL, *sync_bs = NULL;

	if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
		return;
@@ -472,7 +485,9 @@ static void mddev_put(struct mddev *mddev)
		 * so destroy it */
		list_del_init(&mddev->all_mddevs);
		bs = mddev->bio_set;
		sync_bs = mddev->sync_set;
		mddev->bio_set = NULL;
		mddev->sync_set = NULL;
		if (mddev->gendisk) {
			/* We did a probe so need to clean up.  Call
			 * queue_work inside the spinlock so that
@@ -487,6 +502,8 @@ static void mddev_put(struct mddev *mddev)
	spin_unlock(&all_mddevs_lock);
	if (bs)
		bioset_free(bs);
	if (sync_bs)
		bioset_free(sync_bs);
}

static void md_safemode_timeout(unsigned long data);
@@ -751,7 +768,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
	if (test_bit(Faulty, &rdev->flags))
		return;

	bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
	bio = md_bio_alloc_sync(mddev);

	atomic_inc(&rdev->nr_pending);

@@ -783,7 +800,7 @@ int md_super_wait(struct mddev *mddev)
int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
		 struct page *page, int op, int op_flags, bool metadata_op)
{
	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
	struct bio *bio = md_bio_alloc_sync(rdev->mddev);
	int ret;

	bio->bi_bdev = (metadata_op && rdev->meta_bdev) ?
@@ -1852,7 +1869,7 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
		max_dev = le32_to_cpu(sb->max_dev);

	for (i=0; i<max_dev;i++)
		sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_FAULTY);
		sb->dev_roles[i] = cpu_to_le16(MD_DISK_ROLE_SPARE);

	if (test_bit(MD_HAS_JOURNAL, &mddev->flags))
		sb->feature_map |= cpu_to_le32(MD_FEATURE_JOURNAL);
@@ -5432,6 +5449,11 @@ int md_run(struct mddev *mddev)
		if (!mddev->bio_set)
			return -ENOMEM;
	}
	if (mddev->sync_set == NULL) {
		mddev->sync_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
		if (!mddev->sync_set)
			return -ENOMEM;
	}

	spin_lock(&pers_lock);
	pers = find_pers(mddev->level, mddev->clevel);
@@ -7950,12 +7972,14 @@ EXPORT_SYMBOL(md_done_sync);
 * If we need to update some array metadata (e.g. 'active' flag
 * in superblock) before writing, schedule a superblock update
 * and wait for it to complete.
 * A return value of 'false' means that the write wasn't recorded
 * and cannot proceed as the array is being suspend.
 */
void md_write_start(struct mddev *mddev, struct bio *bi)
bool md_write_start(struct mddev *mddev, struct bio *bi)
{
	int did_change = 0;
	if (bio_data_dir(bi) != WRITE)
		return;
		return true;

	BUG_ON(mddev->ro == 1);
	if (mddev->ro == 2) {
@@ -7987,7 +8011,12 @@ void md_write_start(struct mddev *mddev, struct bio *bi)
	if (did_change)
		sysfs_notify_dirent_safe(mddev->sysfs_state);
	wait_event(mddev->sb_wait,
		   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
		   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) && !mddev->suspended);
	if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
		percpu_ref_put(&mddev->writes_pending);
		return false;
	}
	return true;
}
EXPORT_SYMBOL(md_write_start);

+5 −2
Original line number Diff line number Diff line
@@ -444,6 +444,9 @@ struct mddev {
	struct attribute_group		*to_remove;

	struct bio_set			*bio_set;
	struct bio_set			*sync_set; /* for sync operations like
						   * metadata and bitmap writes
						   */

	/* Generic flush handling.
	 * The last to finish preflush schedules a worker to submit
@@ -510,7 +513,7 @@ struct md_personality
	int level;
	struct list_head list;
	struct module *owner;
	void (*make_request)(struct mddev *mddev, struct bio *bio);
	bool (*make_request)(struct mddev *mddev, struct bio *bio);
	int (*run)(struct mddev *mddev);
	void (*free)(struct mddev *mddev, void *priv);
	void (*status)(struct seq_file *seq, struct mddev *mddev);
@@ -649,7 +652,7 @@ extern void md_wakeup_thread(struct md_thread *thread);
extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev);
extern int mddev_init_writes_pending(struct mddev *mddev);
extern void md_write_start(struct mddev *mddev, struct bio *bi);
extern bool md_write_start(struct mddev *mddev, struct bio *bi);
extern void md_write_inc(struct mddev *mddev, struct bio *bi);
extern void md_write_end(struct mddev *mddev);
extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
+4 −4
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ static void multipath_end_request(struct bio *bio)
	rdev_dec_pending(rdev, conf->mddev);
}

static void multipath_make_request(struct mddev *mddev, struct bio * bio)
static bool multipath_make_request(struct mddev *mddev, struct bio * bio)
{
	struct mpconf *conf = mddev->private;
	struct multipath_bh * mp_bh;
@@ -114,7 +114,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)

	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
		md_flush_request(mddev, bio);
		return;
		return true;
	}

	mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
@@ -126,7 +126,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
	if (mp_bh->path < 0) {
		bio_io_error(bio);
		mempool_free(mp_bh, conf->pool);
		return;
		return true;
	}
	multipath = conf->multipaths + mp_bh->path;

@@ -141,7 +141,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
	mddev_check_writesame(mddev, &mp_bh->bio);
	mddev_check_write_zeroes(mddev, &mp_bh->bio);
	generic_make_request(&mp_bh->bio);
	return;
	return true;
}

static void multipath_status(struct seq_file *seq, struct mddev *mddev)
Loading