[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190820223259.22348-15-willy@infradead.org>
Date: Tue, 20 Aug 2019 15:32:35 -0700
From: Matthew Wilcox <willy@...radead.org>
To: netdev@...r.kernel.org
Cc: "Matthew Wilcox (Oracle)" <willy@...radead.org>
Subject: [PATCH 14/38] tap: Convert minor_idr to XArray
From: "Matthew Wilcox (Oracle)" <willy@...radead.org>
The minor_lock can be removed as the XArray contains its own spinlock.
I suspect the GFP_ATOMIC allocation could be GFP_KERNEL, but I couldn't
prove it.
Signed-off-by: Matthew Wilcox (Oracle) <willy@...radead.org>
---
drivers/net/tap.c | 32 +++++++++++++-------------------
1 file changed, 13 insertions(+), 19 deletions(-)
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index dd614c2cd994..81b06a21d96c 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -14,9 +14,9 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/cdev.h>
-#include <linux/idr.h>
#include <linux/fs.h>
#include <linux/uio.h>
+#include <linux/xarray.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
@@ -106,8 +106,7 @@ static LIST_HEAD(major_list);
struct major_info {
struct rcu_head rcu;
dev_t major;
- struct idr minor_idr;
- spinlock_t minor_lock;
+ struct xarray tap_devs;
const char *device_name;
struct list_head next;
};
@@ -414,19 +413,16 @@ int tap_get_minor(dev_t major, struct tap_dev *tap)
goto unlock;
}
- spin_lock(&tap_major->minor_lock);
- retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC);
- if (retval >= 0) {
- tap->minor = retval;
- } else if (retval == -ENOSPC) {
+ retval = xa_alloc(&tap_major->tap_devs, &tap->minor, tap,
+ XA_LIMIT(0, TAP_NUM_DEVS), GFP_ATOMIC);
+ if (retval == -EBUSY) {
netdev_err(tap->dev, "Too many tap devices\n");
retval = -EINVAL;
}
- spin_unlock(&tap_major->minor_lock);
unlock:
rcu_read_unlock();
- return retval < 0 ? retval : 0;
+ return retval;
}
EXPORT_SYMBOL_GPL(tap_get_minor);
@@ -440,12 +436,12 @@ void tap_free_minor(dev_t major, struct tap_dev *tap)
goto unlock;
}
- spin_lock(&tap_major->minor_lock);
+ xa_lock(&tap_major->tap_devs);
if (tap->minor) {
- idr_remove(&tap_major->minor_idr, tap->minor);
+ __xa_erase(&tap_major->tap_devs, tap->minor);
tap->minor = 0;
}
- spin_unlock(&tap_major->minor_lock);
+ xa_unlock(&tap_major->tap_devs);
unlock:
rcu_read_unlock();
@@ -465,13 +461,13 @@ static struct tap_dev *dev_get_by_tap_file(int major, int minor)
goto unlock;
}
- spin_lock(&tap_major->minor_lock);
- tap = idr_find(&tap_major->minor_idr, minor);
+ xa_lock(&tap_major->tap_devs);
+ tap = xa_load(&tap_major->tap_devs, minor);
if (tap) {
dev = tap->dev;
dev_hold(dev);
}
- spin_unlock(&tap_major->minor_lock);
+ xa_unlock(&tap_major->tap_devs);
unlock:
rcu_read_unlock();
@@ -1322,8 +1318,7 @@ static int tap_list_add(dev_t major, const char *device_name)
tap_major->major = MAJOR(major);
- idr_init(&tap_major->minor_idr);
- spin_lock_init(&tap_major->minor_lock);
+ xa_init_flags(&tap_major->tap_devs, XA_FLAGS_ALLOC1);
tap_major->device_name = device_name;
@@ -1369,7 +1364,6 @@ void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
unregister_chrdev_region(major, TAP_NUM_DEVS);
list_for_each_entry_safe(tap_major, tmp, &major_list, next) {
if (tap_major->major == MAJOR(major)) {
- idr_destroy(&tap_major->minor_idr);
list_del_rcu(&tap_major->next);
kfree_rcu(tap_major, rcu);
}
--
2.23.0.rc1
Powered by blists - more mailing lists