Annotation of 43BSDReno/sys/nfs/nfs_subs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Rick Macklem at The University of Guelph.
                      7:  *
                      8:  * Redistribution is only permitted until one year after the first shipment
                      9:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                     10:  * binary forms are permitted provided that: (1) source distributions retain
                     11:  * this entire copyright notice and comment, and (2) distributions including
                     12:  * binaries display the following acknowledgement:  This product includes
                     13:  * software developed by the University of California, Berkeley and its
                     14:  * contributors'' in the documentation or other materials provided with the
                     15:  * distribution and in all advertising materials mentioning features or use
                     16:  * of this software.  Neither the name of the University nor the names of
                     17:  * its contributors may be used to endorse or promote products derived from
                     18:  * this software without specific prior written permission.
                     19:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     20:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     22:  *
                     23:  *     @(#)nfs_subs.c  7.29 (Berkeley) 7/26/90
                     24:  */
                     25: 
                     26: /*
                     27:  * These functions support the macros and help fiddle mbuf chains for
                     28:  * the nfs op functions. They do things like create the rpc header and
                     29:  * copy data between mbuf chains and uio lists.
                     30:  */
                     31: #include "param.h"
                     32: #include "user.h"
                     33: #include "proc.h"
                     34: #include "systm.h"
                     35: #include "kernel.h"
                     36: #include "mount.h"
                     37: #include "file.h"
                     38: #include "vnode.h"
                     39: #include "mbuf.h"
                     40: #include "errno.h"
                     41: #include "map.h"
                     42: #include "rpcv2.h"
                     43: #include "nfsv2.h"
                     44: #include "nfsnode.h"
                     45: #include "nfs.h"
                     46: #include "nfsiom.h"
                     47: #include "xdr_subs.h"
                     48: #include "nfsm_subs.h"
                     49: 
                     50: #define TRUE   1
                     51: #define        FALSE   0
                     52: 
                     53: /*
                     54:  * Data items converted to xdr at startup, since they are constant
                     55:  * This is kinda hokey, but may save a little time doing byte swaps
                     56:  */
                     57: u_long nfs_procids[NFS_NPROCS];
                     58: u_long nfs_xdrneg1;
                     59: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied,
                     60:        rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
                     61: u_long nfs_vers, nfs_prog, nfs_true, nfs_false;
                     62: /* And other global data */
                     63: static u_long *rpc_uidp = (u_long *)0;
                     64: static u_long nfs_xid = 1;
                     65: static char *rpc_unixauth;
                     66: extern long hostid;
                     67: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
                     68: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
                     69: extern struct map nfsmap[NFS_MSIZ];
                     70: extern struct nfsreq nfsreqh;
                     71: 
                     72: /* Function ret types */
                     73: static char *nfs_unixauth();
                     74: 
                     75: /*
                     76:  * Maximum number of groups passed through to NFS server.
                     77:  * According to RFC1057 it should be 16.
                     78:  * For release 3.X systems, the maximum value is 8.
                     79:  * For some other servers, the maximum value is 10.
                     80:  */
                     81: int numgrps = 8;
                     82: 
                     83: /*
                     84:  * Create the header for an rpc request packet
                     85:  * The function nfs_unixauth() creates a unix style authorization string
                     86:  * and returns a ptr to it.
                     87:  * The hsiz is the size of the rest of the nfs request header.
                     88:  * (just used to decide if a cluster is a good idea)
                     89:  * nb: Note that the prog, vers and procid args are already in xdr byte order
                     90:  */
                     91: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid)
                     92:        u_long prog;
                     93:        u_long vers;
                     94:        u_long procid;
                     95:        struct ucred *cred;
                     96:        int hsiz;
                     97:        caddr_t *bpos;
                     98:        struct mbuf **mb;
                     99:        u_long *retxid;
                    100: {
                    101:        register struct mbuf *mreq, *m;
                    102:        register u_long *p;
                    103:        struct mbuf *m1;
                    104:        char *ap;
                    105:        int asiz, siz;
                    106: 
                    107:        NFSMGETHDR(mreq);
                    108:        asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps :
                    109:                  (cred->cr_ngroups - 1)) << 2);
                    110: #ifdef FILLINHOST
                    111:        asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED);
                    112: #else
                    113:        asiz += 9*NFSX_UNSIGNED;
                    114: #endif
                    115: 
                    116:        /* If we need a lot, alloc a cluster ?? */
                    117:        if ((asiz+hsiz+RPC_SIZ) > MHLEN)
                    118:                MCLGET(mreq, M_WAIT);
                    119:        mreq->m_len = NFSMSIZ(mreq);
                    120:        siz = mreq->m_len;
                    121:        m1 = mreq;
                    122:        /*
                    123:         * Alloc enough mbufs
                    124:         * We do it now to avoid all sleeps after the call to nfs_unixauth()
                    125:         */
                    126:        while ((asiz+RPC_SIZ) > siz) {
                    127:                MGET(m, M_WAIT, MT_DATA);
                    128:                m1->m_next = m;
                    129:                m->m_len = MLEN;
                    130:                siz += MLEN;
                    131:                m1 = m;
                    132:        }
                    133:        p = mtod(mreq, u_long *);
                    134:        *p++ = *retxid = txdr_unsigned(++nfs_xid);
                    135:        *p++ = rpc_call;
                    136:        *p++ = rpc_vers;
                    137:        *p++ = prog;
                    138:        *p++ = vers;
                    139:        *p++ = procid;
                    140: 
                    141:        /* Now we can call nfs_unixauth() and copy it in */
                    142:        ap = nfs_unixauth(cred);
                    143:        m = mreq;
                    144:        siz = m->m_len-RPC_SIZ;
                    145:        if (asiz <= siz) {
                    146:                bcopy(ap, (caddr_t)p, asiz);
                    147:                m->m_len = asiz+RPC_SIZ;
                    148:        } else {
                    149:                bcopy(ap, (caddr_t)p, siz);
                    150:                ap += siz;
                    151:                asiz -= siz;
                    152:                while (asiz > 0) {
                    153:                        siz = (asiz > MLEN) ? MLEN : asiz;
                    154:                        m = m->m_next;
                    155:                        bcopy(ap, mtod(m, caddr_t), siz);
                    156:                        m->m_len = siz;
                    157:                        asiz -= siz;
                    158:                        ap += siz;
                    159:                }
                    160:        }
                    161:        
                    162:        /* Finally, return values */
                    163:        *mb = m;
                    164:        *bpos = mtod(m, caddr_t)+m->m_len;
                    165:        return (mreq);
                    166: }
                    167: 
                    168: /*
                    169:  * copies mbuf chain to the uio scatter/gather list
                    170:  */
                    171: nfsm_mbuftouio(mrep, uiop, siz, dpos)
                    172:        struct mbuf **mrep;
                    173:        register struct uio *uiop;
                    174:        int siz;
                    175:        caddr_t *dpos;
                    176: {
                    177:        register char *mbufcp, *uiocp;
                    178:        register int xfer, left, len;
                    179:        register struct mbuf *mp;
                    180:        long uiosiz, rem;
                    181:        int error = 0;
                    182: 
                    183:        mp = *mrep;
                    184:        mbufcp = *dpos;
                    185:        len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
                    186:        rem = nfsm_rndup(siz)-siz;
                    187:        while (siz > 0) {
                    188:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
                    189:                        return (EFBIG);
                    190:                left = uiop->uio_iov->iov_len;
                    191:                uiocp = uiop->uio_iov->iov_base;
                    192:                if (left > siz)
                    193:                        left = siz;
                    194:                uiosiz = left;
                    195:                while (left > 0) {
                    196:                        while (len == 0) {
                    197:                                mp = mp->m_next;
                    198:                                if (mp == NULL)
                    199:                                        return (EBADRPC);
                    200:                                mbufcp = mtod(mp, caddr_t);
                    201:                                len = mp->m_len;
                    202:                        }
                    203:                        xfer = (left > len) ? len : left;
                    204: #ifdef notdef
                    205:                        /* Not Yet.. */
                    206:                        if (uiop->uio_iov->iov_op != NULL)
                    207:                                (*(uiop->uio_iov->iov_op))
                    208:                                (mbufcp, uiocp, xfer);
                    209:                        else
                    210: #endif
                    211:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    212:                                bcopy(mbufcp, uiocp, xfer);
                    213:                        else
                    214:                                copyout(mbufcp, uiocp, xfer);
                    215:                        left -= xfer;
                    216:                        len -= xfer;
                    217:                        mbufcp += xfer;
                    218:                        uiocp += xfer;
                    219:                        uiop->uio_offset += xfer;
                    220:                        uiop->uio_resid -= xfer;
                    221:                }
                    222:                if (uiop->uio_iov->iov_len <= siz) {
                    223:                        uiop->uio_iovcnt--;
                    224:                        uiop->uio_iov++;
                    225:                } else {
                    226:                        uiop->uio_iov->iov_base += uiosiz;
                    227:                        uiop->uio_iov->iov_len -= uiosiz;
                    228:                }
                    229:                siz -= uiosiz;
                    230:        }
                    231:        *dpos = mbufcp;
                    232:        *mrep = mp;
                    233:        if (rem > 0) {
                    234:                if (len < rem)
                    235:                        error = nfs_adv(mrep, dpos, rem, len);
                    236:                else
                    237:                        *dpos += rem;
                    238:        }
                    239:        return (error);
                    240: }
                    241: 
                    242: /*
                    243:  * copies a uio scatter/gather list to an mbuf chain...
                    244:  */
                    245: nfsm_uiotombuf(uiop, mq, siz, bpos)
                    246:        register struct uio *uiop;
                    247:        struct mbuf **mq;
                    248:        int siz;
                    249:        caddr_t *bpos;
                    250: {
                    251:        register char *uiocp;
                    252:        register struct mbuf *mp, *mp2;
                    253:        register int xfer, left, len;
                    254:        int uiosiz, clflg, rem;
                    255:        char *cp;
                    256: 
                    257:        if (siz > MLEN)         /* or should it >= MCLBYTES ?? */
                    258:                clflg = 1;
                    259:        else
                    260:                clflg = 0;
                    261:        rem = nfsm_rndup(siz)-siz;
                    262:        mp2 = *mq;
                    263:        while (siz > 0) {
                    264:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
                    265:                        return (EINVAL);
                    266:                left = uiop->uio_iov->iov_len;
                    267:                uiocp = uiop->uio_iov->iov_base;
                    268:                if (left > siz)
                    269:                        left = siz;
                    270:                uiosiz = left;
                    271:                while (left > 0) {
                    272:                        MGET(mp, M_WAIT, MT_DATA);
                    273:                        if (clflg)
                    274:                                MCLGET(mp, M_WAIT);
                    275:                        mp->m_len = NFSMSIZ(mp);
                    276:                        mp2->m_next = mp;
                    277:                        mp2 = mp;
                    278:                        xfer = (left > mp->m_len) ? mp->m_len : left;
                    279: #ifdef notdef
                    280:                        /* Not Yet.. */
                    281:                        if (uiop->uio_iov->iov_op != NULL)
                    282:                                (*(uiop->uio_iov->iov_op))
                    283:                                (uiocp, mtod(mp, caddr_t), xfer);
                    284:                        else
                    285: #endif
                    286:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    287:                                bcopy(uiocp, mtod(mp, caddr_t), xfer);
                    288:                        else
                    289:                                copyin(uiocp, mtod(mp, caddr_t), xfer);
                    290:                        len = mp->m_len;
                    291:                        mp->m_len = xfer;
                    292:                        left -= xfer;
                    293:                        uiocp += xfer;
                    294:                        uiop->uio_offset += xfer;
                    295:                        uiop->uio_resid -= xfer;
                    296:                }
                    297:                if (uiop->uio_iov->iov_len <= siz) {
                    298:                        uiop->uio_iovcnt--;
                    299:                        uiop->uio_iov++;
                    300:                } else {
                    301:                        uiop->uio_iov->iov_base += uiosiz;
                    302:                        uiop->uio_iov->iov_len -= uiosiz;
                    303:                }
                    304:                siz -= uiosiz;
                    305:        }
                    306:        if (rem > 0) {
                    307:                if (rem > (len-mp->m_len)) {
                    308:                        MGET(mp, M_WAIT, MT_DATA);
                    309:                        mp->m_len = 0;
                    310:                        mp2->m_next = mp;
                    311:                }
                    312:                cp = mtod(mp, caddr_t)+mp->m_len;
                    313:                for (left = 0; left < rem; left++)
                    314:                        *cp++ = '\0';
                    315:                mp->m_len += rem;
                    316:                *bpos = cp;
                    317:        } else
                    318:                *bpos = mtod(mp, caddr_t)+mp->m_len;
                    319:        *mq = mp;
                    320:        return (0);
                    321: }
                    322: 
                    323: /*
                    324:  * Help break down an mbuf chain by setting the first siz bytes contiguous
                    325:  * pointed to by returned val.
                    326:  * If Updateflg == True we can overwrite the first part of the mbuf data
                    327:  * This is used by the macros nfsm_disect and nfsm_disecton for tough
                    328:  * cases. (The macros use the vars. dpos and dpos2)
                    329:  */
                    330: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2)
                    331:        struct mbuf **mdp;
                    332:        caddr_t *dposp;
                    333:        int siz;
                    334:        int left;
                    335:        int updateflg;
                    336:        caddr_t *cp2;
                    337: {
                    338:        register struct mbuf *mp, *mp2;
                    339:        register int siz2, xfer;
                    340:        register caddr_t p;
                    341: 
                    342:        mp = *mdp;
                    343:        while (left == 0) {
                    344:                *mdp = mp = mp->m_next;
                    345:                if (mp == NULL)
                    346:                        return (EBADRPC);
                    347:                left = mp->m_len;
                    348:                *dposp = mtod(mp, caddr_t);
                    349:        }
                    350:        if (left >= siz) {
                    351:                *cp2 = *dposp;
                    352:                *dposp += siz;
                    353:        } else if (mp->m_next == NULL) {
                    354:                return (EBADRPC);
                    355:        } else if (siz > MHLEN) {
                    356:                panic("nfs S too big");
                    357:        } else {
                    358:                /* Iff update, you can overwrite, else must alloc new mbuf */
                    359:                if (updateflg) {
                    360:                        NFSMINOFF(mp);
                    361:                } else {
                    362:                        MGET(mp2, M_WAIT, MT_DATA);
                    363:                        mp2->m_next = mp->m_next;
                    364:                        mp->m_next = mp2;
                    365:                        mp->m_len -= left;
                    366:                        mp = mp2;
                    367:                }
                    368:                *cp2 = p = mtod(mp, caddr_t);
                    369:                bcopy(*dposp, p, left);         /* Copy what was left */
                    370:                siz2 = siz-left;
                    371:                p += left;
                    372:                mp2 = mp->m_next;
                    373:                /* Loop around copying up the siz2 bytes */
                    374:                while (siz2 > 0) {
                    375:                        if (mp2 == NULL)
                    376:                                return (EBADRPC);
                    377:                        xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
                    378:                        if (xfer > 0) {
                    379:                                bcopy(mtod(mp2, caddr_t), p, xfer);
                    380:                                NFSMADV(mp2, xfer);
                    381:                                mp2->m_len -= xfer;
                    382:                                p += xfer;
                    383:                                siz2 -= xfer;
                    384:                        }
                    385:                        if (siz2 > 0)
                    386:                                mp2 = mp2->m_next;
                    387:                }
                    388:                mp->m_len = siz;
                    389:                *mdp = mp2;
                    390:                *dposp = mtod(mp2, caddr_t);
                    391:        }
                    392:        return (0);
                    393: }
                    394: 
                    395: /*
                    396:  * Advance the position in the mbuf chain.
                    397:  */
                    398: nfs_adv(mdp, dposp, offs, left)
                    399:        struct mbuf **mdp;
                    400:        caddr_t *dposp;
                    401:        int offs;
                    402:        int left;
                    403: {
                    404:        register struct mbuf *m;
                    405:        register int s;
                    406: 
                    407:        m = *mdp;
                    408:        s = left;
                    409:        while (s < offs) {
                    410:                offs -= s;
                    411:                m = m->m_next;
                    412:                if (m == NULL)
                    413:                        return (EBADRPC);
                    414:                s = m->m_len;
                    415:        }
                    416:        *mdp = m;
                    417:        *dposp = mtod(m, caddr_t)+offs;
                    418:        return (0);
                    419: }
                    420: 
                    421: /*
                    422:  * Copy a string into mbufs for the hard cases...
                    423:  */
                    424: nfsm_strtmbuf(mb, bpos, cp, siz)
                    425:        struct mbuf **mb;
                    426:        char **bpos;
                    427:        char *cp;
                    428:        long siz;
                    429: {
                    430:        register struct mbuf *m1, *m2;
                    431:        long left, xfer, len, tlen;
                    432:        u_long *p;
                    433:        int putsize;
                    434: 
                    435:        putsize = 1;
                    436:        m2 = *mb;
                    437:        left = NFSMSIZ(m2)-m2->m_len;
                    438:        if (left > 0) {
                    439:                p = ((u_long *)(*bpos));
                    440:                *p++ = txdr_unsigned(siz);
                    441:                putsize = 0;
                    442:                left -= NFSX_UNSIGNED;
                    443:                m2->m_len += NFSX_UNSIGNED;
                    444:                if (left > 0) {
                    445:                        bcopy(cp, (caddr_t) p, left);
                    446:                        siz -= left;
                    447:                        cp += left;
                    448:                        m2->m_len += left;
                    449:                        left = 0;
                    450:                }
                    451:        }
                    452:        /* Loop arround adding mbufs */
                    453:        while (siz > 0) {
                    454:                MGET(m1, M_WAIT, MT_DATA);
                    455:                if (siz > MLEN)
                    456:                        MCLGET(m1, M_WAIT);
                    457:                m1->m_len = NFSMSIZ(m1);
                    458:                m2->m_next = m1;
                    459:                m2 = m1;
                    460:                p = mtod(m1, u_long *);
                    461:                tlen = 0;
                    462:                if (putsize) {
                    463:                        *p++ = txdr_unsigned(siz);
                    464:                        m1->m_len -= NFSX_UNSIGNED;
                    465:                        tlen = NFSX_UNSIGNED;
                    466:                        putsize = 0;
                    467:                }
                    468:                if (siz < m1->m_len) {
                    469:                        len = nfsm_rndup(siz);
                    470:                        xfer = siz;
                    471:                        if (xfer < len)
                    472:                                *(p+(xfer>>2)) = 0;
                    473:                } else {
                    474:                        xfer = len = m1->m_len;
                    475:                }
                    476:                bcopy(cp, (caddr_t) p, xfer);
                    477:                m1->m_len = len+tlen;
                    478:                siz -= xfer;
                    479:                cp += xfer;
                    480:        }
                    481:        *mb = m1;
                    482:        *bpos = mtod(m1, caddr_t)+m1->m_len;
                    483:        return (0);
                    484: }
                    485: 
                    486: /*
                    487:  * Called once to initialize data structures...
                    488:  */
                    489: nfs_init()
                    490: {
                    491:        register int i;
                    492: 
                    493:        rpc_vers = txdr_unsigned(RPC_VER2);
                    494:        rpc_call = txdr_unsigned(RPC_CALL);
                    495:        rpc_reply = txdr_unsigned(RPC_REPLY);
                    496:        rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
                    497:        rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
                    498:        rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
                    499:        rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
                    500:        nfs_vers = txdr_unsigned(NFS_VER2);
                    501:        nfs_prog = txdr_unsigned(NFS_PROG);
                    502:        nfs_true = txdr_unsigned(TRUE);
                    503:        nfs_false = txdr_unsigned(FALSE);
                    504:        /* Loop thru nfs procids */
                    505:        for (i = 0; i < NFS_NPROCS; i++)
                    506:                nfs_procids[i] = txdr_unsigned(i);
                    507:        /* Ensure async daemons disabled */
                    508:        for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
                    509:                nfs_iodwant[i] = (struct proc *)0;
                    510:        nfs_xdrneg1 = txdr_unsigned(-1);
                    511:        nfs_nhinit();                   /* Init the nfsnode table */
                    512:        nfsrv_initcache();              /* Init the server request cache */
                    513:        rminit(nfsmap, (long)NFS_MAPREG, (long)1, "nfs mapreg", NFS_MSIZ);
                    514: 
                    515:        /*
                    516:         * Initialize reply list and start timer
                    517:         */
                    518:        nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
                    519:        nfs_timer();
                    520: }
                    521: 
                    522: /*
                    523:  * Fill in the rest of the rpc_unixauth and return it
                    524:  */
                    525: static char *nfs_unixauth(cr)
                    526:        register struct ucred *cr;
                    527: {
                    528:        register u_long *p;
                    529:        register int i;
                    530:        int ngr;
                    531: 
                    532:        /* Maybe someday there should be a cache of AUTH_SHORT's */
                    533:        if ((p = rpc_uidp) == NULL) {
                    534: #ifdef FILLINHOST
                    535:                i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
                    536: #else
                    537:                i = 25*NFSX_UNSIGNED;
                    538: #endif
                    539:                MALLOC(p, u_long *, i, M_TEMP, M_WAITOK);
                    540:                bzero((caddr_t)p, i);
                    541:                rpc_unixauth = (caddr_t)p;
                    542:                *p++ = txdr_unsigned(RPCAUTH_UNIX);
                    543:                p++;    /* Fill in size later */
                    544:                *p++ = hostid;
                    545: #ifdef FILLINHOST
                    546:                *p++ = txdr_unsigned(hostnamelen);
                    547:                i = nfsm_rndup(hostnamelen);
                    548:                bcopy(hostname, (caddr_t)p, hostnamelen);
                    549:                p += (i>>2);
                    550: #else
                    551:                *p++ = 0;
                    552: #endif
                    553:                rpc_uidp = p;
                    554:        }
                    555:        *p++ = txdr_unsigned(cr->cr_uid);
                    556:        *p++ = txdr_unsigned(cr->cr_groups[0]);
                    557:        ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
                    558:        *p++ = txdr_unsigned(ngr);
                    559:        for (i = 1; i <= ngr; i++)
                    560:                *p++ = txdr_unsigned(cr->cr_groups[i]);
                    561:        /* And add the AUTH_NULL */
                    562:        *p++ = 0;
                    563:        *p = 0;
                    564:        i = (((caddr_t)p)-rpc_unixauth)-12;
                    565:        p = (u_long *)(rpc_unixauth+4);
                    566:        *p = txdr_unsigned(i);
                    567:        return (rpc_unixauth);
                    568: }
                    569: 
                    570: /*
                    571:  * Attribute cache routines.
                    572:  * nfs_loadattrcache() - loads or updates the cache contents from attributes
                    573:  *     that are on the mbuf list
                    574:  * nfs_getattrcache() - returns valid attributes if found in cache, returns
                    575:  *     error otherwise
                    576:  */
                    577: 
                    578: /*
                    579:  * Load the attribute cache (that lives in the nfsnode entry) with
                    580:  * the values on the mbuf list and
                    581:  * Iff vap not NULL
                    582:  *    copy the attributes to *vaper
                    583:  */
                    584: nfs_loadattrcache(vpp, mdp, dposp, vaper)
                    585:        struct vnode **vpp;
                    586:        struct mbuf **mdp;
                    587:        caddr_t *dposp;
                    588:        struct vattr *vaper;
                    589: {
                    590:        register struct vnode *vp = *vpp;
                    591:        register struct vattr *vap;
                    592:        register struct nfsv2_fattr *fp;
                    593:        extern struct vnodeops spec_nfsv2nodeops;
                    594:        register struct nfsnode *np;
                    595:        register long t1;
                    596:        caddr_t dpos, cp2;
                    597:        int error = 0;
                    598:        struct mbuf *md;
                    599:        enum vtype type;
                    600:        long rdev;
                    601:        struct timeval mtime;
                    602:        struct vnode *nvp;
                    603: 
                    604:        md = *mdp;
                    605:        dpos = *dposp;
                    606:        t1 = (mtod(md, caddr_t)+md->m_len)-dpos;
                    607:        if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
                    608:                return (error);
                    609:        fp = (struct nfsv2_fattr *)cp2;
                    610:        type = nfstov_type(fp->fa_type);
                    611:        rdev = fxdr_unsigned(long, fp->fa_rdev);
                    612:        fxdr_time(&fp->fa_mtime, &mtime);
                    613:        /*
                    614:         * If v_type == VNON it is a new node, so fill in the v_type,
                    615:         * n_mtime fields. Check to see if it represents a special 
                    616:         * device, and if so, check for a possible alias. Once the
                    617:         * correct vnode has been obtained, fill in the rest of the
                    618:         * information.
                    619:         */
                    620:        np = VTONFS(vp);
                    621:        if (vp->v_type == VNON) {
                    622:                if (type == VCHR && rdev == 0xffffffff)
                    623:                        vp->v_type = type = VFIFO;
                    624:                else
                    625:                        vp->v_type = type;
                    626:                if (vp->v_type == VFIFO) {
                    627: #ifdef FIFO
                    628:                        extern struct vnodeops fifo_nfsv2nodeops;
                    629:                        vp->v_op = &fifo_nfsv2nodeops;
                    630: #else
                    631:                        return (EOPNOTSUPP);
                    632: #endif /* FIFO */
                    633:                }
                    634:                if (vp->v_type == VCHR || vp->v_type == VBLK) {
                    635:                        vp->v_op = &spec_nfsv2nodeops;
                    636:                        if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {
                    637:                                /*
                    638:                                 * Reinitialize aliased node.
                    639:                                 */
                    640:                                np = VTONFS(nvp);
                    641:                                np->n_vnode = nvp;
                    642:                                np->n_flag = 0;
                    643:                                nfs_lock(nvp);
                    644:                                bcopy((caddr_t)&VTONFS(vp)->n_fh,
                    645:                                        (caddr_t)&np->n_fh, NFSX_FH);
                    646:                                insque(np, nfs_hash(&np->n_fh));
                    647:                                np->n_attrstamp = 0;
                    648:                                np->n_sillyrename = (struct sillyrename *)0;
                    649:                                /*
                    650:                                 * Discard unneeded vnode and update actual one
                    651:                                 */
                    652:                                vput(vp);
                    653:                                *vpp = nvp;
                    654:                        }
                    655:                }
                    656:                np->n_mtime = mtime.tv_sec;
                    657:        }
                    658:        vap = &np->n_vattr;
                    659:        vap->va_type = type;
                    660:        vap->va_mode = nfstov_mode(fp->fa_mode);
                    661:        vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
                    662:        vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
                    663:        vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
                    664:        vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
                    665:        if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size)
                    666:                np->n_size = vap->va_size;
                    667:        vap->va_size_rsv = 0;
                    668:        vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
                    669:        vap->va_rdev = (dev_t)rdev;
                    670:        vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
                    671:        vap->va_bytes_rsv = 0;
                    672:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
                    673:        vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
                    674:        vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
                    675:        vap->va_atime.tv_usec = 0;
                    676:        vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
                    677:        vap->va_mtime = mtime;
                    678:        vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
                    679:        vap->va_ctime.tv_usec = 0;
                    680:        vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
                    681:        np->n_attrstamp = time.tv_sec;
                    682:        *dposp = dpos;
                    683:        *mdp = md;
                    684:        if (vaper != NULL) {
                    685:                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
                    686:                if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
                    687:                        vaper->va_size = np->n_size;
                    688:        }
                    689:        return (0);
                    690: }
                    691: 
                    692: /*
                    693:  * Check the time stamp
                    694:  * If the cache is valid, copy contents to *vap and return 0
                    695:  * otherwise return an error
                    696:  */
                    697: nfs_getattrcache(vp, vap)
                    698:        register struct vnode *vp;
                    699:        struct vattr *vap;
                    700: {
                    701:        register struct nfsnode *np;
                    702: 
                    703:        np = VTONFS(vp);
                    704:        if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) {
                    705:                nfsstats.attrcache_hits++;
                    706:                bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
                    707:                if ((np->n_flag & NMODIFIED) == 0)
                    708:                        np->n_size = vap->va_size;
                    709:                else if (np->n_size > vap->va_size)
                    710:                        vap->va_size = np->n_size;
                    711:                return (0);
                    712:        } else {
                    713:                nfsstats.attrcache_misses++;
                    714:                return (ENOENT);
                    715:        }
                    716: }
                    717: 
                    718: /*
                    719:  * Set up nameidata for a namei() call and do it
                    720:  */
                    721: nfs_namei(ndp, fhp, len, mdp, dposp)
                    722:        register struct nameidata *ndp;
                    723:        fhandle_t *fhp;
                    724:        int len;
                    725:        struct mbuf **mdp;
                    726:        caddr_t *dposp;
                    727: {
                    728:        register int i, rem;
                    729:        register struct mbuf *md;
                    730:        register char *cp;
                    731:        struct vnode *dp;
                    732:        int flag;
                    733:        int error;
                    734: 
                    735:        if ((ndp->ni_nameiop & HASBUF) == 0) {
                    736:                flag = ndp->ni_nameiop & OPFLAG;
                    737:                /*
                    738:                 * Copy the name from the mbuf list to the d_name field of ndp
                    739:                 * and set the various ndp fields appropriately.
                    740:                 */
                    741:                cp = *dposp;
                    742:                md = *mdp;
                    743:                rem = mtod(md, caddr_t)+md->m_len-cp;
                    744:                ndp->ni_hash = 0;
                    745:                for (i = 0; i < len;) {
                    746:                        while (rem == 0) {
                    747:                                md = md->m_next;
                    748:                                if (md == NULL)
                    749:                                        return (EBADRPC);
                    750:                                cp = mtod(md, caddr_t);
                    751:                                rem = md->m_len;
                    752:                        }
                    753:                        if (*cp == '\0' || *cp == '/')
                    754:                                return (EINVAL);
                    755:                        if (*cp & 0200)
                    756:                                if ((*cp&0377) == ('/'|0200) || flag != DELETE)
                    757:                                        return (EINVAL);
                    758:                        ndp->ni_dent.d_name[i++] = *cp;
                    759:                        ndp->ni_hash += (unsigned char)*cp * i;
                    760:                        cp++;
                    761:                        rem--;
                    762:                }
                    763:                *mdp = md;
                    764:                *dposp = cp;
                    765:                len = nfsm_rndup(len)-len;
                    766:                if (len > 0) {
                    767:                        if (rem < len) {
                    768:                                if (error = nfs_adv(mdp, dposp, len, rem))
                    769:                                        return (error);
                    770:                        } else
                    771:                                *dposp += len;
                    772:                }
                    773:        } else
                    774:                i = len;
                    775:        ndp->ni_namelen = i;
                    776:        ndp->ni_dent.d_namlen = i;
                    777:        ndp->ni_dent.d_name[i] = '\0';
                    778:        ndp->ni_segflg = UIO_SYSSPACE;
                    779:        ndp->ni_pathlen = 1;
                    780:        ndp->ni_pnbuf = ndp->ni_dirp = ndp->ni_ptr = &ndp->ni_dent.d_name[0];
                    781:        ndp->ni_next = &ndp->ni_dent.d_name[i];
                    782:        ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE | HASBUF);
                    783: 
                    784:        if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
                    785:                return (error);
                    786:        if (dp->v_type != VDIR) {
                    787:                vrele(dp);
                    788:                return (ENOTDIR);
                    789:        }
                    790:        /*
                    791:         * Must set current directory here to avoid confusion in namei()
                    792:         * called from rename()
                    793:         */
                    794:        ndp->ni_cdir = dp;
                    795:        ndp->ni_rdir = NULLVP;
                    796: 
                    797:        /*
                    798:         * And call namei() to do the real work
                    799:         */
                    800:        error = namei(ndp);
                    801:        vrele(dp);
                    802:        return (error);
                    803: }
                    804: 
                    805: /*
                    806:  * A fiddled version of m_adj() that ensures null fill to a long
                    807:  * boundary and only trims off the back end
                    808:  */
                    809: nfsm_adj(mp, len, nul)
                    810:        struct mbuf *mp;
                    811:        register int len;
                    812:        int nul;
                    813: {
                    814:        register struct mbuf *m;
                    815:        register int count, i;
                    816:        register char *cp;
                    817: 
                    818:        /*
                    819:         * Trim from tail.  Scan the mbuf chain,
                    820:         * calculating its length and finding the last mbuf.
                    821:         * If the adjustment only affects this mbuf, then just
                    822:         * adjust and return.  Otherwise, rescan and truncate
                    823:         * after the remaining size.
                    824:         */
                    825:        count = 0;
                    826:        m = mp;
                    827:        for (;;) {
                    828:                count += m->m_len;
                    829:                if (m->m_next == (struct mbuf *)0)
                    830:                        break;
                    831:                m = m->m_next;
                    832:        }
                    833:        if (m->m_len > len) {
                    834:                m->m_len -= len;
                    835:                if (nul > 0) {
                    836:                        cp = mtod(m, caddr_t)+m->m_len-nul;
                    837:                        for (i = 0; i < nul; i++)
                    838:                                *cp++ = '\0';
                    839:                }
                    840:                return;
                    841:        }
                    842:        count -= len;
                    843:        if (count < 0)
                    844:                count = 0;
                    845:        /*
                    846:         * Correct length for chain is "count".
                    847:         * Find the mbuf with last data, adjust its length,
                    848:         * and toss data from remaining mbufs on chain.
                    849:         */
                    850:        for (m = mp; m; m = m->m_next) {
                    851:                if (m->m_len >= count) {
                    852:                        m->m_len = count;
                    853:                        if (nul > 0) {
                    854:                                cp = mtod(m, caddr_t)+m->m_len-nul;
                    855:                                for (i = 0; i < nul; i++)
                    856:                                        *cp++ = '\0';
                    857:                        }
                    858:                        break;
                    859:                }
                    860:                count -= m->m_len;
                    861:        }
                    862:        while (m = m->m_next)
                    863:                m->m_len = 0;
                    864: }
                    865: 
                    866: /*
                    867:  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
                    868:  *     - look up fsid in mount list (if not found ret error)
                    869:  *     - check that it is exported
                    870:  *     - get vp by calling VFS_FHTOVP() macro
                    871:  *     - if not lockflag unlock it with VOP_UNLOCK()
                    872:  *     - if cred->cr_uid == 0 set it to m_exroot
                    873:  */
                    874: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
                    875:        fhandle_t *fhp;
                    876:        int lockflag;
                    877:        struct vnode **vpp;
                    878:        struct ucred *cred;
                    879: {
                    880:        register struct mount *mp;
                    881: 
                    882:        if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
                    883:                return (ESTALE);
                    884:        if ((mp->mnt_flag & MNT_EXPORTED) == 0)
                    885:                return (EACCES);
                    886:        if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
                    887:                return (ESTALE);
                    888:        if (cred->cr_uid == 0)
                    889:                cred->cr_uid = mp->mnt_exroot;
                    890:        if (!lockflag)
                    891:                VOP_UNLOCK(*vpp);
                    892:        return (0);
                    893: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.