From patchwork Tue Dec 14 14:57:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 410091 X-Patchwork-Delegate: Trond.Myklebust@netapp.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBEEstS5007667 for ; Tue, 14 Dec 2010 14:58:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758082Ab0LNO51 (ORCPT ); Tue, 14 Dec 2010 09:57:27 -0500 Received: from mail-iw0-f174.google.com ([209.85.214.174]:43581 "EHLO mail-iw0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757744Ab0LNO50 (ORCPT ); Tue, 14 Dec 2010 09:57:26 -0500 Received: by mail-iw0-f174.google.com with SMTP id 9so862488iwn.19 for ; Tue, 14 Dec 2010 06:57:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:from:subject:to:cc :date:message-id:in-reply-to:references:user-agent:mime-version :content-type:content-transfer-encoding; bh=JJ8adT7qiWeA6entBh3TuhQj71gbkeRGvlyIrRUO4Ic=; b=HkdaqxoPDV18xhOE1kfSChAHZFMTYBHE2GCmDuLwtDzx1xqbdcJVSQErK0miZ35/w2 pN+BtFeGPxkOFVtFJN+9ELAGUHTm34pBu1jjfjrRFcxL93yTkUAHGYJimlIaPK8mBEQI nl5t4mZLjjWqbqAIXi75XRVGWW/+YPys4u8QY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:subject:to:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding; b=hELrvkv9DR+eFWqpRRBCdBkkPbks2wn/tu2TqmRm97vZcr8oPilFYbSxQk41YDj3gR Jz5wYoYI07eshsrXCIzjEjZSfx3tjRoyO35Jwym3Y1h0/7AYmS5b/qpmPkcRBg1Q/CQQ M/p7rz+5NawfS2ve42be4FCsvTxBqbilRkqvw= Received: by 10.231.35.131 with SMTP id p3mr3357641ibd.87.1292338645074; Tue, 14 Dec 2010 06:57:25 -0800 (PST) Received: from matisse.1015granger.net ([99.26.161.222]) by mx.google.com with ESMTPS id z4sm102907ibg.19.2010.12.14.06.57.23 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 14 Dec 2010 06:57:24 -0800 (PST) From: Chuck Lever Subject: [PATCH 18/31] NFSD: Update XDR encoders in NFSv4 callback client To: trond.myklebust@netapp.com Cc: linux-nfs@vger.kernel.org Date: Tue, 14 Dec 2010 09:57:22 -0500 Message-ID: <20101214145722.2293.88238.stgit@matisse.1015granger.net> In-Reply-To: <20101214144747.2293.68070.stgit@matisse.1015granger.net> References: <20101214144747.2293.68070.stgit@matisse.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 14 Dec 2010 14:58:05 +0000 (UTC) diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 143da2e..d8148cc 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -50,11 +50,6 @@ enum { NFSPROC4_CLNT_CB_SEQUENCE, }; -enum nfs_cb_opnum4 { - OP_CB_RECALL = 4, - OP_CB_SEQUENCE = 11, -}; - #define NFS4_MAXTAGLEN 20 #define NFS4_enc_cb_null_sz 0 @@ -80,30 +75,6 @@ enum nfs_cb_opnum4 { op_dec_sz) /* -* Generic encode routines from fs/nfs/nfs4xdr.c -*/ -static inline __be32 * -xdr_writemem(__be32 *p, const void *ptr, int nbytes) -{ - int tmp = XDR_QUADLEN(nbytes); - if (!tmp) - return p; - p[tmp-1] = 0; - memcpy(p, ptr, nbytes); - return p + tmp; -} - -#define WRITE32(n) *p++ = htonl(n) -#define WRITEMEM(ptr,nbytes) do { \ - p = xdr_writemem(p, ptr, nbytes); \ -} while (0) -#define RESERVE_SPACE(nbytes) do { \ - p = xdr_reserve_space(xdr, nbytes); \ - if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \ - BUG_ON(!p); \ -} while (0) - -/* * Generic decode routines from fs/nfs/nfs4xdr.c */ #define DECODE_TAIL \ @@ -197,102 +168,232 @@ nfs_cb_stat_to_errno(int stat) return stat; } +static __be32 *xdr_encode_empty_array(__be32 *p) +{ + *p++ = xdr_zero; + return p; +} + +/* + * Encode/decode NFSv4 CB basic data types + * + * Basic NFSv4 callback data types are defined in section 15 of RFC + * 3530: "Network File System (NFS) version 4 Protocol" and section + * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version + * 1 Protocol" + */ + +/* + * nfs_cb_opnum4 + * + * enum nfs_cb_opnum4 { + * OP_CB_GETATTR = 3, + * ... + * }; + */ +enum nfs_cb_opnum4 { + OP_CB_GETATTR = 3, + OP_CB_RECALL = 4, + OP_CB_LAYOUTRECALL = 5, + OP_CB_NOTIFY = 6, + OP_CB_PUSH_DELEG = 7, + OP_CB_RECALL_ANY = 8, + OP_CB_RECALLABLE_OBJ_AVAIL = 9, + OP_CB_RECALL_SLOT = 10, + OP_CB_SEQUENCE = 11, + OP_CB_WANTS_CANCELLED = 12, + OP_CB_NOTIFY_LOCK = 13, + OP_CB_NOTIFY_DEVICEID = 14, + OP_CB_ILLEGAL = 10044 +}; + +static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op) +{ + __be32 *p; + + p = xdr_reserve_space(xdr, 4); + *p = cpu_to_be32(op); +} + +/* + * nfs_fh4 + * + * typedef opaque nfs_fh4; + */ +static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh) +{ + u32 length = fh->fh_size; + __be32 *p; + + BUG_ON(length > NFS4_FHSIZE); + p = xdr_reserve_space(xdr, 4 + length); + xdr_encode_opaque(p, &fh->fh_base, length); +} + /* - * XDR encode + * stateid4 + * + * struct stateid4 { + * uint32_t seqid; + * opaque other[12]; + * }; */ +static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid) +{ + __be32 *p; + + p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE); + *p++ = cpu_to_be32(sid->si_generation); + xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE); +} -static void -encode_stateid(struct xdr_stream *xdr, stateid_t *sid) +/* + * sessionid4 + * + * typedef opaque sessionid4[NFS4_SESSIONID_SIZE]; + */ +static void encode_sessionid4(struct xdr_stream *xdr, + const struct nfsd4_session *session) { __be32 *p; - RESERVE_SPACE(sizeof(stateid_t)); - WRITE32(sid->si_generation); - WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); + p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN); + xdr_encode_opaque_fixed(p, session->se_sessionid.data, + NFS4_MAX_SESSIONID_LEN); } -static void -encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) +/* + * CB_COMPOUND4args + * + * struct CB_COMPOUND4args { + * utf8str_cs tag; + * uint32_t minorversion; + * uint32_t callback_ident; + * nfs_cb_argop4 argarray<>; + * }; +*/ +static void encode_cb_compound4args(struct xdr_stream *xdr, + struct nfs4_cb_compound_hdr *hdr) { __be32 * p; - RESERVE_SPACE(16); - WRITE32(0); /* tag length is always 0 */ - WRITE32(hdr->minorversion); - WRITE32(hdr->ident); + p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4); + p = xdr_encode_empty_array(p); /* empty tag */ + *p++ = cpu_to_be32(hdr->minorversion); + *p++ = cpu_to_be32(hdr->ident); + hdr->nops_p = p; - WRITE32(hdr->nops); + *p = cpu_to_be32(hdr->nops); /* argarray element count */ } +/* + * Update argarray element count + */ static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) { - *hdr->nops_p = htonl(hdr->nops); + BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS); + *hdr->nops_p = cpu_to_be32(hdr->nops); } -static void -encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, - struct nfs4_cb_compound_hdr *hdr) +/* + * CB_RECALL4args + * + * struct CB_RECALL4args { + * stateid4 stateid; + * bool truncate; + * nfs_fh4 fh; + * }; + */ +static void encode_cb_recall4args(struct xdr_stream *xdr, + const struct nfs4_delegation *dp, + struct nfs4_cb_compound_hdr *hdr) { __be32 *p; - int len = dp->dl_fh.fh_size; - - RESERVE_SPACE(4); - WRITE32(OP_CB_RECALL); - encode_stateid(xdr, &dp->dl_stateid); - RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2)); - WRITE32(0); /* truncate optimization not implemented */ - WRITE32(len); - WRITEMEM(&dp->dl_fh.fh_base, len); + + encode_nfs_cb_opnum4(xdr, OP_CB_RECALL); + encode_stateid4(xdr, &dp->dl_stateid); + + p = xdr_reserve_space(xdr, 4); + *p++ = xdr_zero; /* truncate */ + + encode_nfs_fh4(xdr, &dp->dl_fh); + hdr->nops++; } -static void -encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb, - struct nfs4_cb_compound_hdr *hdr) +/* + * CB_SEQUENCE4args + * + * struct CB_SEQUENCE4args { + * sessionid4 csa_sessionid; + * sequenceid4 csa_sequenceid; + * slotid4 csa_slotid; + * slotid4 csa_highest_slotid; + * bool csa_cachethis; + * referring_call_list4 csa_referring_call_lists<>; + * }; + */ +static void encode_cb_sequence4args(struct xdr_stream *xdr, + const struct nfsd4_callback *cb, + struct nfs4_cb_compound_hdr *hdr) { + struct nfsd4_session *session = cb->cb_clp->cl_cb_session; __be32 *p; - struct nfsd4_session *ses = cb->cb_clp->cl_cb_session; if (hdr->minorversion == 0) return; - RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20); + encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE); + encode_sessionid4(xdr, session); + + p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4); + *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */ + *p++ = xdr_zero; /* csa_slotid */ + *p++ = xdr_zero; /* csa_highest_slotid */ + *p++ = xdr_zero; /* csa_cachethis */ + xdr_encode_empty_array(p); /* csa_referring_call_lists */ - WRITE32(OP_CB_SEQUENCE); - WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN); - WRITE32(ses->se_cb_seq_nr); - WRITE32(0); /* slotid, always 0 */ - WRITE32(0); /* highest slotid always 0 */ - WRITE32(0); /* cachethis always 0 */ - WRITE32(0); /* FIXME: support referring_call_lists */ hdr->nops++; } -static int -nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p) +/* + * NFSv4.0 and NFSv4.1 XDR encode functions + * + * NFSv4.0 callback argument types are defined in section 15 of RFC + * 3530: "Network File System (NFS) version 4 Protocol" and section 20 + * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1 + * Protocol". + */ + +/* + * NB: Without this zero space reservation, callbacks over krb5p fail + */ +static int nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p, void *__unused) { struct xdr_stream xdrs, *xdr = &xdrs; xdr_init_encode(&xdrs, &req->rq_snd_buf, p); - RESERVE_SPACE(0); + xdr_reserve_space(xdr, 0); return 0; } -static int -nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, - struct nfsd4_callback *cb) +/* + * 20.2. Operation 4: CB_RECALL - Recall a Delegation + */ +static int nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, + const struct nfsd4_callback *cb) { struct xdr_stream xdr; - struct nfs4_delegation *args = cb->cb_op; + const struct nfs4_delegation *args = cb->cb_op; struct nfs4_cb_compound_hdr hdr = { .ident = cb->cb_clp->cl_cb_ident, .minorversion = cb->cb_minorversion, }; xdr_init_encode(&xdr, &req->rq_snd_buf, p); - encode_cb_compound_hdr(&xdr, &hdr); - encode_cb_sequence(&xdr, cb, &hdr); - encode_cb_recall(&xdr, args, &hdr); + encode_cb_compound4args(&xdr, &hdr); + encode_cb_sequence4args(&xdr, cb, &hdr); + encode_cb_recall4args(&xdr, args, &hdr); encode_cb_nops(&hdr); return 0; }