aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2011-05-29 08:02:52 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-05-29 08:02:52 -0400
commitf4808ca99a203f20b4475601748e44b25a65bdec (patch)
tree442641730674c130ec228c626b94606ad4f2e3c7 /drivers
parent4c2593270133708698d4b8cea2dab469479ad13b (diff)
dm table: reject devices without request fns
This patch adds a check that a block device has a request function defined before it is used. Otherwise, misconfiguration can cause an oops. Because we are allowing devices with zero size e.g. an offline multipath device as in commit 2cd54d9bedb79a97f014e86c0da393416b264eb3 ("dm: allow offline devices") there needs to be an additional check to ensure devices are initialised. Some block devices, like a loop device without a backing file, exist but have no request function. Reproducer is trivial: dm-mirror on unbound loop device (no backing file on loop devices) dmsetup create x --table "0 8 mirror core 2 8 sync 2 /dev/loop0 0 /dev/loop1 0" and mirror resync will immediatelly cause OOps. BUG: unable to handle kernel NULL pointer dereference at (null) ? generic_make_request+0x2bd/0x590 ? kmem_cache_alloc+0xad/0x190 submit_bio+0x53/0xe0 ? bio_add_page+0x3b/0x50 dispatch_io+0x1ca/0x210 [dm_mod] ? read_callback+0x0/0xd0 [dm_mirror] dm_io+0xbb/0x290 [dm_mod] do_mirror+0x1e0/0x748 [dm_mirror] Signed-off-by: Milan Broz <mbroz@redhat.com> Reported-by: Zdenek Kabelac <zkabelac@redhat.com> Acked-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@kernel.org Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-table.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 215e112d153e..451c3bb176d2 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -362,6 +362,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
362static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, 362static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
363 sector_t start, sector_t len, void *data) 363 sector_t start, sector_t len, void *data)
364{ 364{
365 struct request_queue *q;
365 struct queue_limits *limits = data; 366 struct queue_limits *limits = data;
366 struct block_device *bdev = dev->bdev; 367 struct block_device *bdev = dev->bdev;
367 sector_t dev_size = 368 sector_t dev_size =
@@ -370,6 +371,22 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
370 limits->logical_block_size >> SECTOR_SHIFT; 371 limits->logical_block_size >> SECTOR_SHIFT;
371 char b[BDEVNAME_SIZE]; 372 char b[BDEVNAME_SIZE];
372 373
374 /*
375 * Some devices exist without request functions,
376 * such as loop devices not yet bound to backing files.
377 * Forbid the use of such devices.
378 */
379 q = bdev_get_queue(bdev);
380 if (!q || !q->make_request_fn) {
381 DMWARN("%s: %s is not yet initialised: "
382 "start=%llu, len=%llu, dev_size=%llu",
383 dm_device_name(ti->table->md), bdevname(bdev, b),
384 (unsigned long long)start,
385 (unsigned long long)len,
386 (unsigned long long)dev_size);
387 return 1;
388 }
389
373 if (!dev_size) 390 if (!dev_size)
374 return 0; 391 return 0;
375 392