svcrpc: free contexts immediately on PROC_DESTROY
authorNeil Brown <neilb@suse.com>
Thu, 22 Dec 2016 17:38:06 +0000 (12:38 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 31 Jan 2017 17:31:53 +0000 (12:31 -0500)
We currently handle a client PROC_DESTROY request by turning it
CACHE_NEGATIVE, setting the expired time to now, and then waiting for
cache_clean to clean it up later.  Since we forgot to set the cache's
nextcheck value, that could take up to 30 minutes.  Also, though there's
probably no real bug in this case, setting CACHE_NEGATIVE directly like
this probably isn't a great idea in general.

So let's just remove the entry from the cache directly, and move this
bit of cache manipulation to a helper function.

Signed-off-by: Neil Brown <neilb@suse.com>
Reported-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
include/linux/sunrpc/cache.h
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c

index 62a60eeacb0aeaf9907a5247d42706851fec3ffb..9dcf2c8fe1c5df46b915ba585b156eee5608a29e 100644 (file)
@@ -227,6 +227,7 @@ extern void sunrpc_destroy_cache_detail(struct cache_detail *cd);
 extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
                                        umode_t, struct cache_detail *);
 extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
+extern void sunrpc_cache_unhash(struct cache_detail *, struct cache_head *);
 
 /* Must store cache_detail in seq_file->private if using next three functions */
 extern void *cache_seq_start(struct seq_file *file, loff_t *pos);
index 1530825985221a1aeb5f77ee81f4251acdef9d96..a54a7a3d28f5300e7940769b1b3bc0b5daa7cfbb 100644 (file)
@@ -1489,8 +1489,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
        case RPC_GSS_PROC_DESTROY:
                if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
                        goto auth_err;
-               rsci->h.expiry_time = seconds_since_boot();
-               set_bit(CACHE_NEGATIVE, &rsci->h.flags);
+               /* Delete the entry from the cache_list and call cache_put */
+               sunrpc_cache_unhash(sn->rsc_cache, &rsci->h);
                if (resv->iov_len + 4 > PAGE_SIZE)
                        goto drop;
                svc_putnl(resv, RPC_SUCCESS);
index 8147e8d56eb214667a9d27a946bacde32637653d..502b9fe9817bfc868f5fcd4d1a69ff4f29fa7169 100644 (file)
@@ -1855,3 +1855,15 @@ void sunrpc_cache_unregister_pipefs(struct cache_detail *cd)
 }
 EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs);
 
+void sunrpc_cache_unhash(struct cache_detail *cd, struct cache_head *h)
+{
+       write_lock(&cd->hash_lock);
+       if (!hlist_unhashed(&h->cache_list)){
+               hlist_del_init(&h->cache_list);
+               cd->entries--;
+               write_unlock(&cd->hash_lock);
+               cache_put(h, cd);
+       } else
+               write_unlock(&cd->hash_lock);
+}
+EXPORT_SYMBOL_GPL(sunrpc_cache_unhash);