diff mbox series

[06/14] genhd: Convert to XArray

Message ID 20190318194821.3470-7-willy@infradead.org (mailing list archive)
State New, archived
Headers show
Series Convert block layer & drivers to XArray | expand

Commit Message

Matthew Wilcox (Oracle) March 18, 2019, 7:48 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/block/genhd.c b/block/genhd.c
index 703267865f14..7bb4d15f7574 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -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",
 };