|
@@ -1233,6 +1233,22 @@ int nfs4_schedule_migration_recovery(const struct nfs_server *server)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery);
|
|
|
|
|
|
+/**
|
|
|
+ * nfs4_schedule_lease_moved_recovery - start lease-moved recovery
|
|
|
+ *
|
|
|
+ * @clp: server to check for moved leases
|
|
|
+ *
|
|
|
+ */
|
|
|
+void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp)
|
|
|
+{
|
|
|
+ dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s\n",
|
|
|
+ __func__, clp->cl_clientid, clp->cl_hostname);
|
|
|
+
|
|
|
+ set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state);
|
|
|
+ nfs4_schedule_state_manager(clp);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery);
|
|
|
+
|
|
|
int nfs4_wait_clnt_recover(struct nfs_client *clp)
|
|
|
{
|
|
|
int res;
|
|
@@ -1661,7 +1677,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
|
|
|
nfs4_state_end_reclaim_reboot(clp);
|
|
|
break;
|
|
|
case -NFS4ERR_STALE_CLIENTID:
|
|
|
- case -NFS4ERR_LEASE_MOVED:
|
|
|
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
|
|
nfs4_state_clear_reclaim_reboot(clp);
|
|
|
nfs4_state_start_reclaim_reboot(clp);
|
|
@@ -1975,6 +1990,55 @@ restart:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Test each nfs_server on the clp's cl_superblocks list to see
|
|
|
+ * if it's moved to another server. Stop when the server no longer
|
|
|
+ * returns NFS4ERR_LEASE_MOVED.
|
|
|
+ */
|
|
|
+static int nfs4_handle_lease_moved(struct nfs_client *clp)
|
|
|
+{
|
|
|
+ const struct nfs4_state_maintenance_ops *ops =
|
|
|
+ clp->cl_mvops->state_renewal_ops;
|
|
|
+ struct nfs_server *server;
|
|
|
+ struct rpc_cred *cred;
|
|
|
+
|
|
|
+ dprintk("%s: lease moved reported on \"%s\"\n", __func__,
|
|
|
+ clp->cl_hostname);
|
|
|
+
|
|
|
+ spin_lock(&clp->cl_lock);
|
|
|
+ cred = ops->get_state_renewal_cred_locked(clp);
|
|
|
+ spin_unlock(&clp->cl_lock);
|
|
|
+ if (cred == NULL)
|
|
|
+ return -NFS4ERR_NOENT;
|
|
|
+
|
|
|
+ clp->cl_mig_gen++;
|
|
|
+restart:
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
|
|
|
+ struct inode *inode;
|
|
|
+ int status;
|
|
|
+
|
|
|
+ if (server->mig_gen == clp->cl_mig_gen)
|
|
|
+ continue;
|
|
|
+ server->mig_gen = clp->cl_mig_gen;
|
|
|
+
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ inode = server->super->s_root->d_inode;
|
|
|
+ status = nfs4_proc_fsid_present(inode, cred);
|
|
|
+ if (status != -NFS4ERR_MOVED)
|
|
|
+ goto restart; /* wasn't this one */
|
|
|
+ if (nfs4_try_migration(server, cred) == -NFS4ERR_LEASE_MOVED)
|
|
|
+ goto restart; /* there are more */
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+out:
|
|
|
+ put_rpccred(cred);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* nfs4_discover_server_trunking - Detect server IP address trunking
|
|
|
*
|
|
@@ -2312,6 +2376,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
|
|
goto out_error;
|
|
|
}
|
|
|
|
|
|
+ if (test_and_clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) {
|
|
|
+ section = "lease moved";
|
|
|
+ status = nfs4_handle_lease_moved(clp);
|
|
|
+ if (status < 0)
|
|
|
+ goto out_error;
|
|
|
+ }
|
|
|
+
|
|
|
/* First recover reboot state... */
|
|
|
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
|
|
|
section = "reclaim reboot";
|