lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ