SUNRPC: Lockless server RPCSEC_GSS context lookup
authorTrond Myklebust <trondmy@gmail.com>
Mon, 1 Oct 2018 14:41:48 +0000 (10:41 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Mon, 29 Oct 2018 20:58:04 +0000 (16:58 -0400)
Use RCU protection for looking up the RPCSEC_GSS context.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/auth_gss/svcauth_gss.c

index 87c71fb0f0ead16874c8f98f606c737751b4f08e..1ece4bc3eb8d86470f41255c05e57ece1ba90f0e 100644 (file)
@@ -76,6 +76,7 @@ struct rsi {
        struct xdr_netobj       in_handle, in_token;
        struct xdr_netobj       out_handle, out_token;
        int                     major_status, minor_status;
+       struct rcu_head         rcu_head;
 };
 
 static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old);
@@ -89,13 +90,21 @@ static void rsi_free(struct rsi *rsii)
        kfree(rsii->out_token.data);
 }
 
-static void rsi_put(struct kref *ref)
+static void rsi_free_rcu(struct rcu_head *head)
 {
-       struct rsi *rsii = container_of(ref, struct rsi, h.ref);
+       struct rsi *rsii = container_of(head, struct rsi, rcu_head);
+
        rsi_free(rsii);
        kfree(rsii);
 }
 
+static void rsi_put(struct kref *ref)
+{
+       struct rsi *rsii = container_of(ref, struct rsi, h.ref);
+
+       call_rcu(&rsii->rcu_head, rsi_free_rcu);
+}
+
 static inline int rsi_hash(struct rsi *item)
 {
        return hash_mem(item->in_handle.data, item->in_handle.len, RSI_HASHBITS)
@@ -282,7 +291,7 @@ static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item)
        struct cache_head *ch;
        int hash = rsi_hash(item);
 
-       ch = sunrpc_cache_lookup(cd, &item->h, hash);
+       ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash);
        if (ch)
                return container_of(ch, struct rsi, h);
        else
@@ -330,6 +339,7 @@ struct rsc {
        struct svc_cred         cred;
        struct gss_svc_seq_data seqdata;
        struct gss_ctx          *mechctx;
+       struct rcu_head         rcu_head;
 };
 
 static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old);
@@ -343,12 +353,22 @@ static void rsc_free(struct rsc *rsci)
        free_svc_cred(&rsci->cred);
 }
 
+static void rsc_free_rcu(struct rcu_head *head)
+{
+       struct rsc *rsci = container_of(head, struct rsc, rcu_head);
+
+       kfree(rsci->handle.data);
+       kfree(rsci);
+}
+
 static void rsc_put(struct kref *ref)
 {
        struct rsc *rsci = container_of(ref, struct rsc, h.ref);
 
-       rsc_free(rsci);
-       kfree(rsci);
+       if (rsci->mechctx)
+               gss_delete_sec_context(&rsci->mechctx);
+       free_svc_cred(&rsci->cred);
+       call_rcu(&rsci->rcu_head, rsc_free_rcu);
 }
 
 static inline int
@@ -542,7 +562,7 @@ static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item)
        struct cache_head *ch;
        int hash = rsc_hash(item);
 
-       ch = sunrpc_cache_lookup(cd, &item->h, hash);
+       ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash);
        if (ch)
                return container_of(ch, struct rsc, h);
        else