summaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
authorTrond Myklebust2016-09-22 19:39:00 +0200
committerAnna Schumaker2016-09-27 20:33:49 +0200
commitbb3d1a3b24b61d8dd87e2d8c127a92ec8dd5d0d4 (patch)
treed5a9ce0df0b36228988d2c93f1106e71e93ee903 /fs/nfs/delegation.c
parentNFSv4.1: Test delegation stateids when server declares "some state revoked" (diff)
downloadkernel-qcow2-linux-bb3d1a3b24b61d8dd87e2d8c127a92ec8dd5d0d4.tar.gz
kernel-qcow2-linux-bb3d1a3b24b61d8dd87e2d8c127a92ec8dd5d0d4.tar.xz
kernel-qcow2-linux-bb3d1a3b24b61d8dd87e2d8c127a92ec8dd5d0d4.zip
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 <trond.myklebust@primarydata.com> Tested-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index dfb300901f7e..0ffead281555 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;