@@ -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);
}