diff options
author | robinson <none@none> | 2006-01-10 08:52:24 -0800 |
---|---|---|
committer | robinson <none@none> | 2006-01-10 08:52:24 -0800 |
commit | eac3aab7aa7e29942e099c28d9dcd8017972926d (patch) | |
tree | 19046f94721e20f8cef8a88123c96b749724f685 /usr | |
parent | d2443e765650e70b88cd0346e67d2aee6dd1ea3a (diff) | |
download | illumos-joyent-eac3aab7aa7e29942e099c28d9dcd8017972926d.tar.gz |
4799697 nfs messages could be more useful
6354997 File changes on NFSv4 servers take a long time to be detected
6355634 Client handling of CB_GETATTR fails to set bitmap
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_callback.c | 17 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_srv_attr.c | 80 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs4_xdr.c | 426 | ||||
-rw-r--r-- | usr/src/uts/common/fs/nfs/nfs_server.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/nfs4.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/nfs/nfs4_kprot.h | 5 |
7 files changed, 333 insertions, 221 deletions
diff --git a/usr/src/uts/common/fs/nfs/nfs4_callback.c b/usr/src/uts/common/fs/nfs/nfs4_callback.c index d80cde3182..93f8cfedcc 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_callback.c +++ b/usr/src/uts/common/fs/nfs/nfs4_callback.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,8 +93,6 @@ nfs_space_limit4 nfs4_deleg_space_phony = { NFS_LIMIT_SIZE, 8192 }; nfs_space_limit4 nfs4_deleg_space_phony2 = { NFS_LIMIT_BLOCKS, 0 }; nfs_modified_limit4 nfs4_deleg_space_phonyl = { 8, 512 }; changeid4 nfs4_deleg_change_phony = 0x7eeeeeee76666660LL; -/* ignore malformed file handle on recall, bug in linux server */ -int nfs4_linux_bug = 1; int nfs4_use_phony_limit; int nfs4_use_phony_recall; int nfs4_phony_recall_v; @@ -192,7 +190,7 @@ cb_getattr(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req, bool_t found = FALSE; struct nfs4_server *sp; struct fattr4 *fap; - char *fdata = NULL; + rpc_inline_t *fdata; long mapcnt; fattr4_change change; fattr4_size size; @@ -317,7 +315,7 @@ cb_getattr(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req, fap->attrmask = 0; /* attrlist4_len starts at 0 and increases as attrs are processed */ - fap->attrlist4 = fdata; + fap->attrlist4 = (char *)fdata; fap->attrlist4_len = 0; /* don't supply attrs if request was zero */ @@ -359,6 +357,7 @@ cb_getattr(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req, */ IXDR_PUT_U_HYPER(fdata, change); fap->attrlist4_len += 2 * BYTES_PER_XDR_UNIT; + fap->attrmask |= FATTR4_CHANGE_MASK; } if (args->attr_request & FATTR4_SIZE_MASK) { @@ -376,6 +375,7 @@ cb_getattr(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req, */ IXDR_PUT_U_HYPER(fdata, size); fap->attrlist4_len += 2 * BYTES_PER_XDR_UNIT; + fap->attrmask |= FATTR4_SIZE_MASK; } } @@ -457,11 +457,6 @@ cb_recall(nfs_cb_argop4 *argop, nfs_cb_resop4 *resop, struct svc_req *req, } else { #ifdef DEBUG CB_WARN("cb_recall: stateid OK, bad fh"); - - if (nfs4_linux_bug) { - found = TRUE; - break; - } #endif } } @@ -735,7 +730,7 @@ cb_dispatch(struct svc_req *req, SVCXPRT *xprt) break; case CB_COMPOUND: - xdr_args = xdr_CB_COMPOUND4args; + xdr_args = xdr_CB_COMPOUND4args_clnt; xdr_res = xdr_CB_COMPOUND4res; proc = cb_compound; freeproc = cb_compound_free; diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c index 6169621a73..5e77185200 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c +++ b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -753,19 +753,37 @@ rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, return (error); } +/* + * Server side compare of a filehandle from the wire to a native + * server filehandle. + */ +static int +rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh) +{ + nfs_fh4_fmt_t fh; + + ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t))); + + bzero(&fh, sizeof (nfs_fh4_fmt_t)); + if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh, + wirefh->nfs_fh4_len)) + return (1); + + return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len)); +} + /* ARGSUSED */ static int rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na) { - int error = 0; nfs_fh4 *fh; switch (cmd) { case NFS4ATTR_SUPPORTED: if (sarg->op == NFS4ATTR_SETIT) - error = EINVAL; - break; /* this attr is supported */ + return (EINVAL); + return (0); /* this attr is supported */ case NFS4ATTR_GETIT: /* * If sarg->cs->fh is all zeros then should makefh a new @@ -773,42 +791,44 @@ rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, */ fh = &sarg->cs->fh; if (sarg->cs->fh.nfs_fh4_len == 0) { - if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { - error = -1; /* okay if rdattr_error */ - break; - } + if (sarg->rdattr_error && (sarg->cs->vp == NULL)) + return (-1); /* okay if rdattr_error */ ASSERT(sarg->cs->vp != NULL); na->filehandle.nfs_fh4_val = - kmem_alloc(NFS_FH4_LEN, KM_SLEEP); - error = makefh4(&na->filehandle, sarg->cs->vp, - sarg->cs->exi); - } else { - na->filehandle.nfs_fh4_val = - kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); - nfs_fh4_copy(fh, &na->filehandle); + kmem_alloc(NFS_FH4_LEN, KM_SLEEP); + return (makefh4(&na->filehandle, sarg->cs->vp, + sarg->cs->exi)); } - break; + na->filehandle.nfs_fh4_val = + kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); + nfs_fh4_copy(fh, &na->filehandle); + return (0); case NFS4ATTR_SETIT: /* * read-only attr */ - error = EINVAL; - break; + return (EINVAL); case NFS4ATTR_VERIT: - if (nfs4cmpfh(&na->filehandle, &sarg->cs->fh)) - error = -1; /* no match */ - break; + /* + * A verify of a filehandle will have the client sending + * the raw format which needs to be compared to the + * native format. + */ + if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1) + return (-1); /* no match */ + return (0); case NFS4ATTR_FREEIT: - if (sarg->op == NFS4ATTR_GETIT) { - if (na->filehandle.nfs_fh4_val) { - kmem_free(na->filehandle.nfs_fh4_val, - na->filehandle.nfs_fh4_len); - bzero(&na->filehandle, sizeof (na->filehandle)); - } - } - break; + if (sarg->op != NFS4ATTR_GETIT) + return (0); + if (na->filehandle.nfs_fh4_val == NULL) + return (0); + kmem_free(na->filehandle.nfs_fh4_val, + na->filehandle.nfs_fh4_len); + na->filehandle.nfs_fh4_val = NULL; + na->filehandle.nfs_fh4_len = 0; + return (0); } - return (error); + return (0); } /* diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c b/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c index b42fc98cb7..84b8d36b6b 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c +++ b/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -833,7 +833,7 @@ retry: */ args->callback_ident = cbp->cb_ident; - stat = clnt_call(ch, CB_COMPOUND, xdr_CB_COMPOUND4args, + stat = clnt_call(ch, CB_COMPOUND, xdr_CB_COMPOUND4args_srv, (caddr_t)args, xdr_CB_COMPOUND4res, (caddr_t)res, timeout); diff --git a/usr/src/uts/common/fs/nfs/nfs4_xdr.c b/usr/src/uts/common/fs/nfs/nfs4_xdr.c index ec08a8006f..5020d4dc87 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_xdr.c +++ b/usr/src/uts/common/fs/nfs/nfs4_xdr.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. + * Copyright 2006 Sun Microsystems, Inc. * All rights reserved. Use is subject to license terms. */ @@ -149,93 +149,109 @@ xdr_utf8string(XDR *xdrs, utf8string *objp) } /* - * XDR_INLINE encode a filehandle. + * XDR_INLINE decode a filehandle. */ bool_t -xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone, - nfs_fh4_fmt_t *fhp) +xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize) { - uint32_t *ptr = *ptrp; + uchar_t *bp = (uchar_t *)ptr; uchar_t *cp; - uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ - uint32_t padword; - - fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; - xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; + uint32_t dsize; + uintptr_t resid; /* - * First get the initial and variable sized part of the filehandle. + * Check to see if what the client sent us is bigger or smaller + * than what we can ever possibly send out. NFS_FHMAXDATA is + * unfortunately badly named as it is no longer the max and is + * really the min of what is sent over the wire. */ - otw_len = sizeof (fhp->fh4_fsid) + - sizeof (fhp->fh4_len) + fsize + - sizeof (fhp->fh4_xlen) + xsize; + if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) + + sizeof (ushort_t) + NFS_FHMAXDATA + + sizeof (ushort_t) + NFS_FHMAXDATA)) { + return (FALSE); + } /* - * Round out to a full word. + * All internal parts of a filehandle are in native byte order. + * + * Decode what should be fh4_fsid, it is aligned. */ - otw_len = RNDUP(otw_len); - padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */ + fhp->fh4_fsid.val[0] = *(uint32_t *)bp; + bp += BYTES_PER_XDR_UNIT; + fhp->fh4_fsid.val[1] = *(uint32_t *)bp; + bp += BYTES_PER_XDR_UNIT; /* - * Add in the fixed sized pieces. + * Decode what should be fh4_len. fh4_len is two bytes, so we're + * unaligned now. */ - otw_len += sizeof (fhp->fh4_flag); -#ifdef VOLATILE_FH_TEST - otw_len += sizeof (fhp->fh4_volatile_id); -#endif + cp = (uchar_t *)&fhp->fh4_len; + *cp++ = *bp++; + *cp++ = *bp++; + fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t); /* - * Make sure we don't exceed our buffer. + * For backwards compatability, the fid length may be less than + * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes. */ - if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone) - return (FALSE); - - IXDR_PUT_U_INT32(ptr, otw_len); + dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; /* - * Zero out the pading. + * Make sure the client isn't sending us a bogus length for fh4_data. */ - ptr[padword] = 0; + if (fhsize < dsize) + return (FALSE); + bcopy(bp, fhp->fh4_data, dsize); + bp += dsize; + fhsize -= dsize; - /* - * The rest of the filehandle is in native byteorder - */ - /* fh4_fsid */ - *ptr++ = (uint32_t)fhp->fh4_fsid.val[0]; - *ptr++ = (uint32_t)fhp->fh4_fsid.val[1]; + if (fhsize < sizeof (ushort_t)) + return (FALSE); + cp = (uchar_t *)&fhp->fh4_xlen; + *cp++ = *bp++; + *cp++ = *bp++; + fhsize -= sizeof (ushort_t); + + dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; /* - * Since the next pieces are unaligned, we need to - * do bytewise copies. + * Make sure the client isn't sending us a bogus length for fh4_xdata. */ - cp = (uchar_t *)ptr; - - /* fh4_len + fh4_data */ - bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize); - cp += sizeof (fhp->fh4_len) + fsize; - - /* fh4_xlen + fh4_xdata */ - bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize); - cp += sizeof (fhp->fh4_xlen) + xsize; - - /* do necessary rounding/padding */ - cp = (uchar_t *)RNDUP((uintptr_t)cp); - ptr = (uint32_t *)cp; + if (fhsize < dsize) + return (FALSE); + bcopy(bp, fhp->fh4_xdata, dsize); + fhsize -= dsize; + bp += dsize; /* - * With the above padding, we're word aligned again. + * We realign things on purpose, so skip any padding */ - ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0); + resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT; + if (resid != 0) { + if (fhsize < (BYTES_PER_XDR_UNIT - resid)) + return (FALSE); + bp += BYTES_PER_XDR_UNIT - resid; + fhsize -= BYTES_PER_XDR_UNIT - resid; + } - /* fh4_flag */ - *ptr++ = (uint32_t)fhp->fh4_flag; + if (fhsize < BYTES_PER_XDR_UNIT) + return (FALSE); + fhp->fh4_flag = *(uint32_t *)bp; + bp += BYTES_PER_XDR_UNIT; + fhsize -= BYTES_PER_XDR_UNIT; #ifdef VOLATILE_FH_TEST - /* fh4_volatile_id */ - *ptr++ = (uint32_t)fhp->fh4_volatile_id; + if (fhsize < BYTES_PER_XDR_UNIT) + return (FALSE); + fhp->fh4_volatile_id = *(uint32_t *)bp; + bp += BYTES_PER_XDR_UNIT; + fhsize -= BYTES_PER_XDR_UNIT; #endif - *ptrp = ptr; - + /* + * Make sure client didn't send extra bytes + */ + if (fhsize != 0) + return (FALSE); return (TRUE); } @@ -244,11 +260,8 @@ xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) { uint32_t fhsize; /* filehandle size */ uint32_t bufsize; - uint32_t dsize; - nfs_fh4_fmt_t *fh_fmtp; rpc_inline_t *ptr; - uintptr_t resid; - uchar_t *buf, *bp, *cp; + uchar_t *buf, *bp; ASSERT(xdrs->x_op == XDR_DECODE); @@ -280,118 +293,122 @@ xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) */ bufsize = RNDUP(fhsize); ptr = XDR_INLINE(xdrs, bufsize); + bp = (uchar_t *)ptr; if (ptr == NULL) { bp = buf = kmem_alloc(bufsize, KM_SLEEP); if (!xdr_opaque(xdrs, (char *)bp, bufsize)) return (FALSE); - } else { - bp = (uchar_t *)ptr; } objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP); objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t); - fh_fmtp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val; + + if (xdr_inline_decode_nfs_fh4((uint32_t *)bp, + (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) { + /* + * If in the process of decoding we find the file handle + * is not correctly formed, we need to continue decoding + * and trigger an NFS layer error. Set the nfs_fh4_len to + * zero so it gets caught as a bad length. + */ + kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); + objp->nfs_fh4_val = NULL; + objp->nfs_fh4_len = 0; + } + + if (ptr == NULL) + kmem_free(buf, bufsize); + return (TRUE); +} + +/* + * XDR_INLINE encode a filehandle. + */ +bool_t +xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone, + nfs_fh4_fmt_t *fhp) +{ + uint32_t *ptr = *ptrp; + uchar_t *cp; + uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ + uint32_t padword; + + fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; + xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; /* - * All internal parts of a filehandle are in native byte order. - * - * Decode what should be fh4_fsid, it is aligned. + * First get the initial and variable sized part of the filehandle. */ - fh_fmtp->fh4_fsid.val[0] = *(uint32_t *)bp; - bp += BYTES_PER_XDR_UNIT; - fh_fmtp->fh4_fsid.val[1] = *(uint32_t *)bp; - bp += BYTES_PER_XDR_UNIT; + otw_len = sizeof (fhp->fh4_fsid) + + sizeof (fhp->fh4_len) + fsize + + sizeof (fhp->fh4_xlen) + xsize; /* - * Decode what should be fh4_len. fh4_len is two bytes, so we're - * unaligned now. + * Round out to a full word. */ - cp = (uchar_t *)&fh_fmtp->fh4_len; - *cp++ = *bp++; - *cp++ = *bp++; - fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t); + otw_len = RNDUP(otw_len); + padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */ /* - * For backwards compatability, the fid length may be less than - * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes. + * Add in the fixed sized pieces. */ - dsize = fh_fmtp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : - fh_fmtp->fh4_len; + otw_len += sizeof (fhp->fh4_flag); +#ifdef VOLATILE_FH_TEST + otw_len += sizeof (fhp->fh4_volatile_id); +#endif /* - * Make sure the client isn't sending us a bogus length for fh4_data. + * Make sure we don't exceed our buffer. */ - if (dsize > fhsize) - goto badfh; - bcopy(bp, fh_fmtp->fh4_data, dsize); - bp += dsize; - fhsize -= dsize; + if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone) + return (FALSE); - if (fhsize < sizeof (ushort_t)) - goto badfh; - cp = (uchar_t *)&fh_fmtp->fh4_xlen; - *cp++ = *bp++; - *cp++ = *bp++; - fhsize -= sizeof (ushort_t); + IXDR_PUT_U_INT32(ptr, otw_len); - dsize = fh_fmtp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : - fh_fmtp->fh4_xlen; /* - * Make sure the client isn't sending us a bogus length for fh4_xdata. + * Zero out the pading. */ - if (dsize > fhsize) - goto badfh; - bcopy(bp, fh_fmtp->fh4_xdata, dsize); - fhsize -= dsize; - bp += dsize; + ptr[padword] = 0; /* - * We realign things on purpose, so skip any padding + * The rest of the filehandle is in native byteorder */ - resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT; - if (resid != 0) { - if (fhsize < (BYTES_PER_XDR_UNIT - resid)) - goto badfh; - bp += BYTES_PER_XDR_UNIT - resid; - fhsize -= BYTES_PER_XDR_UNIT - resid; - } - - if (fhsize < BYTES_PER_XDR_UNIT) - goto badfh; - fh_fmtp->fh4_flag = *(uint32_t *)bp; - bp += BYTES_PER_XDR_UNIT; - fhsize -= BYTES_PER_XDR_UNIT; + /* fh4_fsid */ + *ptr++ = (uint32_t)fhp->fh4_fsid.val[0]; + *ptr++ = (uint32_t)fhp->fh4_fsid.val[1]; -#ifdef VOLATILE_FH_TEST - if (fhsize < BYTES_PER_XDR_UNIT) - goto badfh; - fh_fmtp->fh4_fh4_volatile_id = *(uint32_t *)bp; - bp += BYTES_PER_XDR_UNIT; - fhsize -= BYTES_PER_XDR_UNIT; -#endif /* - * Make sure client didn't send extra bytes + * Since the next pieces are unaligned, we need to + * do bytewise copies. */ - if (fhsize != 0) - goto badfh; + cp = (uchar_t *)ptr; - if (ptr == NULL) - kmem_free(buf, bufsize); - return (TRUE); + /* fh4_len + fh4_data */ + bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize); + cp += sizeof (fhp->fh4_len) + fsize; + + /* fh4_xlen + fh4_xdata */ + bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize); + cp += sizeof (fhp->fh4_xlen) + xsize; + + /* do necessary rounding/padding */ + cp = (uchar_t *)RNDUP((uintptr_t)cp); + ptr = (uint32_t *)cp; -badfh: /* - * If in the process of decoding we find the file handle - * is not correctly formed, we need to continue decoding - * and trigger an NFS layer error. Set the nfs_fh4_len to - * zero so it gets caught as a bad length. + * With the above padding, we're word aligned again. */ - if (objp->nfs_fh4_val != NULL) - kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); - objp->nfs_fh4_val = NULL; - objp->nfs_fh4_len = 0; - if (ptr == NULL) - kmem_free(buf, bufsize); + ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0); + + /* fh4_flag */ + *ptr++ = (uint32_t)fhp->fh4_flag; + +#ifdef VOLATILE_FH_TEST + /* fh4_volatile_id */ + *ptr++ = (uint32_t)fhp->fh4_volatile_id; +#endif + *ptrp = ptr; + return (TRUE); } @@ -450,20 +467,26 @@ xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) /* * XDR a NFSv4 filehandle. + * Encoding interprets the contents (server). + * Decoding the contents are opaque (client). */ bool_t xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) { - if (xdrs->x_op == XDR_DECODE) - return (xdr_decode_nfs_fh4(xdrs, objp)); - else if (xdrs->x_op == XDR_ENCODE) + switch (xdrs->x_op) { + case XDR_ENCODE: return (xdr_encode_nfs_fh4(xdrs, objp)); - - if (objp->nfs_fh4_val != NULL) { - kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); - objp->nfs_fh4_val = NULL; + case XDR_DECODE: + return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val, + (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE)); + case XDR_FREE: + if (objp->nfs_fh4_val != NULL) { + kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); + objp->nfs_fh4_val = NULL; + } + return (TRUE); } - return (TRUE); + return (FALSE); } /* Called by xdr_array */ @@ -4397,7 +4420,7 @@ xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp) if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) return (TRUE); return (xdr_encode_nfs_fh4(xdrs, - &objp->nfs_resop4_u.opgetfh.object)); + &objp->nfs_resop4_u.opgetfh.object)); default: return (xdr_nfs_resop4(xdrs, objp)); } @@ -4715,35 +4738,78 @@ xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp) objp->array_len, objp->array_len)); } +/* + * NFS server side callback, initiating the callback request so it + * is the RPC client. Must convert from server's internal filehandle + * format to wire format. + */ static bool_t -xdr_nfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) +xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) { + CB_GETATTR4args *gargs; + CB_RECALL4args *rargs; + + ASSERT(xdrs->x_op == XDR_ENCODE); + + if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop)) + return (FALSE); + + switch (objp->argop) { + case OP_CB_GETATTR: + gargs = &objp->nfs_cb_argop4_u.opcbgetattr; + + if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh)) + return (FALSE); + return (xdr_bitmap4(xdrs, &gargs->attr_request)); + case OP_CB_RECALL: + rargs = &objp->nfs_cb_argop4_u.opcbrecall; + + if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid)) + return (FALSE); + if (!xdr_opaque(xdrs, rargs->stateid.other, 12)) + return (FALSE); + if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate)) + return (FALSE); + return (xdr_encode_nfs_fh4(xdrs, &rargs->fh)); + case OP_CB_ILLEGAL: + return (TRUE); + } + return (FALSE); +} + +/* + * NFS client side callback, receiving the callback request so it + * is the RPC server. Must treat the file handles as opaque. + */ +static bool_t +xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) +{ + CB_GETATTR4args *gargs; + CB_RECALL4args *rargs; + + ASSERT(xdrs->x_op != XDR_ENCODE); + if (!xdr_u_int(xdrs, &objp->argop)) return (FALSE); switch (objp->argop) { case OP_CB_GETATTR: - if (!xdr_bytes(xdrs, - (char **)&objp->nfs_cb_argop4_u.opcbgetattr.fh.nfs_fh4_val, - (uint_t *)&objp->nfs_cb_argop4_u.opcbgetattr.fh.nfs_fh4_len, - NFS4_FHSIZE)) + gargs = &objp->nfs_cb_argop4_u.opcbgetattr; + + if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val, + (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE)) return (FALSE); - return (xdr_bitmap4(xdrs, - &objp->nfs_cb_argop4_u.opcbgetattr.attr_request)); + return (xdr_bitmap4(xdrs, &gargs->attr_request)); case OP_CB_RECALL: - if (!xdr_u_int(xdrs, - &objp->nfs_cb_argop4_u.opcbrecall.stateid.seqid)) + rargs = &objp->nfs_cb_argop4_u.opcbrecall; + + if (!xdr_u_int(xdrs, &rargs->stateid.seqid)) return (FALSE); - if (!xdr_opaque(xdrs, - objp->nfs_cb_argop4_u.opcbrecall.stateid.other, - 12)) + if (!xdr_opaque(xdrs, rargs->stateid.other, 12)) return (FALSE); - if (!xdr_bool(xdrs, - &objp->nfs_cb_argop4_u.opcbrecall.truncate)) + if (!xdr_bool(xdrs, &rargs->truncate)) return (FALSE); - return (xdr_bytes(xdrs, - (char **)&objp->nfs_cb_argop4_u.opcbrecall.fh.nfs_fh4_val, - (uint_t *)&objp->nfs_cb_argop4_u.opcbrecall.fh.nfs_fh4_len, - NFS4_FHSIZE)); + return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val, + (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE)); case OP_CB_ILLEGAL: return (TRUE); } @@ -4776,8 +4842,30 @@ xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp) return (FALSE); } +/* + * The NFS client side callback, RPC server + */ +bool_t +xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp) +{ + if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, + (uint_t *)&objp->tag.utf8string_len, + NFS4_MAX_UTF8STRING)) + return (FALSE); + if (!xdr_u_int(xdrs, &objp->minorversion)) + return (FALSE); + if (!xdr_u_int(xdrs, &objp->callback_ident)) + return (FALSE); + return (xdr_array(xdrs, (char **)&objp->array, + (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, + sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4)); +} + +/* + * The NFS server side callback, RPC client + */ bool_t -xdr_CB_COMPOUND4args(XDR *xdrs, CB_COMPOUND4args *objp) +xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp) { if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, (uint_t *)&objp->tag.utf8string_len, @@ -4789,7 +4877,7 @@ xdr_CB_COMPOUND4args(XDR *xdrs, CB_COMPOUND4args *objp) return (FALSE); return (xdr_array(xdrs, (char **)&objp->array, (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, - sizeof (nfs_cb_argop4), (xdrproc_t)xdr_nfs_cb_argop4)); + sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4)); } bool_t diff --git a/usr/src/uts/common/fs/nfs/nfs_server.c b/usr/src/uts/common/fs/nfs/nfs_server.c index 8d99ee0dbf..c7cb83bbde 100644 --- a/usr/src/uts/common/fs/nfs/nfs_server.c +++ b/usr/src/uts/common/fs/nfs/nfs_server.c @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1426,6 +1426,8 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers, struct netbuf nb; bool_t logging_enabled = FALSE; struct exportinfo *nfslog_exi = NULL; + char **procnames; + char cbuf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */ vers = req->rq_vers; @@ -1447,12 +1449,13 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers, (*(disptable[(int)vers].dis_proccntp))[which].value.ui64++; disp = &disptable[(int)vers].dis_table[which]; + procnames = disptable[(int)vers].dis_procnames; auth_flavor = req->rq_cred.oa_flavor; + /* * Deserialize into the args struct. */ - args = (char *)&args_buf; #ifdef DEBUG @@ -1468,8 +1471,11 @@ common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers, if (!SVC_GETARGS(xprt, disp->dis_xdrargs, args)) { svcerr_decode(xprt); error++; - cmn_err(CE_NOTE, "%s: bad getargs for %u/%d", - pgmname, vers + min_vers, which); + cmn_err(CE_NOTE, + "Failed to decode arguments for %s version %u " + "procedure %s client %s%s", + pgmname, vers + min_vers, procnames[which], + client_name(req), client_addr(req, cbuf)); goto done; } } @@ -1741,7 +1747,7 @@ static void rfs_dispatch(struct svc_req *req, SVCXPRT *xprt) { common_dispatch(req, xprt, NFS_VERSMIN, NFS_VERSMAX, - "nfs_server", rfs_disptable); + "NFS", rfs_disptable); } static char *aclcallnames_v2[] = { @@ -1867,7 +1873,7 @@ static void acl_dispatch(struct svc_req *req, SVCXPRT *xprt) { common_dispatch(req, xprt, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, - "acl_server", acl_disptable); + "ACL", acl_disptable); } int diff --git a/usr/src/uts/common/nfs/nfs4.h b/usr/src/uts/common/nfs/nfs4.h index c501f8726f..1fc6edd28f 100644 --- a/usr/src/uts/common/nfs/nfs4.h +++ b/usr/src/uts/common/nfs/nfs4.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1286,6 +1286,8 @@ extern const struct fs_operation_def nfs4_vnodeops_template[]; extern uint_t nfs4_tsize(struct knetconfig *); extern uint_t rfs4_tsize(struct svc_req *); +extern bool_t xdr_inline_decode_nfs_fh4(uint32_t *, nfs_fh4_fmt_t *, + uint32_t); extern bool_t xdr_inline_encode_nfs_fh4(uint32_t **, uint32_t *, nfs_fh4_fmt_t *); diff --git a/usr/src/uts/common/nfs/nfs4_kprot.h b/usr/src/uts/common/nfs/nfs4_kprot.h index 65187b3935..9befd95284 100644 --- a/usr/src/uts/common/nfs/nfs4_kprot.h +++ b/usr/src/uts/common/nfs/nfs4_kprot.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1621,7 +1621,8 @@ extern bool_t xdr_COMPOUND4args_clnt(XDR *, COMPOUND4args_clnt *); extern bool_t xdr_COMPOUND4args_srv(XDR *, COMPOUND4args *); extern bool_t xdr_COMPOUND4res_clnt(XDR *, COMPOUND4res_clnt *); extern bool_t xdr_COMPOUND4res_srv(XDR *, COMPOUND4res *); -extern bool_t xdr_CB_COMPOUND4args(XDR *, CB_COMPOUND4args *); +extern bool_t xdr_CB_COMPOUND4args_clnt(XDR *, CB_COMPOUND4args *); +extern bool_t xdr_CB_COMPOUND4args_srv(XDR *, CB_COMPOUND4args *); extern bool_t xdr_CB_COMPOUND4res(XDR *, CB_COMPOUND4res *); |