@@ -17,7 +17,7 @@
#include <linux/kmod.h>
#include <linux/kobj_map.h>
#include <linux/mutex.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
#include <linux/log2.h>
#include <linux/pm_runtime.h>
#include <linux/badblocks.h>
@@ -30,11 +30,8 @@ struct kobject *block_depr;
/* for extended dynamic devt allocation, currently only one major is used */
#define NR_EXT_DEVT (1 << MINORBITS)
-/* For extended devt allocation. ext_devt_lock prevents look up
- * results from going away underneath its user.
- */
-static DEFINE_SPINLOCK(ext_devt_lock);
-static DEFINE_IDR(ext_devt_idr);
+/* For extended devt allocation */
+static DEFINE_XARRAY_FLAGS(ext_devt, XA_FLAGS_LOCK_BH | XA_FLAGS_ALLOC);
static const struct device_type disk_type;
@@ -487,7 +484,8 @@ static int blk_mangle_minor(int minor)
int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
{
struct gendisk *disk = part_to_disk(part);
- int idx;
+ u32 idx;
+ int err;
/* in consecutive minor range? */
if (part->partno < disk->minors) {
@@ -495,16 +493,10 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
return 0;
}
- /* allocate ext devt */
- idr_preload(GFP_KERNEL);
-
- spin_lock_bh(&ext_devt_lock);
- idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT);
- spin_unlock_bh(&ext_devt_lock);
-
- idr_preload_end();
- if (idx < 0)
- return idx == -ENOSPC ? -EBUSY : idx;
+ err = xa_alloc(&ext_devt, &idx, part, XA_LIMIT(0, NR_EXT_DEVT - 1),
+ GFP_KERNEL);
+ if (err < 0)
+ return err;
*devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
return 0;
@@ -516,8 +508,7 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
*
* Free @devt which was allocated using blk_alloc_devt().
*
- * CONTEXT:
- * Might sleep.
+ * Context: Might sleep.
*/
void blk_free_devt(dev_t devt)
{
@@ -525,9 +516,7 @@ void blk_free_devt(dev_t devt)
return;
if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
- spin_lock_bh(&ext_devt_lock);
- idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
- spin_unlock_bh(&ext_devt_lock);
+ xa_erase_bh(&ext_devt, blk_mangle_minor(MINOR(devt)));
}
}
@@ -852,13 +841,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
} else {
struct hd_struct *part;
- spin_lock_bh(&ext_devt_lock);
- part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
+ rcu_read_lock();
+ part = xa_load(&ext_devt, blk_mangle_minor(MINOR(devt)));
if (part && get_disk_and_module(part_to_disk(part))) {
*partno = part->partno;
disk = part_to_disk(part);
}
- spin_unlock_bh(&ext_devt_lock);
+ rcu_read_unlock();
}
if (!disk)
@@ -1303,8 +1292,9 @@ static void disk_release(struct device *dev)
hd_free_part(&disk->part0);
if (disk->queue)
blk_put_queue(disk->queue);
- kfree(disk);
+ kfree_rcu(disk, part0.rcu_work.rcu);
}
+
struct class block_class = {
.name = "block",
};
Replace the IDR with the XArray. Includes converting the lookup from being protected by a spinlock to being protected by RCU. Signed-off-by: Matthew Wilcox <willy@infradead.org> --- block/genhd.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-)