Commit 870d6656126add8e383645732b03df2b7ccd4f94
Committed by
Jens Axboe
1 parent
f615b48cc7
Exists in
master
and in
4 other branches
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>
Showing 4 changed files with 63 additions and 3 deletions Side-by-side Diff
block/genhd.c
... | ... | @@ -299,6 +299,38 @@ |
299 | 299 | static 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 | + */ | |
314 | +static 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 | 334 | * blk_alloc_devt - allocate a dev_t for a partition |
303 | 335 | * @part: partition to allocate dev_t for |
304 | 336 | * @gfp_mask: memory allocation flag |
... | ... | @@ -339,7 +371,7 @@ |
339 | 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 | 375 | return 0; |
344 | 376 | } |
345 | 377 | |
... | ... | @@ -361,7 +393,7 @@ |
361 | 393 | |
362 | 394 | if (MAJOR(devt) == BLOCK_EXT_MAJOR) { |
363 | 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 | 397 | mutex_unlock(&ext_devt_mutex); |
366 | 398 | } |
367 | 399 | } |
... | ... | @@ -473,7 +505,7 @@ |
473 | 505 | struct hd_struct *part; |
474 | 506 | |
475 | 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 | 509 | if (part && get_disk(part_to_disk(part))) { |
478 | 510 | *partno = part->partno; |
479 | 511 | disk = part_to_disk(part); |
drivers/ide/ide-disk.c
... | ... | @@ -42,7 +42,13 @@ |
42 | 42 | #include <asm/div64.h> |
43 | 43 | |
44 | 44 | #define IDE_DISK_PARTS (1 << PARTN_BITS) |
45 | + | |
46 | +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) | |
45 | 47 | #define IDE_DISK_MINORS IDE_DISK_PARTS |
48 | +#else | |
49 | +#define IDE_DISK_MINORS 1 | |
50 | +#endif | |
51 | + | |
46 | 52 | #define IDE_DISK_EXT_MINORS (IDE_DISK_PARTS - IDE_DISK_MINORS) |
47 | 53 | |
48 | 54 | struct ide_disk_obj { |
drivers/scsi/sd.c
... | ... | @@ -87,7 +87,13 @@ |
87 | 87 | MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); |
88 | 88 | |
89 | 89 | #define SD_PARTS 64 |
90 | + | |
91 | +#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT) | |
90 | 92 | #define SD_MINORS 16 |
93 | +#else | |
94 | +#define SD_MINORS 1 | |
95 | +#endif | |
96 | + | |
91 | 97 | #define SD_EXT_MINORS (SD_PARTS - SD_MINORS) |
92 | 98 | |
93 | 99 | static int sd_revalidate_disk(struct gendisk *); |
lib/Kconfig.debug
... | ... | @@ -624,6 +624,22 @@ |
624 | 624 | |
625 | 625 | Say N if you are unsure. |
626 | 626 | |
627 | +config 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 | + | |
627 | 643 | config LKDTM |
628 | 644 | tristate "Linux Kernel Dump Test Tool Module" |
629 | 645 | depends on DEBUG_KERNEL |