NFS: EXCHANGE_ID should save the server major and minor ID
authorChuck Lever <chuck.lever@oracle.com>
Tue, 22 May 2012 02:46:16 +0000 (22:46 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 22 May 2012 20:45:48 +0000 (16:45 -0400)
Save the server major and minor ID results from EXCHANGE_ID, as they
are needed for detecting server trunking.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h

index 34b2e68c52499fa87adcab3ab87c7766d8ce73fc..3c144689f9e4c98234564e2cc17e9f09428434f1 100644 (file)
@@ -237,6 +237,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
                nfs_idmap_delete(clp);
 
        rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+       kfree(clp->cl_serverowner);
        kfree(clp->cl_serverscope);
        kfree(clp->cl_implid);
 }
index 9e9334a172cfc2ec2d5ba29e79119c30fdbcc5fd..0d46fe449f0b3439fb1aaa4f32a08e19014f3f26 100644 (file)
@@ -5109,11 +5109,18 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                                clp->cl_rpcclient->cl_nodename,
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
+       res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
+                                       GFP_KERNEL);
+       if (unlikely(res.server_owner == NULL)) {
+               status = -ENOMEM;
+               goto out;
+       }
+
        res.server_scope = kzalloc(sizeof(struct nfs41_server_scope),
                                        GFP_KERNEL);
        if (unlikely(res.server_scope == NULL)) {
                status = -ENOMEM;
-               goto out;
+               goto out_server_owner;
        }
 
        res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_KERNEL);
@@ -5126,6 +5133,12 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
        if (status == 0)
                status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
 
+       if (status == 0) {
+               kfree(clp->cl_serverowner);
+               clp->cl_serverowner = res.server_owner;
+               res.server_owner = NULL;
+       }
+
        if (status == 0) {
                /* use the most recent implementation id */
                kfree(clp->cl_implid);
@@ -5150,6 +5163,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                }
        }
 
+out_server_owner:
+       kfree(res.server_owner);
 out_server_scope:
        kfree(res.server_scope);
 out:
index 12b99825a1c1ed9f5175f8c8addd091e7ad6855e..5ad2b2c2aecb1a0808f7de04e70b93edde3b7a4d 100644 (file)
@@ -5144,24 +5144,27 @@ static int decode_exchange_id(struct xdr_stream *xdr,
        if (dummy != SP4_NONE)
                return -EIO;
 
-       /* Throw away minor_id */
+       /* server_owner4.so_minor_id */
        p = xdr_inline_decode(xdr, 8);
        if (unlikely(!p))
                goto out_overflow;
+       p = xdr_decode_hyper(p, &res->server_owner->minor_id);
 
-       /* Throw away Major id */
+       /* server_owner4.so_major_id */
        status = decode_opaque_inline(xdr, &dummy, &dummy_str);
        if (unlikely(status))
                return status;
+       if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
+               return -EIO;
+       memcpy(res->server_owner->major_id, dummy_str, dummy);
+       res->server_owner->major_id_sz = dummy;
 
-       /* Save server_scope */
+       /* server_scope4 */
        status = decode_opaque_inline(xdr, &dummy, &dummy_str);
        if (unlikely(status))
                return status;
-
        if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
                return -EIO;
-
        memcpy(res->server_scope->server_scope, dummy_str, dummy);
        res->server_scope->server_scope_sz = dummy;
 
index 3a99f52523408899f0d7df0c34a64b6420c57736..fbb78fb09bd25c925d65207643bf61da614167d8 100644 (file)
@@ -80,6 +80,7 @@ struct nfs_client {
        /* The flags used for obtaining the clientid during EXCHANGE_ID */
        u32                     cl_exchange_flags;
        struct nfs4_session     *cl_session;    /* shared session */
+       struct nfs41_server_owner *cl_serverowner;
        struct nfs41_server_scope *cl_serverscope;
        struct nfs41_impl_id    *cl_implid;
 #endif /* CONFIG_NFS_V4 */
index 07048c012dec282ff4f7c697cfae43f9846d65d0..0872f32c8eef8f5e8b63ae7ab6a0634ecaea2dbf 100644 (file)
@@ -1098,7 +1098,7 @@ struct nfs41_exchange_id_args {
        u32                             flags;
 };
 
-struct server_owner {
+struct nfs41_server_owner {
        uint64_t                        minor_id;
        uint32_t                        major_id_sz;
        char                            major_id[NFS4_OPAQUE_LIMIT];
@@ -1118,6 +1118,7 @@ struct nfs41_impl_id {
 struct nfs41_exchange_id_res {
        struct nfs_client               *client;
        u32                             flags;
+       struct nfs41_server_owner       *server_owner;
        struct nfs41_server_scope       *server_scope;
        struct nfs41_impl_id            *impl_id;
 };