From 28e0d48ef9feb5cc55f6ca56673fae0ee31e5e7b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Wed, 9 Jan 2019 13:47:19 -0500 Subject: [PATCH] nfsd: Convert cl_stateids to XArray Signed-off-by: Matthew Wilcox --- fs/nfsd/nfs4state.c | 42 ++++++++++++++---------------------------- fs/nfsd/state.h | 3 ++- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7857942c5ca6..25385e407484 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -698,38 +698,25 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *sla void (*sc_free)(struct nfs4_stid *)) { struct nfs4_stid *stid; - int new_id; + int ret; stid = kmem_cache_zalloc(slab, GFP_KERNEL); if (!stid) return NULL; - idr_preload(GFP_KERNEL); - spin_lock(&cl->cl_lock); - /* Reserving 0 for start of file in nfsdfs "states" file: */ - new_id = idr_alloc_cyclic(&cl->cl_stateids, stid, 1, 0, GFP_NOWAIT); - spin_unlock(&cl->cl_lock); - idr_preload_end(); - if (new_id < 0) + ret = xa_alloc_cyclic(&cl->cl_stateids, + &stid->sc_stateid.si_opaque.so_id, stid, + xa_limit_32b, &cl->cl_stateid_next, GFP_KERNEL); + if (ret < 0) goto out_free; stid->sc_free = sc_free; stid->sc_client = cl; - stid->sc_stateid.si_opaque.so_id = new_id; stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid; /* Will be incremented before return to client: */ refcount_set(&stid->sc_count, 1); spin_lock_init(&stid->sc_lock); - /* - * It shouldn't be a problem to reuse an opaque stateid value. - * I don't think it is for 4.1. But with 4.0 I worry that, for - * example, a stray write retransmission could be accepted by - * the server when it should have been rejected. Therefore, - * adopt a trick from the sctp code to attempt to maximize the - * amount of time until an id is reused, by ensuring they always - * "increase" (mod INT_MAX): - */ return stid; out_free: kmem_cache_free(slab, stid); @@ -912,7 +899,7 @@ nfs4_put_stid(struct nfs4_stid *s) wake_up_all(&close_wq); return; } - idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); + xa_erase(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); spin_unlock(&clp->cl_lock); s->sc_free(s); if (fp) @@ -1317,7 +1304,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, return; } - idr_remove(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); + xa_erase(&clp->cl_stateids, s->sc_stateid.si_opaque.so_id); list_add(&stp->st_locks, reaplist); } @@ -1868,7 +1855,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) for (i = 0; i < OWNER_HASH_SIZE; i++) INIT_LIST_HEAD(&clp->cl_ownerstr_hashtbl[i]); INIT_LIST_HEAD(&clp->cl_sessions); - idr_init(&clp->cl_stateids); + xa_init_flags(&clp->cl_stateids, XA_FLAGS_ALLOC1); atomic_set(&clp->cl_rpc_users, 0); clp->cl_cb_state = NFSD4_CB_UNKNOWN; INIT_LIST_HEAD(&clp->cl_idhash); @@ -1901,7 +1888,7 @@ static void __free_client(struct kref *k) kfree(clp->cl_name.data); kfree(clp->cl_nii_domain.data); kfree(clp->cl_nii_name.data); - idr_destroy(&clp->cl_stateids); + xa_destroy(&clp->cl_stateids); kmem_cache_free(client_slab, clp); } @@ -2209,7 +2196,7 @@ find_stateid_locked(struct nfs4_client *cl, stateid_t *t) { struct nfs4_stid *ret; - ret = idr_find(&cl->cl_stateids, t->si_opaque.so_id); + ret = xa_load(&cl->cl_stateids, t->si_opaque.so_id); if (!ret || !ret->sc_type) return NULL; return ret; @@ -2296,8 +2283,8 @@ static void *states_start(struct seq_file *s, loff_t *pos) unsigned long id = *pos; void *ret; - spin_lock(&clp->cl_lock); - ret = idr_get_next_ul(&clp->cl_stateids, &id); + xa_lock(&clp->cl_stateids); + ret = xa_find(&clp->cl_stateids, &id, ULONG_MAX, XA_PRESENT); *pos = id; return ret; } @@ -2309,8 +2296,7 @@ static void *states_next(struct seq_file *s, void *v, loff_t *pos) void *ret; id = *pos; - id++; - ret = idr_get_next_ul(&clp->cl_stateids, &id); + ret = xa_find_after(&clp->cl_stateids, &id, ULONG_MAX, XA_PRESENT); *pos = id; return ret; } @@ -2320,7 +2306,7 @@ static void states_stop(struct seq_file *s, void *v) { struct nfs4_client *clp = s->private; - spin_unlock(&clp->cl_lock); + xa_unlock(&clp->cl_stateids); } static void nfs4_show_superblock(struct seq_file *s, struct file *f) diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 5dbd16946e8e..8b89ad193aeb 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -301,7 +301,8 @@ struct nfs4_client { struct rb_node cl_namenode; /* link into by-name trees */ struct list_head *cl_ownerstr_hashtbl; struct list_head cl_openowners; - struct idr cl_stateids; /* stateid lookup */ + struct xarray cl_stateids; /* stateid lookup */ + u32 cl_stateid_next; struct list_head cl_delegations; struct list_head cl_revoked; /* unacknowledged, revoked 4.1 state */ struct list_head cl_lru; /* tail queue */ -- 2.50.1