From: "Matthew Wilcox (Oracle)" <wi...@infradead.org> Replace idr_lock with the internal XArray lock. The idr_in_use counter isn't needed as we can free all the elements in the array without it.
Signed-off-by: Matthew Wilcox (Oracle) <wi...@infradead.org> --- net/tipc/topsrv.c | 49 ++++++++++++++--------------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index 3a12fc18239b..72b3180e0ea5 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -54,9 +54,7 @@ /** * struct tipc_topsrv - TIPC server structure - * @conn_idr: identifier set of connection - * @idr_lock: protect the connection identifier set - * @idr_in_use: amount of allocated identifier entry + * @conns: identifier set of connection * @net: network namspace instance * @awork: accept work item * @rcv_wq: receive workqueue @@ -65,9 +63,7 @@ * @name: server name */ struct tipc_topsrv { - struct idr conn_idr; - spinlock_t idr_lock; /* for idr list */ - int idr_in_use; + struct xarray conns; struct net *net; struct work_struct awork; struct workqueue_struct *rcv_wq; @@ -127,10 +123,7 @@ static void tipc_conn_kref_release(struct kref *kref) struct tipc_topsrv *s = con->server; struct outqueue_entry *e, *safe; - spin_lock_bh(&s->idr_lock); - idr_remove(&s->conn_idr, con->conid); - s->idr_in_use--; - spin_unlock_bh(&s->idr_lock); + xa_erase_bh(&s->conns, con->conid); if (con->sock) sock_release(con->sock); @@ -194,16 +187,12 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) INIT_WORK(&con->swork, tipc_conn_send_work); INIT_WORK(&con->rwork, tipc_conn_recv_work); - spin_lock_bh(&s->idr_lock); - ret = idr_alloc(&s->conn_idr, con, 0, 0, GFP_ATOMIC); + ret = xa_alloc_bh(&s->conns, &con->conid, con, xa_limit_32b, + GFP_ATOMIC); if (ret < 0) { kfree(con); - spin_unlock_bh(&s->idr_lock); return ERR_PTR(-ENOMEM); } - con->conid = ret; - s->idr_in_use++; - spin_unlock_bh(&s->idr_lock); set_bit(CF_CONNECTED, &con->flags); con->server = s; @@ -215,11 +204,11 @@ static struct tipc_conn *tipc_conn_lookup(struct tipc_topsrv *s, int conid) { struct tipc_conn *con; - spin_lock_bh(&s->idr_lock); - con = idr_find(&s->conn_idr, conid); + xa_lock_bh(&s->conns); + con = xa_load(&s->conns, conid); if (!connected(con) || !kref_get_unless_zero(&con->kref)) con = NULL; - spin_unlock_bh(&s->idr_lock); + xa_unlock_bh(&s->conns); return con; } @@ -655,9 +644,7 @@ static int tipc_topsrv_start(struct net *net) tn->topsrv = srv; atomic_set(&tn->subscription_count, 0); - spin_lock_init(&srv->idr_lock); - idr_init(&srv->conn_idr); - srv->idr_in_use = 0; + xa_init_flags(&srv->conns, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_BH); ret = tipc_topsrv_work_start(srv); if (ret < 0) @@ -675,24 +662,16 @@ static void tipc_topsrv_stop(struct net *net) struct tipc_topsrv *srv = tipc_topsrv(net); struct socket *lsock = srv->listener; struct tipc_conn *con; - int id; - - spin_lock_bh(&srv->idr_lock); - for (id = 0; srv->idr_in_use; id++) { - con = idr_find(&srv->conn_idr, id); - if (con) { - spin_unlock_bh(&srv->idr_lock); - tipc_conn_close(con); - spin_lock_bh(&srv->idr_lock); - } - } + unsigned long id; + + xa_for_each(&srv->conns, id, con) + tipc_conn_close(con); + __module_get(lsock->ops->owner); __module_get(lsock->sk->sk_prot_creator->owner); srv->listener = NULL; - spin_unlock_bh(&srv->idr_lock); sock_release(lsock); tipc_topsrv_work_stop(srv); - idr_destroy(&srv->conn_idr); kfree(srv); } -- 2.23.0.rc1