diff mbox series

[36/38] netlink: Convert genl_fam_idr to XArray

Message ID 20190820223259.22348-37-willy@infradead.org
State Changes Requested
Delegated to: David Miller
Headers show
Series Convert networking to use the XArray | expand

Commit Message

Matthew Wilcox (Oracle) Aug. 20, 2019, 10:32 p.m. UTC
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>

Straightforward conversion without touching the locking.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 net/netlink/genetlink.c | 46 +++++++++++++++++------------------------
 1 file changed, 19 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index efccd1ac9a66..02f5c7453f84 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -18,7 +18,7 @@ 
 #include <linux/mutex.h>
 #include <linux/bitmap.h>
 #include <linux/rwsem.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
 #include <net/sock.h>
 #include <net/genetlink.h>
 
@@ -60,7 +60,8 @@  static void genl_unlock_all(void)
 	up_write(&cb_lock);
 }
 
-static DEFINE_IDR(genl_fam_idr);
+static unsigned int genl_families_next;
+static DEFINE_XARRAY_ALLOC(genl_families);
 
 /*
  * Bitmap of multicast groups that are currently in use.
@@ -92,15 +93,15 @@  static int genl_ctrl_event(int event, const struct genl_family *family,
 
 static const struct genl_family *genl_family_find_byid(unsigned int id)
 {
-	return idr_find(&genl_fam_idr, id);
+	return xa_load(&genl_families, id);
 }
 
 static const struct genl_family *genl_family_find_byname(char *name)
 {
 	const struct genl_family *family;
-	unsigned int id;
+	unsigned long id;
 
-	idr_for_each_entry(&genl_fam_idr, family, id)
+	xa_for_each(&genl_families, id, family)
 		if (strcmp(family->name, name) == 0)
 			return family;
 
@@ -362,12 +363,10 @@  int genl_register_family(struct genl_family *family)
 	} else
 		family->attrbuf = NULL;
 
-	family->id = idr_alloc_cyclic(&genl_fam_idr, family,
-				      start, end + 1, GFP_KERNEL);
-	if (family->id < 0) {
-		err = family->id;
+	err = xa_alloc_cyclic(&genl_families, &family->id, family,
+			XA_LIMIT(start, end), &genl_families_next, GFP_KERNEL);
+	if (err < 0)
 		goto errout_free;
-	}
 
 	err = genl_validate_assign_mc_groups(family);
 	if (err)
@@ -384,7 +383,7 @@  int genl_register_family(struct genl_family *family)
 	return 0;
 
 errout_remove:
-	idr_remove(&genl_fam_idr, family->id);
+	xa_erase(&genl_families, family->id);
 errout_free:
 	kfree(family->attrbuf);
 errout_locked:
@@ -412,7 +411,7 @@  int genl_unregister_family(const struct genl_family *family)
 
 	genl_unregister_mc_groups(family);
 
-	idr_remove(&genl_fam_idr, family->id);
+	xa_erase(&genl_families, family->id);
 
 	up_write(&cb_lock);
 	wait_event(genl_sk_destructing_waitq,
@@ -802,28 +801,21 @@  static int ctrl_fill_mcgrp_info(const struct genl_family *family,
 
 static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	int n = 0;
 	struct genl_family *rt;
 	struct net *net = sock_net(skb->sk);
-	int fams_to_skip = cb->args[0];
-	unsigned int id;
+	unsigned long id;
 
-	idr_for_each_entry(&genl_fam_idr, rt, id) {
+	xa_for_each_start(&genl_families, id, rt, cb->args[0]) {
 		if (!rt->netnsok && !net_eq(net, &init_net))
 			continue;
 
-		if (n++ < fams_to_skip)
-			continue;
-
 		if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid,
 				   cb->nlh->nlmsg_seq, NLM_F_MULTI,
-				   skb, CTRL_CMD_NEWFAMILY) < 0) {
-			n--;
+				   skb, CTRL_CMD_NEWFAMILY) < 0)
 			break;
-		}
 	}
 
-	cb->args[0] = n;
+	cb->args[0] = id;
 	return skb->len;
 }
 
@@ -993,11 +985,11 @@  static int genl_bind(struct net *net, int group)
 {
 	struct genl_family *f;
 	int err = -ENOENT;
-	unsigned int id;
+	unsigned long id;
 
 	down_read(&cb_lock);
 
-	idr_for_each_entry(&genl_fam_idr, f, id) {
+	xa_for_each(&genl_families, id, f) {
 		if (group >= f->mcgrp_offset &&
 		    group < f->mcgrp_offset + f->n_mcgrps) {
 			int fam_grp = group - f->mcgrp_offset;
@@ -1019,11 +1011,11 @@  static int genl_bind(struct net *net, int group)
 static void genl_unbind(struct net *net, int group)
 {
 	struct genl_family *f;
-	unsigned int id;
+	unsigned long id;
 
 	down_read(&cb_lock);
 
-	idr_for_each_entry(&genl_fam_idr, f, id) {
+	xa_for_each(&genl_families, id, f) {
 		if (group >= f->mcgrp_offset &&
 		    group < f->mcgrp_offset + f->n_mcgrps) {
 			int fam_grp = group - f->mcgrp_offset;