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

Reply via email to