diff options
Diffstat (limited to 'block/genhd.c')
-rw-r--r-- | block/genhd.c | 38 |
1 files changed, 35 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); | |||
299 | static struct kobj_map *bdev_map; | 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 | * 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); |