aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4state.c73
2 files changed, 74 insertions, 1 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 2f0f8c216441..210e44ed1d2a 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -30,6 +30,7 @@ enum nfs4_client_state {
30 NFS4CLNT_PURGE_STATE, 30 NFS4CLNT_PURGE_STATE,
31 NFS4CLNT_BIND_CONN_TO_SESSION, 31 NFS4CLNT_BIND_CONN_TO_SESSION,
32 NFS4CLNT_MOVED, 32 NFS4CLNT_MOVED,
33 NFS4CLNT_LEASE_MOVED,
33}; 34};
34 35
35#define NFS4_RENEW_TIMEOUT 0x01 36#define NFS4_RENEW_TIMEOUT 0x01
@@ -425,6 +426,7 @@ extern void nfs4_schedule_state_manager(struct nfs_client *);
425extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); 426extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
426extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); 427extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
427extern int nfs4_schedule_migration_recovery(const struct nfs_server *); 428extern int nfs4_schedule_migration_recovery(const struct nfs_server *);
429extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *);
428extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 430extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
429extern void nfs41_handle_server_scope(struct nfs_client *, 431extern void nfs41_handle_server_scope(struct nfs_client *,
430 struct nfs41_server_scope **); 432 struct nfs41_server_scope **);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index ba0db18b5f67..552706d2d776 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1233,6 +1233,22 @@ int nfs4_schedule_migration_recovery(const struct nfs_server *server)
1233} 1233}
1234EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery); 1234EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery);
1235 1235
1236/**
1237 * nfs4_schedule_lease_moved_recovery - start lease-moved recovery
1238 *
1239 * @clp: server to check for moved leases
1240 *
1241 */
1242void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp)
1243{
1244 dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s\n",
1245 __func__, clp->cl_clientid, clp->cl_hostname);
1246
1247 set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state);
1248 nfs4_schedule_state_manager(clp);
1249}
1250EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery);
1251
1236int nfs4_wait_clnt_recover(struct nfs_client *clp) 1252int nfs4_wait_clnt_recover(struct nfs_client *clp)
1237{ 1253{
1238 int res; 1254 int res;
@@ -1661,7 +1677,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1661 nfs4_state_end_reclaim_reboot(clp); 1677 nfs4_state_end_reclaim_reboot(clp);
1662 break; 1678 break;
1663 case -NFS4ERR_STALE_CLIENTID: 1679 case -NFS4ERR_STALE_CLIENTID:
1664 case -NFS4ERR_LEASE_MOVED:
1665 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1680 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1666 nfs4_state_clear_reclaim_reboot(clp); 1681 nfs4_state_clear_reclaim_reboot(clp);
1667 nfs4_state_start_reclaim_reboot(clp); 1682 nfs4_state_start_reclaim_reboot(clp);
@@ -1975,6 +1990,55 @@ restart:
1975 return 0; 1990 return 0;
1976} 1991}
1977 1992
1993/*
1994 * Test each nfs_server on the clp's cl_superblocks list to see
1995 * if it's moved to another server. Stop when the server no longer
1996 * returns NFS4ERR_LEASE_MOVED.
1997 */
1998static int nfs4_handle_lease_moved(struct nfs_client *clp)
1999{
2000 const struct nfs4_state_maintenance_ops *ops =
2001 clp->cl_mvops->state_renewal_ops;
2002 struct nfs_server *server;
2003 struct rpc_cred *cred;
2004
2005 dprintk("%s: lease moved reported on \"%s\"\n", __func__,
2006 clp->cl_hostname);
2007
2008 spin_lock(&clp->cl_lock);
2009 cred = ops->get_state_renewal_cred_locked(clp);
2010 spin_unlock(&clp->cl_lock);
2011 if (cred == NULL)
2012 return -NFS4ERR_NOENT;
2013
2014 clp->cl_mig_gen++;
2015restart:
2016 rcu_read_lock();
2017 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
2018 struct inode *inode;
2019 int status;
2020
2021 if (server->mig_gen == clp->cl_mig_gen)
2022 continue;
2023 server->mig_gen = clp->cl_mig_gen;
2024
2025 rcu_read_unlock();
2026
2027 inode = server->super->s_root->d_inode;
2028 status = nfs4_proc_fsid_present(inode, cred);
2029 if (status != -NFS4ERR_MOVED)
2030 goto restart; /* wasn't this one */
2031 if (nfs4_try_migration(server, cred) == -NFS4ERR_LEASE_MOVED)
2032 goto restart; /* there are more */
2033 goto out;
2034 }
2035 rcu_read_unlock();
2036
2037out:
2038 put_rpccred(cred);
2039 return 0;
2040}
2041
1978/** 2042/**
1979 * nfs4_discover_server_trunking - Detect server IP address trunking 2043 * nfs4_discover_server_trunking - Detect server IP address trunking
1980 * 2044 *
@@ -2312,6 +2376,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
2312 goto out_error; 2376 goto out_error;
2313 } 2377 }
2314 2378
2379 if (test_and_clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) {
2380 section = "lease moved";
2381 status = nfs4_handle_lease_moved(clp);
2382 if (status < 0)
2383 goto out_error;
2384 }
2385
2315 /* First recover reboot state... */ 2386 /* First recover reboot state... */
2316 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { 2387 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
2317 section = "reclaim reboot"; 2388 section = "reclaim reboot";