aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-08-25 06:47:25 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-10-09 02:56:06 -0400
commit870d6656126add8e383645732b03df2b7ccd4f94 (patch)
tree9c33dd91350ea163b160d9f5cb40d913c5caf268
parentf615b48cc7df7cac3865ec76ac1a5bb04d3e07f4 (diff)
block: implement CONFIG_DEBUG_BLOCK_EXT_DEVT
Extended devt introduces non-contiguos device numbers. This patch implements a debug option which forces most devt allocations to be from the extended area and spreads them out. This is enabled by default if DEBUG_KERNEL is set and achieves... 1. Detects code paths in kernel or userland which expect predetermined consecutive device numbers. 2. When something goes wrong, avoid corruption as adding to the minor of earlier partition won't lead to the wrong but valid device. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--block/genhd.c38
-rw-r--r--drivers/ide/ide-disk.c6
-rw-r--r--drivers/scsi/sd.c6
-rw-r--r--lib/Kconfig.debug16
4 files changed, 63 insertions, 3 deletions
diff --git a/block/genhd.c b/block/genhd.c
index ee4b13520e59..67e5a59ced2a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -299,6 +299,38 @@ EXPORT_SYMBOL(unregister_blkdev);
299static struct kobj_map *bdev_map; 299static struct kobj_map *bdev_map;
300 300
301/** 301/**
302 * blk_mangle_minor - scatter minor numbers apart
303 * @minor: minor number to mangle
304 *
305 * Scatter consecutively allocated @minor number apart if MANGLE_DEVT
306 * is enabled. Mangling twice gives the original value.
307 *
308 * RETURNS:
309 * Mangled value.
310 *
311 * CONTEXT:
312 * Don't care.
313 */
314static int blk_mangle_minor(int minor)
315{
316#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT
317 int i;
318
319 for (i = 0; i < MINORBITS / 2; i++) {
320 int low = minor & (1 << i);
321 int high = minor & (1 << (MINORBITS - 1 - i));
322 int distance = MINORBITS - 1 - 2 * i;
323
324 minor ^= low | high; /* clear both bits */
325 low <<= distance; /* swap the positions */
326 high >>= distance;
327 minor |= low | high; /* and set */
328 }
329#endif
330 return minor;
331}
332
333/**
302 * blk_alloc_devt - allocate a dev_t for a partition 334 * blk_alloc_devt - allocate a dev_t for a partition
303 * @part: partition to allocate dev_t for 335 * @part: partition to allocate dev_t for
304 * @gfp_mask: memory allocation flag 336 * @gfp_mask: memory allocation flag
@@ -339,7 +371,7 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
339 return -EBUSY; 371 return -EBUSY;
340 } 372 }
341 373
342 *devt = MKDEV(BLOCK_EXT_MAJOR, idx); 374 *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
343 return 0; 375 return 0;
344} 376}
345 377
@@ -361,7 +393,7 @@ void blk_free_devt(dev_t devt)
361 393
362 if (MAJOR(devt) == BLOCK_EXT_MAJOR) { 394 if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
363 mutex_lock(&ext_devt_mutex); 395 mutex_lock(&ext_devt_mutex);
364 idr_remove(&ext_devt_idr, MINOR(devt)); 396 idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
365 mutex_unlock(&ext_devt_mutex); 397 mutex_unlock(&ext_devt_mutex);
366 } 398 }
367} 399}
@@ -473,7 +505,7 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
473 struct hd_struct *part; 505 struct hd_struct *part;
474 506
475 mutex_lock(&ext_devt_mutex); 507 mutex_lock(&ext_devt_mutex);
476 part = idr_find(&ext_devt_idr, MINOR(devt)); 508 part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
477 if (part && get_disk(part_to_disk(part))) { 509 if (part && get_disk(part_to_disk(part))) {
478 *partno = part->partno; 510 *partno = part->partno;
479 disk = part_to_disk(part); 511 disk = part_to_disk(part);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7a88de9ada29..a072df5053ae 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -42,7 +42,13 @@
42#include <asm/div64.h> 42#include <asm/div64.h>
43 43
44#define IDE_DISK_PARTS (1 << PARTN_BITS) 44#define IDE_DISK_PARTS (1 << PARTN_BITS)
45
46#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
45#define IDE_DISK_MINORS IDE_DISK_PARTS 47#define IDE_DISK_MINORS IDE_DISK_PARTS
48#else
49#define IDE_DISK_MINORS 1
50#endif
51
46#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) 52#define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS)
47 53
48struct ide_disk_obj { 54struct ide_disk_obj {
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d1bb0e1d2d28..280d231a86ed 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -87,7 +87,13 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
87MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); 87MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
88 88
89#define SD_PARTS 64 89#define SD_PARTS 64
90
91#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
90#define SD_MINORS 16 92#define SD_MINORS 16
93#else
94#define SD_MINORS 1
95#endif
96
91#define SD_EXT_MINORS (SD_PARTS - SD_MINORS) 97#define SD_EXT_MINORS (SD_PARTS - SD_MINORS)
92 98
93static int sd_revalidate_disk(struct gendisk *); 99static int sd_revalidate_disk(struct gendisk *);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 0b504814e378..5a536f703a83 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -624,6 +624,22 @@ config BACKTRACE_SELF_TEST
624 624
625 Say N if you are unsure. 625 Say N if you are unsure.
626 626
627config DEBUG_BLOCK_EXT_DEVT
628 bool "Force extended block device numbers and spread them"
629 depends on DEBUG_KERNEL
630 depends on BLOCK
631 default y
632 help
633 Conventionally, block device numbers are allocated from
634 predetermined contiguous area. However, extended block area
635 may introduce non-contiguous block device numbers. This
636 option forces most block device numbers to be allocated from
637 the extended space and spreads them to discover kernel or
638 userland code paths which assume predetermined contiguous
639 device number allocation.
640
641 Say N if you are unsure.
642
627config LKDTM 643config LKDTM
628 tristate "Linux Kernel Dump Test Tool Module" 644 tristate "Linux Kernel Dump Test Tool Module"
629 depends on DEBUG_KERNEL 645 depends on DEBUG_KERNEL