nfsd: don't use locks_in_grace to determine whether to call nfs4_grace_end
authorJeff Layton <jlayton@redhat.com>
Tue, 10 Apr 2012 15:08:48 +0000 (11:08 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 11 Apr 2012 21:55:00 +0000 (17:55 -0400)
It's possible that lockd or another lock manager might still be on the
list after we call nfsd4_end_grace. If the laundromat thread runs
again at that point, then we could end up calling nfsd4_end_grace more
than once.

That's not only inefficient, but calling nfsd4_recdir_purge_old more
than once could be problematic. Fix this by adding a new global
"grace_ended" flag and use that to determine whether we've already
called nfsd4_grace_end.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4state.c

index a822e31..277c989 100644 (file)
@@ -3155,10 +3155,17 @@ out:
 static struct lock_manager nfsd4_manager = {
 };
 
+static bool grace_ended;
+
 static void
 nfsd4_end_grace(void)
 {
+       /* do nothing if grace period already ended */
+       if (grace_ended)
+               return;
+
        dprintk("NFSD: end of grace period\n");
+       grace_ended = true;
        nfsd4_record_grace_done(&init_net, boot_time);
        locks_end_grace(&nfsd4_manager);
        /*
@@ -3183,8 +3190,7 @@ nfs4_laundromat(void)
        nfs4_lock_state();
 
        dprintk("NFSD: laundromat service - starting\n");
-       if (locks_in_grace())
-               nfsd4_end_grace();
+       nfsd4_end_grace();
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&client_lock);
        list_for_each_safe(pos, next, &client_lru) {
@@ -4718,6 +4724,7 @@ nfs4_state_start(void)
        nfsd4_client_tracking_init(&init_net);
        boot_time = get_seconds();
        locks_start_grace(&nfsd4_manager);
+       grace_ended = false;
        printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
               nfsd4_grace);
        ret = set_callback_cred();