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

Commit 466891f9 authored by Jun'ichi Nomura's avatar Jun'ichi Nomura Committed by Alasdair G Kergon
Browse files

dm mpath: detect invalid map_context



The map_context pointer should always be set. However, we have reports
that upon requeuing it is not set correctly.  So add set and clear
functions with a BUG_ON() to track the issue properly.

Signed-off-by: default avatarJun'ichi Nomura <j-nomura@ce.jp.nec.com>
Cc: Mike Snitzer <snitzer@redhat.com>
Acked-by: default avatarHannes Reinecke <hare@suse.de>
Tested-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Acked-by: default avatarDave Wysochanski <dwysocha@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 4d7b38b7
Loading
Loading
Loading
Loading
+32 −14
Original line number Diff line number Diff line
@@ -226,6 +226,27 @@ static void free_multipath(struct multipath *m)
	kfree(m);
}

static int set_mapinfo(struct multipath *m, union map_info *info)
{
	struct dm_mpath_io *mpio;

	mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
	if (!mpio)
		return -ENOMEM;

	memset(mpio, 0, sizeof(*mpio));
	info->ptr = mpio;

	return 0;
}

static void clear_mapinfo(struct multipath *m, union map_info *info)
{
	struct dm_mpath_io *mpio = info->ptr;

	info->ptr = NULL;
	mempool_free(mpio, m->mpio_pool);
}

/*-----------------------------------------------
 * Path selection
@@ -341,13 +362,14 @@ static int __must_push_back(struct multipath *m)
}

static int map_io(struct multipath *m, struct request *clone,
		  struct dm_mpath_io *mpio, unsigned was_queued)
		  union map_info *map_context, unsigned was_queued)
{
	int r = DM_MAPIO_REMAPPED;
	size_t nr_bytes = blk_rq_bytes(clone);
	unsigned long flags;
	struct pgpath *pgpath;
	struct block_device *bdev;
	struct dm_mpath_io *mpio = map_context->ptr;

	spin_lock_irqsave(&m->lock, flags);

@@ -423,7 +445,6 @@ static void dispatch_queued_ios(struct multipath *m)
{
	int r;
	unsigned long flags;
	struct dm_mpath_io *mpio;
	union map_info *info;
	struct request *clone, *n;
	LIST_HEAD(cl);
@@ -436,16 +457,15 @@ static void dispatch_queued_ios(struct multipath *m)
		list_del_init(&clone->queuelist);

		info = dm_get_rq_mapinfo(clone);
		mpio = info->ptr;

		r = map_io(m, clone, mpio, 1);
		r = map_io(m, clone, info, 1);
		if (r < 0) {
			mempool_free(mpio, m->mpio_pool);
			clear_mapinfo(m, info);
			dm_kill_unmapped_request(clone, r);
		} else if (r == DM_MAPIO_REMAPPED)
			dm_dispatch_request(clone);
		else if (r == DM_MAPIO_REQUEUE) {
			mempool_free(mpio, m->mpio_pool);
			clear_mapinfo(m, info);
			dm_requeue_unmapped_request(clone);
		}
	}
@@ -908,20 +928,16 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
			 union map_info *map_context)
{
	int r;
	struct dm_mpath_io *mpio;
	struct multipath *m = (struct multipath *) ti->private;

	mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC);
	if (!mpio)
	if (set_mapinfo(m, map_context) < 0)
		/* ENOMEM, requeue */
		return DM_MAPIO_REQUEUE;
	memset(mpio, 0, sizeof(*mpio));

	map_context->ptr = mpio;
	clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
	r = map_io(m, clone, mpio, 0);
	r = map_io(m, clone, map_context, 0);
	if (r < 0 || r == DM_MAPIO_REQUEUE)
		mempool_free(mpio, m->mpio_pool);
		clear_mapinfo(m, map_context);

	return r;
}
@@ -1261,13 +1277,15 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
	struct path_selector *ps;
	int r;

	BUG_ON(!mpio);

	r  = do_end_io(m, clone, error, mpio);
	if (pgpath) {
		ps = &pgpath->pg->ps;
		if (ps->type->end_io)
			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
	}
	mempool_free(mpio, m->mpio_pool);
	clear_mapinfo(m, map_context);

	return r;
}