summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorrobinson <none@none>2006-01-10 08:52:24 -0800
committerrobinson <none@none>2006-01-10 08:52:24 -0800
commiteac3aab7aa7e29942e099c28d9dcd8017972926d (patch)
tree19046f94721e20f8cef8a88123c96b749724f685 /usr
parentd2443e765650e70b88cd0346e67d2aee6dd1ea3a (diff)
downloadillumos-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.c17
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_attr.c80
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c4
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_xdr.c426
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_server.c18
-rw-r--r--usr/src/uts/common/nfs/nfs4.h4
-rw-r--r--usr/src/uts/common/nfs/nfs4_kprot.h5
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 *);