I counted it all up. It definitely needs to be 8 * NFSX_UNSIGNED.
See my count below.
-Matt
:In /sys/nfs/nfs_serv.c:nfsrv_readdirplus(), we have the following
:code:
:
: /*
: * If either the dircount or maxcount will be
: * exceeded, get out now. Both of these lengths
: * are calculated conservatively, including all
: * XDR overheads.
: */
: len += (7 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
: NFSX_V3POSTOPATTR);
: dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
:
:I observed that the value of "len" didn't agree with the actual amount
:of data beong consumed in the mbuf chain. It turns out that each
:time through the loop, len is being incremented by 4 bytes too little.
:In other words, 7 * NFSX_UNSIGNED should really be 8 * NFSX_UNSIGNED.
:When I change 7 to 8, I no longer get oversized replies and everything
:adds up.
:...
:
:Unfortunately I haven't been able to wrap my brain around how this is
:being counted up for the "len" calculation. Whatever it's doing, it's
:off by 4 bytes. Possibly somebody forgot that "filename3" is a string,
:which in XDR format consists of a string bytes, plus padding to a longword
:boundary, *plus* a longword length value. Some comments would have been
:useful here. (Hint, hint.)
:
:What I don't know is whether or not the calculation for dirlen is
:wrong or not. Hopefully now that I've shown everyone the light, maybe
:somebody can tell me for sure.
:
:-Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu
:...
: len += (7 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
: NFSX_V3POSTOPATTR);
nfsm_clget;
*tl = nfs_true;
bp += NFSX_UNSIGNED; (one)
nfsm_clget;
*tl = 0;
bp += NFSX_UNSIGNED; (two)
nfsm_clget;
*tl = txdr_unsigned(dp->d_fileno);
bp += NFSX_UNSIGNED; (three)
nfsm_clget;
*tl = txdr_unsigned(nlen);
bp += NFSX_UNSIGNED; (four)
...
xfer = nlen; (nlen)
while (xfer > 0) {
nfsm_clget;
if ((bp + xfer) > be)
tsiz = be - bp;
else
tsiz = xfer;
bcopy(cp, bp, tsiz);
bp += tsiz;
xfer -= tsiz;
if (xfer > 0)
cp += tsiz;
}
/* And null pad to a int32_t boundary */
for (i = 0; i < rem; i++) (rem)
*bp++ = '\0';
/*
* Now copy the flrep structure out.
*/
xfer = sizeof (struct flrep);
>>>>>>> 8 + 4 + NFSX_V3FATTR + 4 + 4 + NFSX_V3FH
note: NFSX_V3POSTOPATTR eats an extra 32 bit int because it
is defined as:
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
(NFSX_V3POSTOPATTR)
(NFSX_V3FATTR)
(NFSX_V3FH)
20 remaining, remove 4 to take into account NFSX_UNSIGNED
in NFSX_V3POSTOPATTR, leaving 16.
(five)
(six)
(seven)
(eight) *************
struct flrep {
nfsuint64 fl_off;
u_int32_t fl_postopok;
u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
u_int32_t fl_fhok;
u_int32_t fl_fhsize;
u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
};
cp = (caddr_t)&fl;
while (xfer > 0) {
nfsm_clget;
if ((bp + xfer) > be)
tsiz = be - bp;
else
tsiz = xfer;
bcopy(cp, bp, tsiz);
bp += tsiz;
xfer -= tsiz;
if (xfer > 0)
cp += tsiz;
}
-Matt
Matthew Dillon
<[EMAIL PROTECTED]>
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message