NFSv4.1: Deal with server reboots during delegation expiration recovery
authorTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 22 Sep 2016 17:39:00 +0000 (13:39 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Tue, 27 Sep 2016 18:33:49 +0000 (14:33 -0400)
Ensure that if the server reboots while we're testing and recovering
from revoked delegations, we exit to allow the state manager to
handle matters.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/delegation.c

index dfb3009..0ffead2 100644 (file)
@@ -884,6 +884,13 @@ restart:
        rcu_read_unlock();
 }
 
+static inline bool nfs4_server_rebooted(const struct nfs_client *clp)
+{
+       return (clp->cl_state & (BIT(NFS4CLNT_CHECK_LEASE) |
+                               BIT(NFS4CLNT_LEASE_EXPIRED) |
+                               BIT(NFS4CLNT_SESSION_RESET))) != 0;
+}
+
 static void nfs_mark_test_expired_delegation(struct nfs_server *server,
            struct nfs_delegation *delegation)
 {
@@ -892,6 +899,19 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server,
        set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state);
 }
 
+static void nfs_inode_mark_test_expired_delegation(struct nfs_server *server,
+               struct inode *inode)
+{
+       struct nfs_delegation *delegation;
+
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation)
+               nfs_mark_test_expired_delegation(server, delegation);
+       rcu_read_unlock();
+
+}
+
 static void nfs_delegation_mark_test_expired_server(struct nfs_server *server)
 {
        struct nfs_delegation *delegation;
@@ -964,6 +984,12 @@ restart:
                                nfs_inode_find_state_and_recover(inode, &stateid);
                        }
                        put_rpccred(cred);
+                       if (nfs4_server_rebooted(clp)) {
+                               nfs_inode_mark_test_expired_delegation(server,inode);
+                               iput(inode);
+                               nfs_sb_deactive(server->super);
+                               return;
+                       }
                        iput(inode);
                        nfs_sb_deactive(server->super);
                        goto restart;