]> www.infradead.org Git - users/willy/xarray.git/commitdiff
nfsd: Convert cl_stateids to XArray
authorMatthew Wilcox <willy@infradead.org>
Wed, 9 Jan 2019 18:47:19 +0000 (13:47 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 8 Aug 2019 14:29:40 +0000 (10:29 -0400)
Signed-off-by: Matthew Wilcox <willy@infradead.org>
fs/nfsd/nfs4state.c
fs/nfsd/state.h

index 7857942c5ca6572b8e7b6c2107bca795e2f6c85c..25385e407484ef8ac2f0cbc3136964b4c4e6caf1 100644 (file)
@@ -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)
index 5dbd16946e8efa5e6e1a5c00ce201a292de02baf..8b89ad193aeb25950f424903523ee659e626a3e3 100644 (file)
@@ -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 */