diff options
-rw-r--r-- | fs/nfs/nfs4_fs.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 73 |
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 *); | |||
425 | extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); | 426 | extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); |
426 | extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); | 427 | extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); |
427 | extern int nfs4_schedule_migration_recovery(const struct nfs_server *); | 428 | extern int nfs4_schedule_migration_recovery(const struct nfs_server *); |
429 | extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *); | ||
428 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); | 430 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); |
429 | extern void nfs41_handle_server_scope(struct nfs_client *, | 431 | extern 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 | } |
1234 | EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery); | 1234 | EXPORT_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 | */ | ||
1242 | void 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 | } | ||
1250 | EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery); | ||
1251 | |||
1236 | int nfs4_wait_clnt_recover(struct nfs_client *clp) | 1252 | int 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 | */ | ||
1998 | static 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++; | ||
2015 | restart: | ||
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 | |||
2037 | out: | ||
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"; |