sunrpc: add a rcu_head to svc_rqst and use kfree_rcu to free it
authorJeff Layton <jlayton@primarydata.com>
Fri, 21 Nov 2014 19:19:28 +0000 (14:19 -0500)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 9 Dec 2014 16:22:22 +0000 (11:22 -0500)
...also make the manipulation of sp_all_threads list use RCU-friendly
functions.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Tested-by: Chris Worley <chris.worley@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
include/linux/sunrpc/svc.h
include/trace/events/sunrpc.h
net/sunrpc/svc.c

index 5f0ab39..7f80a99 100644 (file)
@@ -223,6 +223,7 @@ static inline void svc_putu32(struct kvec *iov, __be32 val)
 struct svc_rqst {
        struct list_head        rq_list;        /* idle list */
        struct list_head        rq_all;         /* all threads list */
+       struct rcu_head         rq_rcu_head;    /* for RCU deferred kfree */
        struct svc_xprt *       rq_xprt;        /* transport ptr */
 
        struct sockaddr_storage rq_addr;        /* peer address */
@@ -262,6 +263,7 @@ struct svc_rqst {
 #define        RQ_SPLICE_OK    (4)                     /* turned off in gss privacy
                                                 * to prevent encrypting page
                                                 * cache pages */
+#define        RQ_VICTIM       (5)                     /* about to be shut down */
        unsigned long           rq_flags;       /* flags field */
 
        void *                  rq_argp;        /* decoded arguments */
index 5848fc2..08a5fed 100644 (file)
@@ -418,7 +418,8 @@ TRACE_EVENT(xs_tcp_data_recv,
                { (1UL << RQ_LOCAL),            "RQ_LOCAL"},            \
                { (1UL << RQ_USEDEFERRAL),      "RQ_USEDEFERRAL"},      \
                { (1UL << RQ_DROPME),           "RQ_DROPME"},           \
-               { (1UL << RQ_SPLICE_OK),        "RQ_SPLICE_OK"})
+               { (1UL << RQ_SPLICE_OK),        "RQ_SPLICE_OK"},        \
+               { (1UL << RQ_VICTIM),           "RQ_VICTIM"})
 
 TRACE_EVENT(svc_recv,
        TP_PROTO(struct svc_rqst *rqst, int status),
index a06a891..b90d1bc 100644 (file)
@@ -616,7 +616,7 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
        serv->sv_nrthreads++;
        spin_lock_bh(&pool->sp_lock);
        pool->sp_nrthreads++;
-       list_add(&rqstp->rq_all, &pool->sp_all_threads);
+       list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads);
        spin_unlock_bh(&pool->sp_lock);
        rqstp->rq_server = serv;
        rqstp->rq_pool = pool;
@@ -684,7 +684,8 @@ found_pool:
                 * so we don't try to kill it again.
                 */
                rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all);
-               list_del_init(&rqstp->rq_all);
+               set_bit(RQ_VICTIM, &rqstp->rq_flags);
+               list_del_rcu(&rqstp->rq_all);
                task = rqstp->rq_task;
        }
        spin_unlock_bh(&pool->sp_lock);
@@ -782,10 +783,11 @@ svc_exit_thread(struct svc_rqst *rqstp)
 
        spin_lock_bh(&pool->sp_lock);
        pool->sp_nrthreads--;
-       list_del(&rqstp->rq_all);
+       if (!test_and_set_bit(RQ_VICTIM, &rqstp->rq_flags))
+               list_del_rcu(&rqstp->rq_all);
        spin_unlock_bh(&pool->sp_lock);
 
-       kfree(rqstp);
+       kfree_rcu(rqstp, rq_rcu_head);
 
        /* Release the server */
        if (serv)