NFS: Add migration recovery callouts in nfs4proc.c
authorChuck Lever <chuck.lever@oracle.com>
Thu, 17 Oct 2013 18:13:19 +0000 (14:13 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 28 Oct 2013 19:25:23 +0000 (15:25 -0400)
When a server returns NFS4ERR_MOVED, trigger the new migration
recovery logic in the state manager.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c

index fa87f81527b3e48374bb14ca2a82f3765060b51a..a1f620950f11016c725e7ca288f141ff25fd0898 100644 (file)
@@ -384,6 +384,11 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case -NFS4ERR_STALE_CLIENTID:
                        nfs4_schedule_lease_recovery(clp);
                        goto wait_on_recovery;
+               case -NFS4ERR_MOVED:
+                       ret = nfs4_schedule_migration_recovery(server);
+                       if (ret < 0)
+                               break;
+                       goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
@@ -431,6 +436,8 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
        return nfs4_map_errors(ret);
 wait_on_recovery:
        ret = nfs4_wait_clnt_recover(clp);
+       if (test_bit(NFS_MIG_FAILED, &server->mig_status))
+               return -EIO;
        if (ret == 0)
                exception->retry = 1;
        return ret;
@@ -2974,11 +2981,16 @@ static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
        status = nfs4_proc_fs_locations(client, dir, name, locations, page);
        if (status != 0)
                goto out;
-       /* Make sure server returned a different fsid for the referral */
+
+       /*
+        * If the fsid didn't change, this is a migration event, not a
+        * referral.  Cause us to drop into the exception handler, which
+        * will kick off migration recovery.
+        */
        if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
                dprintk("%s: server did not return a different fsid for"
                        " a referral at %s\n", __func__, name->name);
-               status = -EIO;
+               status = -NFS4ERR_MOVED;
                goto out;
        }
        /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
@@ -4739,6 +4751,10 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                case -NFS4ERR_STALE_CLIENTID:
                        nfs4_schedule_lease_recovery(clp);
                        goto wait_on_recovery;
+               case -NFS4ERR_MOVED:
+                       if (nfs4_schedule_migration_recovery(server) < 0)
+                               goto recovery_failed;
+                       goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
@@ -4769,6 +4785,8 @@ wait_on_recovery:
        rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
        if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
                rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+       if (test_bit(NFS_MIG_FAILED, &server->mig_status))
+               goto recovery_failed;
 restart_call:
        task->tk_status = 0;
        return -EAGAIN;