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: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Cc: Mike Snitzer <snitzer@redhat.com> Acked-by: Hannes Reinecke <hare@suse.de> Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com> Acked-by: Dave Wysochanski <dwysocha@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
parent
4d7b38b7d9
commit
466891f995
1 changed files with 32 additions and 14 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue