NLM: don't let lockd exit on unexpected svc_recv errors (try #2)
authorJeff Layton <jlayton@redhat.com>
Tue, 8 Apr 2008 19:40:08 +0000 (15:40 -0400)
committerJ. Bruce Fields <bfields@citi.umich.edu>
Wed, 23 Apr 2008 20:13:43 +0000 (16:13 -0400)
When svc_recv returns an unexpected error, lockd will print a warning
and exit. This problematic for several reasons. In particular, it will
cause the reference counts for the thread to be wrong, and can lead to a
potential BUG() call.

Rather than exiting on error from svc_recv, have the thread do a 1s
sleep and then retry the loop. This is unlikely to cause any harm, and
if the error turns out to be something temporary then it may be able to
recover.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
fs/lockd/svc.c

index 66b5c98c7ff5bfbb72e6ee6d183a0e5bf15146be..cf977bbcf303b558cb8817638f83d709b093fe9e 100644 (file)
@@ -112,7 +112,7 @@ static inline void clear_grace_period(void)
 static int
 lockd(void *vrqstp)
 {
-       int             err = 0;
+       int             err = 0, preverr = 0;
        struct svc_rqst *rqstp = vrqstp;
        unsigned long grace_period_expire;
 
@@ -172,14 +172,20 @@ lockd(void *vrqstp)
                 * recvfrom routine.
                 */
                err = svc_recv(rqstp, timeout);
-               if (err == -EAGAIN || err == -EINTR)
+               if (err == -EAGAIN || err == -EINTR) {
+                       preverr = err;
                        continue;
+               }
                if (err < 0) {
-                       printk(KERN_WARNING
-                              "lockd: terminating on error %d\n",
-                              -err);
-                       break;
+                       if (err != preverr) {
+                               printk(KERN_WARNING "%s: unexpected error "
+                                       "from svc_recv (%d)\n", __func__, err);
+                               preverr = err;
+                       }
+                       schedule_timeout_interruptible(HZ);
+                       continue;
                }
+               preverr = err;
 
                dprintk("lockd: request from %s\n",
                                svc_print_addr(rqstp, buf, sizeof(buf)));