From 090f30fdc24fd1cf0e4db46a683f3964d548a4eb Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 22 Sep 2016 13:39:00 -0400 Subject: [PATCH] NFSv4.1: Deal with server reboots during delegation expiration recovery 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 Tested-by: Oleg Drokin Signed-off-by: Anna Schumaker --- fs/nfs/delegation.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index dfb300901f7e7..0ffead281555f 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -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; -- 2.39.5