]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix bug in sunrpc/server code.
authorNeil Brown <neilb@cse.unsw.edu.au>
Wed, 13 Aug 2003 16:38:25 +0000 (09:38 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Wed, 13 Aug 2003 16:38:25 +0000 (09:38 -0700)
When a socket has a request ready it notifies a server thread.
When the thread has 'received' the request it calls svc_sock_received
to confirm the fact.

In some cases, svc_sock_received would be called an extra time and
this could lead to linked-list corruption and bad problems.

net/sunrpc/svcsock.c

index f6eea03b1e47e07434030d6e74e3c3356678b941..42f9f6bc359ba9cd60ff751dff03897cb7c90fbc 100644 (file)
@@ -567,14 +567,17 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
                                (serv->sv_nrthreads+3) * serv->sv_bufsz,
                                (serv->sv_nrthreads+3) * serv->sv_bufsz);
 
-       if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk)))
+       if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) {
+               svc_sock_received(svsk);
                return svc_deferred_recv(rqstp);
+       }
 
        clear_bit(SK_DATA, &svsk->sk_flags);
        while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) {
-               svc_sock_received(svsk);
-               if (err == -EAGAIN)
+               if (err == -EAGAIN) {
+                       svc_sock_received(svsk);
                        return err;
+               }
                /* possibly an icmp error */
                dprintk("svc: recvfrom returned error %d\n", -err);
        }
@@ -869,8 +872,10 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
                test_bit(SK_CONN, &svsk->sk_flags),
                test_bit(SK_CLOSE, &svsk->sk_flags));
 
-       if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk)))
+       if ((rqstp->rq_deferred = svc_deferred_dequeue(svsk))) {
+               svc_sock_received(svsk);
                return svc_deferred_recv(rqstp);
+       }
 
        if (test_bit(SK_CLOSE, &svsk->sk_flags)) {
                svc_delete_socket(svsk);
@@ -1545,6 +1550,5 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk)
                set_bit(SK_DEFERRED, &svsk->sk_flags);
        }
        spin_unlock(&serv->sv_lock);
-       svc_sock_received(svsk);
        return dr;
 }