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

Commit 0001ec56 authored by Mike Snitzer's avatar Mike Snitzer
Browse files

dm mpath: factor out SCSI vs NVMe path selection



Trying to do both SCSI and NVMe bio-based handling with branching in the
same common code has proven too tedious on a code maintenance level.  In
addition it slightly hurts IO performance.

Fix this by factoring out __map_bio() and __map_bio_nvme().

Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent 848b8aef
Loading
Loading
Loading
Loading
+55 −13
Original line number Original line Diff line number Diff line
@@ -555,7 +555,8 @@ static void multipath_release_clone(struct request *clone)
/*
/*
 * Map cloned bios (bio-based multipath)
 * Map cloned bios (bio-based multipath)
 */
 */
static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_mpath_io *mpio)

static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
{
{
	struct pgpath *pgpath;
	struct pgpath *pgpath;
	unsigned long flags;
	unsigned long flags;
@@ -563,31 +564,72 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m


	/* Do we need to select a new pgpath? */
	/* Do we need to select a new pgpath? */
	pgpath = READ_ONCE(m->current_pgpath);
	pgpath = READ_ONCE(m->current_pgpath);
	/* MPATHF_QUEUE_IO will never be set for NVMe */
	queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
	queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
	if (!pgpath || !queue_io)
	if (!pgpath || !queue_io)
		pgpath = choose_pgpath(m, mpio->nr_bytes);
		pgpath = choose_pgpath(m, bio->bi_iter.bi_size);


	if ((!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) ||
	if ((pgpath && queue_io) ||
	    (pgpath && queue_io)) {
	    (!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
		/* Queue for the daemon to resubmit */
		/* Queue for the daemon to resubmit */
		spin_lock_irqsave(&m->lock, flags);
		spin_lock_irqsave(&m->lock, flags);
		bio_list_add(&m->queued_bios, bio);
		bio_list_add(&m->queued_bios, bio);
		spin_unlock_irqrestore(&m->lock, flags);
		spin_unlock_irqrestore(&m->lock, flags);


		if (m->queue_mode == DM_TYPE_NVME_BIO_BASED) {
			queue_work(kmultipathd, &m->process_queued_bios);
		} else {
		/* PG_INIT_REQUIRED cannot be set without QUEUE_IO */
		/* PG_INIT_REQUIRED cannot be set without QUEUE_IO */
		if (queue_io || test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
		if (queue_io || test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
			pg_init_all_paths(m);
			pg_init_all_paths(m);
		else if (!queue_io)
		else if (!queue_io)
			queue_work(kmultipathd, &m->process_queued_bios);
			queue_work(kmultipathd, &m->process_queued_bios);

		return ERR_PTR(-EAGAIN);
	}
	}


		return DM_MAPIO_SUBMITTED;
	return pgpath;
}

static struct pgpath *__map_bio_nvme(struct multipath *m, struct bio *bio)
{
	struct pgpath *pgpath;
	unsigned long flags;

	/* Do we need to select a new pgpath? */
	/*
	 * FIXME: currently only switching path if no path (due to failure, etc)
	 * - which negates the point of using a path selector
	 */
	pgpath = READ_ONCE(m->current_pgpath);
	if (!pgpath)
		pgpath = choose_pgpath(m, bio->bi_iter.bi_size);

	if (!pgpath) {
		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
			/* Queue for the daemon to resubmit */
			spin_lock_irqsave(&m->lock, flags);
			bio_list_add(&m->queued_bios, bio);
			spin_unlock_irqrestore(&m->lock, flags);
			queue_work(kmultipathd, &m->process_queued_bios);

			return ERR_PTR(-EAGAIN);
		}
		return NULL;
	}
	}


	return pgpath;
}

static int __multipath_map_bio(struct multipath *m, struct bio *bio,
			       struct dm_mpath_io *mpio)
{
	struct pgpath *pgpath;

	if (m->queue_mode == DM_TYPE_NVME_BIO_BASED)
		pgpath = __map_bio_nvme(m, bio);
	else
		pgpath = __map_bio(m, bio);

	if (IS_ERR(pgpath))
		return DM_MAPIO_SUBMITTED;

	if (!pgpath) {
	if (!pgpath) {
		if (must_push_back_bio(m))
		if (must_push_back_bio(m))
			return DM_MAPIO_REQUEUE;
			return DM_MAPIO_REQUEUE;