Skip to content

Commit 43e43c9

Browse files
nomuranecsnitm
authored andcommitted
dm mpath: fix infinite recursion in ioctl when no paths and !queue_if_no_path
In multipath_prepare_ioctl(), - pgpath is a path selected from available paths - m->queue_io is true if we cannot send a request immediately to paths, either because: * there is no available path * the path group needs activation (pg_init) - pg_init is not started - pg_init is still running - m->queue_if_no_path is true if the device is configured to queue I/O if there are no available paths If !pgpath && !m->queue_if_no_path, the handler should return -EIO. However in the course of refactoring the condition check has broken and returns success in that case. Since bdev points to the dm device itself, dm_blk_ioctl() calls __blk_dev_driver_ioctl() for itself and recurses until crash. You could reproduce the problem like this: # dmsetup create mp --table '0 1024 multipath 0 0 0 0' # sg_inq /dev/mapper/mp <crash> [ 172.648615] BUG: unable to handle kernel paging request at fffffffc81b10268 [ 172.662843] PGD 19dd067 PUD 0 [ 172.666269] Thread overran stack, or stack corrupted [ 172.671808] Oops: 0000 [#1] SMP ... Fix the condition check with some clarifications. Fixes: e56f81e ("dm: refactor ioctl handling") Signed-off-by: Jun'ichi Nomura <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Mike Snitzer <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 647a20d commit 43e43c9

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

drivers/md/dm-mpath.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,29 +1537,31 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
15371537
struct block_device **bdev, fmode_t *mode)
15381538
{
15391539
struct multipath *m = ti->private;
1540-
struct pgpath *pgpath;
15411540
unsigned long flags;
15421541
int r;
15431542

1544-
r = 0;
1545-
15461543
spin_lock_irqsave(&m->lock, flags);
15471544

15481545
if (!m->current_pgpath)
15491546
__choose_pgpath(m, 0);
15501547

1551-
pgpath = m->current_pgpath;
1552-
1553-
if (pgpath) {
1554-
*bdev = pgpath->path.dev->bdev;
1555-
*mode = pgpath->path.dev->mode;
1548+
if (m->current_pgpath) {
1549+
if (!m->queue_io) {
1550+
*bdev = m->current_pgpath->path.dev->bdev;
1551+
*mode = m->current_pgpath->path.dev->mode;
1552+
r = 0;
1553+
} else {
1554+
/* pg_init has not started or completed */
1555+
r = -ENOTCONN;
1556+
}
1557+
} else {
1558+
/* No path is available */
1559+
if (m->queue_if_no_path)
1560+
r = -ENOTCONN;
1561+
else
1562+
r = -EIO;
15561563
}
15571564

1558-
if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
1559-
r = -ENOTCONN;
1560-
else if (!*bdev)
1561-
r = -EIO;
1562-
15631565
spin_unlock_irqrestore(&m->lock, flags);
15641566

15651567
if (r == -ENOTCONN) {

0 commit comments

Comments
 (0)