[BACK]Return to nfs_serv.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / nfs

Annotation of src/sys/nfs/nfs_serv.c, Revision 1.81

1.81    ! agc         1: /*     $NetBSD: nfs_serv.c,v 1.80 2003/07/09 21:16:12 bouyer Exp $     */
1.16      cgd         2:
1.1       cgd         3: /*
1.15      mycroft     4:  * Copyright (c) 1989, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Rick Macklem at The University of Guelph.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
1.81    ! agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
1.42      fvdl       34:  *     @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
1.1       cgd        35:  */
                     36:
                     37: /*
1.23      fvdl       38:  * nfs version 2 and 3 server calls to vnode ops
1.1       cgd        39:  * - these routines generally have 3 phases
                     40:  *   1 - break down and validate rpc request in mbuf list
                     41:  *   2 - do the vnode ops for the request
                     42:  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
                     43:  *   3 - build the rpc reply in an mbuf list
                     44:  *   nb:
                     45:  *     - do not mix the phases, since the nfsm_?? macros can return failures
                     46:  *       on a bad rpc or similar and do not do any vrele() or vput()'s
                     47:  *
                     48:  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
                     49:  *     error number iff error != 0 whereas
                     50:  *     returning an error from the server function implies a fatal error
                     51:  *     such as a badly constructed rpc request that should be dropped without
                     52:  *     a reply.
1.23      fvdl       53:  *     For Version 3, nfsm_reply() does not return for the error case, since
                     54:  *     most version 3 rpcs return more than the status for error cases.
1.1       cgd        55:  */
1.62      lukem      56:
                     57: #include <sys/cdefs.h>
1.81    ! agc        58: __KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.80 2003/07/09 21:16:12 bouyer Exp $");
1.41      mrg        59:
1.10      mycroft    60: #include <sys/param.h>
                     61: #include <sys/systm.h>
                     62: #include <sys/proc.h>
                     63: #include <sys/file.h>
                     64: #include <sys/namei.h>
                     65: #include <sys/vnode.h>
                     66: #include <sys/mount.h>
1.23      fvdl       67: #include <sys/socket.h>
                     68: #include <sys/socketvar.h>
1.10      mycroft    69: #include <sys/mbuf.h>
1.15      mycroft    70: #include <sys/dirent.h>
                     71: #include <sys/stat.h>
1.23      fvdl       72: #include <sys/kernel.h>
                     73: #include <ufs/ufs/dir.h>
1.1       cgd        74:
1.72      yamt       75: #include <uvm/uvm.h>
1.40      mrg        76:
1.23      fvdl       77: #include <nfs/nfsproto.h>
1.15      mycroft    78: #include <nfs/rpcv2.h>
1.10      mycroft    79: #include <nfs/nfs.h>
                     80: #include <nfs/xdr_subs.h>
                     81: #include <nfs/nfsm_subs.h>
1.15      mycroft    82: #include <nfs/nqnfs.h>
1.22      christos   83: #include <nfs/nfs_var.h>
1.1       cgd        84:
                     85: /* Global vars */
1.19      cgd        86: extern u_int32_t nfs_xdrneg1;
                     87: extern u_int32_t nfs_false, nfs_true;
1.23      fvdl       88: extern enum vtype nv3tov_type[8];
                     89: extern struct nfsstats nfsstats;
1.66      matt       90: extern const nfstype nfsv2_type[9];
                     91: extern const nfstype nfsv3_type[9];
1.23      fvdl       92: int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
1.72      yamt       93: int nfsd_use_loan = 1; /* use page-loan for READ OP */
1.1       cgd        94:
1.15      mycroft    95: /*
1.23      fvdl       96:  * nfs v3 access service
1.15      mycroft    97:  */
1.22      christos   98: int
1.79      fvdl       99: nfsrv3_access(nfsd, slp, procp, mrq)
1.23      fvdl      100:        struct nfsrv_descript *nfsd;
                    101:        struct nfssvc_sock *slp;
1.79      fvdl      102:        struct proc *procp;
1.23      fvdl      103:        struct mbuf **mrq;
1.15      mycroft   104: {
1.23      fvdl      105:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    106:        struct mbuf *nam = nfsd->nd_nam;
                    107:        caddr_t dpos = nfsd->nd_dpos;
                    108:        struct ucred *cred = &nfsd->nd_cr;
1.15      mycroft   109:        struct vnode *vp;
1.23      fvdl      110:        nfsfh_t nfh;
1.15      mycroft   111:        fhandle_t *fhp;
1.54      augustss  112:        u_int32_t *tl;
                    113:        int32_t t1;
1.15      mycroft   114:        caddr_t bpos;
1.23      fvdl      115:        int error = 0, rdonly, cache = 0, getret;
1.15      mycroft   116:        char *cp2;
1.67      matt      117:        struct mbuf *mb, *mreq;
1.23      fvdl      118:        struct vattr va;
1.32      mycroft   119:        u_long inmode, testmode, outmode;
1.15      mycroft   120:        u_quad_t frev;
                    121:
                    122:        fhp = &nfh.fh_generic;
                    123:        nfsm_srvmtofh(fhp);
1.23      fvdl      124:        nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    125:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.78      thorpej   126:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      127:        if (error) {
                    128:                nfsm_reply(NFSX_UNSIGNED);
                    129:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    130:                return (0);
                    131:        }
1.32      mycroft   132:        inmode = fxdr_unsigned(u_int32_t, *tl);
                    133:        outmode = 0;
                    134:        if ((inmode & NFSV3ACCESS_READ) &&
1.79      fvdl      135:            nfsrv_access(vp, VREAD, cred, rdonly, procp, 0) == 0)
1.32      mycroft   136:                outmode |= NFSV3ACCESS_READ;
                    137:        if (vp->v_type != VDIR) {
                    138:                testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
                    139:                if (testmode &&
1.79      fvdl      140:                    nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
1.32      mycroft   141:                        outmode |= testmode;
                    142:                if ((inmode & NFSV3ACCESS_EXECUTE) &&
1.79      fvdl      143:                    nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
1.32      mycroft   144:                        outmode |= NFSV3ACCESS_EXECUTE;
                    145:        } else {
                    146:                testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
                    147:                    NFSV3ACCESS_DELETE);
                    148:                if (testmode &&
1.79      fvdl      149:                    nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
1.32      mycroft   150:                        outmode |= testmode;
                    151:                if ((inmode & NFSV3ACCESS_LOOKUP) &&
1.79      fvdl      152:                    nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
1.32      mycroft   153:                        outmode |= NFSV3ACCESS_LOOKUP;
                    154:        }
1.79      fvdl      155:        getret = VOP_GETATTR(vp, &va, cred, procp);
1.15      mycroft   156:        vput(vp);
1.23      fvdl      157:        nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
                    158:        nfsm_srvpostop_attr(getret, &va);
                    159:        nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1.32      mycroft   160:        *tl = txdr_unsigned(outmode);
1.15      mycroft   161:        nfsm_srvdone;
                    162: }
                    163:
1.1       cgd       164: /*
                    165:  * nfs getattr service
                    166:  */
1.22      christos  167: int
1.79      fvdl      168: nfsrv_getattr(nfsd, slp, procp, mrq)
1.23      fvdl      169:        struct nfsrv_descript *nfsd;
                    170:        struct nfssvc_sock *slp;
1.79      fvdl      171:        struct proc *procp;
1.23      fvdl      172:        struct mbuf **mrq;
1.1       cgd       173: {
1.23      fvdl      174:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    175:        struct mbuf *nam = nfsd->nd_nam;
                    176:        caddr_t dpos = nfsd->nd_dpos;
                    177:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  178:        struct nfs_fattr *fp;
1.1       cgd       179:        struct vattr va;
                    180:        struct vnode *vp;
1.23      fvdl      181:        nfsfh_t nfh;
1.1       cgd       182:        fhandle_t *fhp;
1.54      augustss  183:        u_int32_t *tl;
                    184:        int32_t t1;
1.1       cgd       185:        caddr_t bpos;
1.15      mycroft   186:        int error = 0, rdonly, cache;
1.1       cgd       187:        char *cp2;
1.67      matt      188:        struct mbuf *mb, *mreq;
1.15      mycroft   189:        u_quad_t frev;
1.1       cgd       190:
                    191:        fhp = &nfh.fh_generic;
                    192:        nfsm_srvmtofh(fhp);
1.23      fvdl      193:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.78      thorpej   194:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      195:        if (error) {
1.1       cgd       196:                nfsm_reply(0);
1.23      fvdl      197:                return (0);
                    198:        }
                    199:        nqsrv_getl(vp, ND_READ);
1.79      fvdl      200:        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd       201:        vput(vp);
1.23      fvdl      202:        nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
                    203:        if (error)
                    204:                return (0);
                    205:        nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
                    206:        nfsm_srvfillattr(&va, fp);
1.1       cgd       207:        nfsm_srvdone;
                    208: }
                    209:
                    210: /*
                    211:  * nfs setattr service
                    212:  */
1.22      christos  213: int
1.79      fvdl      214: nfsrv_setattr(nfsd, slp, procp, mrq)
1.23      fvdl      215:        struct nfsrv_descript *nfsd;
                    216:        struct nfssvc_sock *slp;
1.79      fvdl      217:        struct proc *procp;
1.23      fvdl      218:        struct mbuf **mrq;
1.1       cgd       219: {
1.23      fvdl      220:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    221:        struct mbuf *nam = nfsd->nd_nam;
                    222:        caddr_t dpos = nfsd->nd_dpos;
                    223:        struct ucred *cred = &nfsd->nd_cr;
                    224:        struct vattr va, preat;
1.54      augustss  225:        struct nfsv2_sattr *sp;
                    226:        struct nfs_fattr *fp;
1.1       cgd       227:        struct vnode *vp;
1.23      fvdl      228:        nfsfh_t nfh;
1.1       cgd       229:        fhandle_t *fhp;
1.54      augustss  230:        u_int32_t *tl;
                    231:        int32_t t1;
1.1       cgd       232:        caddr_t bpos;
1.23      fvdl      233:        int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
                    234:        int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
1.1       cgd       235:        char *cp2;
1.67      matt      236:        struct mbuf *mb, *mreq;
1.23      fvdl      237:        u_quad_t frev;
                    238:        struct timespec guard;
1.1       cgd       239:
                    240:        fhp = &nfh.fh_generic;
                    241:        nfsm_srvmtofh(fhp);
1.18      mycroft   242:        VATTR_NULL(&va);
1.23      fvdl      243:        if (v3) {
                    244:                nfsm_srvsattr(&va);
                    245:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    246:                gcheck = fxdr_unsigned(int, *tl);
                    247:                if (gcheck) {
                    248:                        nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                    249:                        fxdr_nfsv3time(tl, &guard);
                    250:                }
                    251:        } else {
                    252:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                    253:                /*
                    254:                 * Nah nah nah nah na nah
                    255:                 * There is a bug in the Sun client that puts 0xffff in the mode
                    256:                 * field of sattr when it should put in 0xffffffff. The u_short
                    257:                 * doesn't sign extend.
                    258:                 * --> check the low order 2 bytes for 0xffff
                    259:                 */
                    260:                if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
                    261:                        va.va_mode = nfstov_mode(sp->sa_mode);
                    262:                if (sp->sa_uid != nfs_xdrneg1)
                    263:                        va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
                    264:                if (sp->sa_gid != nfs_xdrneg1)
                    265:                        va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
                    266:                if (sp->sa_size != nfs_xdrneg1)
                    267:                        va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
                    268:                if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
1.15      mycroft   269: #ifdef notyet
1.23      fvdl      270:                        fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
1.15      mycroft   271: #else
1.20      jtc       272:                        va.va_atime.tv_sec =
1.23      fvdl      273:                                fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
1.20      jtc       274:                        va.va_atime.tv_nsec = 0;
1.15      mycroft   275: #endif
                    276:                }
1.23      fvdl      277:                if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
                    278:                        fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
                    279:
                    280:        }
                    281:
                    282:        /*
                    283:         * Now that we have all the fields, lets do it.
                    284:         */
                    285:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
1.78      thorpej   286:            (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      287:        if (error) {
                    288:                nfsm_reply(2 * NFSX_UNSIGNED);
                    289:                nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    290:                return (0);
                    291:        }
                    292:        nqsrv_getl(vp, ND_WRITE);
                    293:        if (v3) {
1.79      fvdl      294:                error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
1.23      fvdl      295:                if (!error && gcheck &&
                    296:                        (preat.va_ctime.tv_sec != guard.tv_sec ||
                    297:                         preat.va_ctime.tv_nsec != guard.tv_nsec))
                    298:                        error = NFSERR_NOT_SYNC;
                    299:                if (error) {
                    300:                        vput(vp);
                    301:                        nfsm_reply(NFSX_WCCDATA(v3));
                    302:                        nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    303:                        return (0);
                    304:                }
1.15      mycroft   305:        }
                    306:
1.1       cgd       307:        /*
1.15      mycroft   308:         * If the size is being changed write acces is required, otherwise
                    309:         * just check for a read only file system.
1.1       cgd       310:         */
1.18      mycroft   311:        if (va.va_size == ((u_quad_t)((quad_t) -1))) {
1.15      mycroft   312:                if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
                    313:                        error = EROFS;
                    314:                        goto out;
                    315:                }
                    316:        } else {
                    317:                if (vp->v_type == VDIR) {
                    318:                        error = EISDIR;
                    319:                        goto out;
1.22      christos  320:                } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
1.79      fvdl      321:                        procp, 0)) != 0)
1.15      mycroft   322:                        goto out;
1.1       cgd       323:        }
1.79      fvdl      324:        error = VOP_SETATTR(vp, &va, cred, procp);
                    325:        postat_ret = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl      326:        if (!error)
                    327:                error = postat_ret;
1.1       cgd       328: out:
                    329:        vput(vp);
1.23      fvdl      330:        nfsm_reply(NFSX_WCCORFATTR(v3));
                    331:        if (v3) {
                    332:                nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
                    333:                return (0);
                    334:        } else {
                    335:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                    336:                nfsm_srvfillattr(&va, fp);
1.15      mycroft   337:        }
1.1       cgd       338:        nfsm_srvdone;
                    339: }
                    340:
                    341: /*
                    342:  * nfs lookup rpc
                    343:  */
1.22      christos  344: int
1.79      fvdl      345: nfsrv_lookup(nfsd, slp, procp, mrq)
1.23      fvdl      346:        struct nfsrv_descript *nfsd;
                    347:        struct nfssvc_sock *slp;
1.79      fvdl      348:        struct proc *procp;
1.23      fvdl      349:        struct mbuf **mrq;
1.1       cgd       350: {
1.23      fvdl      351:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    352:        struct mbuf *nam = nfsd->nd_nam;
                    353:        caddr_t dpos = nfsd->nd_dpos;
                    354:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  355:        struct nfs_fattr *fp;
1.35      fvdl      356:        struct nameidata nd, ind, *ndp = &nd;
1.23      fvdl      357:        struct vnode *vp, *dirp;
                    358:        nfsfh_t nfh;
1.1       cgd       359:        fhandle_t *fhp;
1.54      augustss  360:        caddr_t cp;
                    361:        u_int32_t *tl;
                    362:        int32_t t1;
1.1       cgd       363:        caddr_t bpos;
1.68      yamt      364:        int error = 0, cache, dirattr_ret = 1;
                    365:        uint32_t len;
1.35      fvdl      366:        int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
1.1       cgd       367:        char *cp2;
1.67      matt      368:        struct mbuf *mb, *mreq;
1.23      fvdl      369:        struct vattr va, dirattr;
                    370:        u_quad_t frev;
1.1       cgd       371:
                    372:        fhp = &nfh.fh_generic;
                    373:        nfsm_srvmtofh(fhp);
1.23      fvdl      374:        nfsm_srvnamesiz(len);
1.35      fvdl      375:
                    376:        pubflag = nfs_ispublicfh(fhp);
                    377:
1.15      mycroft   378:        nd.ni_cnd.cn_cred = cred;
                    379:        nd.ni_cnd.cn_nameiop = LOOKUP;
                    380:        nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
1.23      fvdl      381:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl      382:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
1.35      fvdl      383:
                    384:        if (!error && pubflag) {
                    385:                if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
                    386:                        /*
                    387:                         * Setup call to lookup() to see if we can find
                    388:                         * the index file. Arguably, this doesn't belong
                    389:                         * in a kernel.. Ugh.
                    390:                         */
                    391:                        ind = nd;
1.42      fvdl      392:                        VOP_UNLOCK(nd.ni_vp, 0);
1.35      fvdl      393:                        ind.ni_pathlen = strlen(nfs_pub.np_index);
                    394:                        ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
                    395:                            nfs_pub.np_index;
                    396:                        ind.ni_startdir = nd.ni_vp;
                    397:                        VREF(ind.ni_startdir);
                    398:                        error = lookup(&ind);
                    399:                        if (!error) {
                    400:                                /*
                    401:                                 * Found an index file. Get rid of
                    402:                                 * the old references.
                    403:                                 */
                    404:                                if (dirp)
                    405:                                        vrele(dirp);
                    406:                                dirp = nd.ni_vp;
                    407:                                vrele(nd.ni_startdir);
                    408:                                ndp = &ind;
                    409:                        } else
                    410:                                error = 0;
                    411:                }
                    412:                /*
                    413:                 * If the public filehandle was used, check that this lookup
                    414:                 * didn't result in a filehandle outside the publicly exported
                    415:                 * filesystem.
                    416:                 */
                    417:
                    418:                if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
                    419:                        vput(nd.ni_vp);
                    420:                        error = EPERM;
                    421:                }
                    422:        }
                    423:
1.23      fvdl      424:        if (dirp) {
                    425:                if (v3)
1.79      fvdl      426:                        dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
                    427:                                procp);
1.23      fvdl      428:                vrele(dirp);
                    429:        }
1.35      fvdl      430:
1.23      fvdl      431:        if (error) {
                    432:                nfsm_reply(NFSX_POSTOPATTR(v3));
                    433:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    434:                return (0);
                    435:        }
1.35      fvdl      436:
                    437:        nqsrv_getl(ndp->ni_startdir, ND_READ);
                    438:        vrele(ndp->ni_startdir);
1.57      thorpej   439:        PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
1.35      fvdl      440:        vp = ndp->ni_vp;
1.44      perry     441:        memset((caddr_t)fhp, 0, sizeof(nfh));
1.1       cgd       442:        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1.23      fvdl      443:        error = VFS_VPTOFH(vp, &fhp->fh_fid);
                    444:        if (!error)
1.79      fvdl      445:                error = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl      446:        vput(vp);
                    447:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
                    448:        if (error) {
                    449:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    450:                return (0);
1.1       cgd       451:        }
1.23      fvdl      452:        nfsm_srvfhtom(fhp, v3);
                    453:        if (v3) {
                    454:                nfsm_srvpostop_attr(0, &va);
                    455:                nfsm_srvpostop_attr(dirattr_ret, &dirattr);
                    456:        } else {
                    457:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                    458:                nfsm_srvfillattr(&va, fp);
1.15      mycroft   459:        }
1.1       cgd       460:        nfsm_srvdone;
                    461: }
                    462:
                    463: /*
                    464:  * nfs readlink service
                    465:  */
1.22      christos  466: int
1.79      fvdl      467: nfsrv_readlink(nfsd, slp, procp, mrq)
1.23      fvdl      468:        struct nfsrv_descript *nfsd;
                    469:        struct nfssvc_sock *slp;
1.79      fvdl      470:        struct proc *procp;
1.23      fvdl      471:        struct mbuf **mrq;
1.1       cgd       472: {
1.23      fvdl      473:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    474:        struct mbuf *nam = nfsd->nd_nam;
                    475:        caddr_t dpos = nfsd->nd_dpos;
                    476:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd       477:        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
1.54      augustss  478:        struct iovec *ivp = iv;
                    479:        struct mbuf *mp;
                    480:        u_int32_t *tl;
                    481:        int32_t t1;
1.1       cgd       482:        caddr_t bpos;
1.76      yamt      483:        int error = 0, rdonly, cache, i, padlen, getret;
                    484:        uint32_t len;
1.23      fvdl      485:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd       486:        char *cp2;
1.67      matt      487:        struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq;
1.1       cgd       488:        struct vnode *vp;
1.23      fvdl      489:        struct vattr attr;
                    490:        nfsfh_t nfh;
1.1       cgd       491:        fhandle_t *fhp;
                    492:        struct uio io, *uiop = &io;
1.15      mycroft   493:        u_quad_t frev;
1.1       cgd       494:
                    495:        fhp = &nfh.fh_generic;
                    496:        nfsm_srvmtofh(fhp);
                    497:        len = 0;
                    498:        i = 0;
                    499:        while (len < NFS_MAXPATHLEN) {
1.67      matt      500:                mp = m_get(M_WAIT, MT_DATA);
                    501:                MCLAIM(mp, &nfs_mowner);
                    502:                m_clget(mp, M_WAIT);
1.1       cgd       503:                mp->m_len = NFSMSIZ(mp);
                    504:                if (len == 0)
                    505:                        mp3 = mp2 = mp;
                    506:                else {
                    507:                        mp2->m_next = mp;
                    508:                        mp2 = mp;
                    509:                }
                    510:                if ((len+mp->m_len) > NFS_MAXPATHLEN) {
                    511:                        mp->m_len = NFS_MAXPATHLEN-len;
                    512:                        len = NFS_MAXPATHLEN;
                    513:                } else
                    514:                        len += mp->m_len;
                    515:                ivp->iov_base = mtod(mp, caddr_t);
                    516:                ivp->iov_len = mp->m_len;
                    517:                i++;
                    518:                ivp++;
                    519:        }
                    520:        uiop->uio_iov = iv;
                    521:        uiop->uio_iovcnt = i;
                    522:        uiop->uio_offset = 0;
                    523:        uiop->uio_resid = len;
                    524:        uiop->uio_rw = UIO_READ;
                    525:        uiop->uio_segflg = UIO_SYSSPACE;
1.79      fvdl      526:        uiop->uio_procp = (struct proc *)0;
1.23      fvdl      527:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej   528:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.22      christos  529:        if (error) {
1.1       cgd       530:                m_freem(mp3);
1.23      fvdl      531:                nfsm_reply(2 * NFSX_UNSIGNED);
                    532:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    533:                return (0);
1.1       cgd       534:        }
                    535:        if (vp->v_type != VLNK) {
1.23      fvdl      536:                if (v3)
                    537:                        error = EINVAL;
                    538:                else
                    539:                        error = ENXIO;
1.1       cgd       540:                goto out;
                    541:        }
1.23      fvdl      542:        nqsrv_getl(vp, ND_READ);
1.1       cgd       543:        error = VOP_READLINK(vp, uiop, cred);
                    544: out:
1.79      fvdl      545:        getret = VOP_GETATTR(vp, &attr, cred, procp);
1.1       cgd       546:        vput(vp);
                    547:        if (error)
                    548:                m_freem(mp3);
1.23      fvdl      549:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
                    550:        if (v3) {
                    551:                nfsm_srvpostop_attr(getret, &attr);
                    552:                if (error)
                    553:                        return (0);
                    554:        }
1.76      yamt      555:        len -= uiop->uio_resid;
                    556:        padlen = nfsm_padlen(len);
                    557:        if (uiop->uio_resid || padlen)
                    558:                nfs_zeropad(mp3, uiop->uio_resid, padlen);
1.19      cgd       559:        nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1.1       cgd       560:        *tl = txdr_unsigned(len);
                    561:        mb->m_next = mp3;
                    562:        nfsm_srvdone;
                    563: }
                    564:
                    565: /*
1.75      yamt      566:  * XXX UBC temp limit
                    567:  * maximum number of pages we can do VOP_GETPAGES and loan-out at once.
                    568:  * should be <= MAX_READ_AHEAD in genfs_vnops.c
                    569:  */
                    570: #define        NFSD_READ_GETPAGES_CHUNK        16
                    571:
                    572: /*
1.1       cgd       573:  * nfs read service
                    574:  */
1.22      christos  575: int
1.79      fvdl      576: nfsrv_read(nfsd, slp, procp, mrq)
1.23      fvdl      577:        struct nfsrv_descript *nfsd;
                    578:        struct nfssvc_sock *slp;
1.79      fvdl      579:        struct proc *procp;
1.23      fvdl      580:        struct mbuf **mrq;
1.1       cgd       581: {
1.23      fvdl      582:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    583:        struct mbuf *nam = nfsd->nd_nam;
                    584:        caddr_t dpos = nfsd->nd_dpos;
                    585:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  586:        struct mbuf *m;
                    587:        struct nfs_fattr *fp;
                    588:        u_int32_t *tl;
                    589:        int32_t t1;
                    590:        int i;
1.1       cgd       591:        caddr_t bpos;
1.72      yamt      592:        int error = 0, rdonly, cache, getret;
1.68      yamt      593:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.76      yamt      594:        uint32_t reqlen, len, cnt, left;
                    595:        int padlen;
1.1       cgd       596:        char *cp2;
1.67      matt      597:        struct mbuf *mb, *mreq;
1.1       cgd       598:        struct vnode *vp;
1.23      fvdl      599:        nfsfh_t nfh;
1.1       cgd       600:        fhandle_t *fhp;
                    601:        struct uio io, *uiop = &io;
1.18      mycroft   602:        struct vattr va;
1.1       cgd       603:        off_t off;
1.15      mycroft   604:        u_quad_t frev;
1.1       cgd       605:
                    606:        fhp = &nfh.fh_generic;
                    607:        nfsm_srvmtofh(fhp);
1.23      fvdl      608:        if (v3) {
                    609:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair      610:                off = fxdr_hyper(tl);
1.23      fvdl      611:        } else {
1.19      cgd       612:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                    613:                off = (off_t)fxdr_unsigned(u_int32_t, *tl);
1.15      mycroft   614:        }
1.71      yamt      615:        nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
                    616:        reqlen = fxdr_unsigned(uint32_t, *tl);
                    617:        reqlen = MIN(reqlen, NFS_SRVMAXDATA(nfsd));
1.23      fvdl      618:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej   619:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      620:        if (error) {
                    621:                nfsm_reply(2 * NFSX_UNSIGNED);
                    622:                nfsm_srvpostop_attr(1, (struct vattr *)0);
                    623:                return (0);
                    624:        }
1.15      mycroft   625:        if (vp->v_type != VREG) {
1.23      fvdl      626:                if (v3)
                    627:                        error = EINVAL;
                    628:                else
                    629:                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1.1       cgd       630:        }
1.23      fvdl      631:        if (!error) {
                    632:            nqsrv_getl(vp, ND_READ);
1.79      fvdl      633:            if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
                    634:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
1.23      fvdl      635:        }
1.79      fvdl      636:        getret = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl      637:        if (!error)
                    638:                error = getret;
1.22      christos  639:        if (error) {
1.1       cgd       640:                vput(vp);
1.23      fvdl      641:                nfsm_reply(NFSX_POSTOPATTR(v3));
                    642:                nfsm_srvpostop_attr(getret, &va);
                    643:                return (0);
1.1       cgd       644:        }
1.18      mycroft   645:        if (off >= va.va_size)
1.15      mycroft   646:                cnt = 0;
1.23      fvdl      647:        else if ((off + reqlen) > va.va_size)
1.76      yamt      648:                cnt = va.va_size - off;
1.23      fvdl      649:        else
                    650:                cnt = reqlen;
                    651:        nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
                    652:        if (v3) {
                    653:                nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
                    654:                *tl++ = nfs_true;
                    655:                fp = (struct nfs_fattr *)tl;
                    656:                tl += (NFSX_V3FATTR / sizeof (u_int32_t));
                    657:        } else {
                    658:                nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
                    659:                fp = (struct nfs_fattr *)tl;
                    660:                tl += (NFSX_V2FATTR / sizeof (u_int32_t));
                    661:        }
1.15      mycroft   662:        len = left = cnt;
1.73      yamt      663:        if (cnt > 0) {
1.72      yamt      664:                if (nfsd_use_loan) {
                    665:                        struct vm_page **pgpp;
                    666:                        voff_t pgoff = trunc_page(off);
1.75      yamt      667:                        int orignpages, nleftpages;
                    668:                        vaddr_t lva, curlva;
1.72      yamt      669:
1.75      yamt      670:                        orignpages = (round_page(off + cnt) - pgoff)
1.72      yamt      671:                            >> PAGE_SHIFT;
1.75      yamt      672:                        KASSERT(orignpages <= M_EXT_MAXPAGES); /* XXX */
1.72      yamt      673:
1.75      yamt      674:                        lva = sokvaalloc(orignpages << PAGE_SHIFT, slp->ns_so);
1.72      yamt      675:                        if (lva == 0) {
                    676:                                /* fall back to VOP_READ */
                    677:                                goto loan_fail;
                    678:                        }
                    679:
                    680:                        m = m_get(M_WAIT, MT_DATA);
                    681:                        pgpp = m->m_ext.ext_pgs;
1.75      yamt      682:
                    683:                        curlva = lva;
                    684:                        nleftpages = orignpages;
                    685:                        while (nleftpages > 0) {
                    686:                                int npages = nleftpages;
                    687:                                if (npages > NFSD_READ_GETPAGES_CHUNK)
                    688:                                        npages = NFSD_READ_GETPAGES_CHUNK;
1.72      yamt      689: again:
1.75      yamt      690:                                simple_lock(&vp->v_interlock);
                    691:                                error = VOP_GETPAGES(vp, pgoff, pgpp, &npages,
                    692:                                    0, VM_PROT_READ, 0, PGO_SYNCIO);
                    693:                                if (error == EAGAIN) {
                    694:                                        tsleep(&lbolt, PVM, "nfsread", 0);
                    695:                                        goto again;
                    696:                                }
                    697:                                if (error) {
                    698:                                        uvm_unloan(m->m_ext.ext_pgs,
                    699:                                            orignpages - nleftpages,
                    700:                                            UVM_LOAN_TOPAGE);
                    701:                                        sokvafree(lva,
                    702:                                            orignpages << PAGE_SHIFT);
                    703:                                        m_free(m);
                    704:                                        goto read_error;
                    705:                                }
                    706:
                    707:                                /* loan and unbusy pages */
                    708:                                simple_lock(&vp->v_interlock);
                    709:                                for (i = 0; i < npages; i++) {
                    710:                                        if (pgpp[i]->flags & PG_RELEASED) {
                    711:                                                uvm_lock_pageq();
                    712:                                                uvm_page_unbusy(pgpp, npages);
                    713:                                                uvm_unlock_pageq();
                    714:                                                simple_unlock(&vp->v_interlock);
                    715:                                                continue;
                    716:                                        }
1.72      yamt      717:                                }
1.75      yamt      718:                                uvm_loanuobjpages(pgpp, npages);
                    719:                                simple_unlock(&vp->v_interlock);
1.72      yamt      720:
1.75      yamt      721:                                /* map pages */
                    722:                                for (i = 0; i < npages; i++) {
                    723:                                        pmap_kenter_pa(curlva,
                    724:                                            VM_PAGE_TO_PHYS(pgpp[i]),
                    725:                                            VM_PROT_READ);
                    726:                                        curlva += PAGE_SIZE;
                    727:                                }
                    728:                                nleftpages -= npages;
                    729:                                pgpp += npages;
                    730:                                pgoff += npages << PAGE_SHIFT;
1.15      mycroft   731:                        }
1.72      yamt      732:
                    733:                        lva += off & PAGE_MASK;
                    734:
                    735:                        MCLAIM(m, &nfs_mowner);
                    736:                        MEXTADD(m, (void *)lva, cnt, M_MBUF, soloanfree,
                    737:                            slp->ns_so);
                    738:                        m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
                    739:                        m->m_len = cnt;
                    740:
                    741:                        pmap_update(pmap_kernel());
                    742:                        mb->m_next = m;
                    743:                        mb = m;
                    744:                        error = 0;
                    745:                        uiop->uio_resid = 0;
                    746:                } else {
                    747:                        struct iovec *iv;
                    748:                        struct iovec *iv2;
                    749:                        struct mbuf *m2;
                    750:                        int siz;
                    751: loan_fail:
                    752:                        /*
                    753:                         * Generate the mbuf list with the uio_iov ref. to it.
                    754:                         */
                    755:                        i = 0;
                    756:                        m = m2 = mb;
                    757:                        while (left > 0) {
                    758:                                siz = min(M_TRAILINGSPACE(m), left);
                    759:                                if (siz > 0) {
                    760:                                        left -= siz;
                    761:                                        i++;
                    762:                                }
                    763:                                if (left > 0) {
                    764:                                        m = m_get(M_WAIT, MT_DATA);
                    765:                                        MCLAIM(m, &nfs_mowner);
                    766:                                        m_clget(m, M_WAIT);
                    767:                                        m->m_len = 0;
                    768:                                        m2->m_next = m;
                    769:                                        m2 = m;
                    770:                                }
                    771:                        }
                    772:                        iv = malloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
                    773:                        uiop->uio_iov = iv2 = iv;
                    774:                        m = mb;
                    775:                        left = cnt;
                    776:                        i = 0;
                    777:                        while (left > 0) {
                    778:                                if (m == NULL)
                    779:                                        panic("nfsrv_read iov");
                    780:                                siz = min(M_TRAILINGSPACE(m), left);
                    781:                                if (siz > 0) {
                    782:                                        iv->iov_base = mtod(m, caddr_t) +
                    783:                                            m->m_len;
                    784:                                        iv->iov_len = siz;
                    785:                                        m->m_len += siz;
                    786:                                        left -= siz;
                    787:                                        iv++;
                    788:                                        i++;
                    789:                                }
                    790:                                m = m->m_next;
1.23      fvdl      791:                        }
1.72      yamt      792:                        uiop->uio_iovcnt = i;
                    793:                        uiop->uio_offset = off;
                    794:                        uiop->uio_resid = cnt;
                    795:                        uiop->uio_rw = UIO_READ;
                    796:                        uiop->uio_segflg = UIO_SYSSPACE;
                    797:                        error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
                    798:                        off = uiop->uio_offset;
                    799:                        free((caddr_t)iv2, M_TEMP);
1.23      fvdl      800:                }
1.72      yamt      801: read_error:
1.79      fvdl      802:                if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
1.23      fvdl      803:                        if (!error)
                    804:                                error = getret;
1.15      mycroft   805:                        m_freem(mreq);
                    806:                        vput(vp);
1.23      fvdl      807:                        nfsm_reply(NFSX_POSTOPATTR(v3));
                    808:                        nfsm_srvpostop_attr(getret, &va);
                    809:                        return (0);
1.15      mycroft   810:                }
1.72      yamt      811:        } else {
1.15      mycroft   812:                uiop->uio_resid = 0;
1.72      yamt      813:        }
1.1       cgd       814:        vput(vp);
1.23      fvdl      815:        nfsm_srvfillattr(&va, fp);
1.1       cgd       816:        len -= uiop->uio_resid;
1.76      yamt      817:        padlen = nfsm_padlen(len);
                    818:        if (uiop->uio_resid || padlen)
                    819:                nfs_zeropad(mb, uiop->uio_resid, padlen);
1.23      fvdl      820:        if (v3) {
                    821:                *tl++ = txdr_unsigned(len);
                    822:                if (len < reqlen)
                    823:                        *tl++ = nfs_true;
                    824:                else
                    825:                        *tl++ = nfs_false;
                    826:        }
1.1       cgd       827:        *tl = txdr_unsigned(len);
                    828:        nfsm_srvdone;
                    829: }
                    830:
                    831: /*
                    832:  * nfs write service
                    833:  */
1.22      christos  834: int
1.79      fvdl      835: nfsrv_write(nfsd, slp, procp, mrq)
1.23      fvdl      836:        struct nfsrv_descript *nfsd;
                    837:        struct nfssvc_sock *slp;
1.79      fvdl      838:        struct proc *procp;
1.23      fvdl      839:        struct mbuf **mrq;
1.1       cgd       840: {
1.23      fvdl      841:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                    842:        struct mbuf *nam = nfsd->nd_nam;
                    843:        caddr_t dpos = nfsd->nd_dpos;
                    844:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss  845:        struct iovec *ivp;
                    846:        int i, cnt;
                    847:        struct mbuf *mp;
                    848:        struct nfs_fattr *fp;
1.23      fvdl      849:        struct iovec *iv;
                    850:        struct vattr va, forat;
1.54      augustss  851:        u_int32_t *tl;
                    852:        int32_t t1;
1.1       cgd       853:        caddr_t bpos;
1.23      fvdl      854:        int error = 0, rdonly, cache, len, forat_ret = 1;
                    855:        int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
                    856:        int stable = NFSV3WRITE_FILESYNC;
                    857:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd       858:        char *cp2;
1.67      matt      859:        struct mbuf *mb, *mreq;
1.1       cgd       860:        struct vnode *vp;
1.23      fvdl      861:        nfsfh_t nfh;
1.1       cgd       862:        fhandle_t *fhp;
                    863:        struct uio io, *uiop = &io;
                    864:        off_t off;
1.15      mycroft   865:        u_quad_t frev;
1.1       cgd       866:
1.23      fvdl      867:        if (mrep == NULL) {
                    868:                *mrq = NULL;
                    869:                return (0);
                    870:        }
1.1       cgd       871:        fhp = &nfh.fh_generic;
                    872:        nfsm_srvmtofh(fhp);
1.23      fvdl      873:        if (v3) {
                    874:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair      875:                off = fxdr_hyper(tl);
1.23      fvdl      876:                tl += 3;
                    877:                stable = fxdr_unsigned(int, *tl++);
                    878:        } else {
                    879:                nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.19      cgd       880:                off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1.15      mycroft   881:                tl += 2;
                    882:        }
1.23      fvdl      883:        retlen = len = fxdr_unsigned(int32_t, *tl);
                    884:        cnt = i = 0;
                    885:
                    886:        /*
                    887:         * For NFS Version 2, it is not obvious what a write of zero length
                    888:         * should do, but I might as well be consistent with Version 3,
                    889:         * which is to return ok so long as there are no permission problems.
                    890:         */
                    891:        if (len > 0) {
1.74      yamt      892:                zeroing = 1;
                    893:                mp = mrep;
                    894:                while (mp) {
                    895:                        if (mp == md) {
                    896:                                zeroing = 0;
                    897:                                adjust = dpos - mtod(mp, caddr_t);
                    898:                                mp->m_len -= adjust;
                    899:                                if (mp->m_len > 0 && adjust > 0)
                    900:                                        NFSMADV(mp, adjust);
1.23      fvdl      901:                        }
1.74      yamt      902:                        if (zeroing)
                    903:                                mp->m_len = 0;
                    904:                        else if (mp->m_len > 0) {
                    905:                                i += mp->m_len;
                    906:                                if (i > len) {
                    907:                                        mp->m_len -= (i - len);
                    908:                                        zeroing = 1;
                    909:                                }
                    910:                                if (mp->m_len > 0)
                    911:                                        cnt++;
                    912:                        }
                    913:                        mp = mp->m_next;
1.23      fvdl      914:                }
                    915:        }
                    916:        if (len > NFS_MAXDATA || len < 0 || i < len) {
                    917:                error = EIO;
                    918:                nfsm_reply(2 * NFSX_UNSIGNED);
                    919:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    920:                return (0);
1.1       cgd       921:        }
1.23      fvdl      922:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej   923:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl      924:        if (error) {
                    925:                nfsm_reply(2 * NFSX_UNSIGNED);
                    926:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    927:                return (0);
1.1       cgd       928:        }
1.23      fvdl      929:        if (v3)
1.79      fvdl      930:                forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
1.15      mycroft   931:        if (vp->v_type != VREG) {
1.23      fvdl      932:                if (v3)
                    933:                        error = EINVAL;
                    934:                else
                    935:                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
                    936:        }
                    937:        if (!error) {
                    938:                nqsrv_getl(vp, ND_WRITE);
1.79      fvdl      939:                error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1.15      mycroft   940:        }
1.22      christos  941:        if (error) {
1.1       cgd       942:                vput(vp);
1.23      fvdl      943:                nfsm_reply(NFSX_WCCDATA(v3));
                    944:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    945:                return (0);
                    946:        }
                    947:
                    948:        if (len > 0) {
1.74      yamt      949:                ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, M_WAITOK);
                    950:                uiop->uio_iov = iv = ivp;
                    951:                uiop->uio_iovcnt = cnt;
                    952:                mp = mrep;
                    953:                while (mp) {
                    954:                        if (mp->m_len > 0) {
                    955:                                ivp->iov_base = mtod(mp, caddr_t);
                    956:                                ivp->iov_len = mp->m_len;
                    957:                                ivp++;
                    958:                        }
                    959:                        mp = mp->m_next;
                    960:                }
                    961:
                    962:                /*
                    963:                 * XXX
                    964:                 * The IO_METASYNC flag indicates that all metadata (and not
                    965:                 * just enough to ensure data integrity) must be written to
                    966:                 * stable storage synchronously.
                    967:                 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
                    968:                 */
                    969:                if (stable == NFSV3WRITE_UNSTABLE)
                    970:                        ioflags = IO_NODELOCKED;
                    971:                else if (stable == NFSV3WRITE_DATASYNC)
                    972:                        ioflags = (IO_SYNC | IO_NODELOCKED);
                    973:                else
                    974:                        ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
                    975:                uiop->uio_resid = len;
                    976:                uiop->uio_rw = UIO_WRITE;
                    977:                uiop->uio_segflg = UIO_SYSSPACE;
1.79      fvdl      978:                uiop->uio_procp = (struct proc *)0;
1.74      yamt      979:                uiop->uio_offset = off;
                    980:                error = VOP_WRITE(vp, uiop, ioflags, cred);
                    981:                nfsstats.srvvop_writes++;
                    982:                free(iv, M_TEMP);
1.23      fvdl      983:        }
1.79      fvdl      984:        aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl      985:        vput(vp);
                    986:        if (!error)
                    987:                error = aftat_ret;
                    988:        nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
                    989:                2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
                    990:        if (v3) {
                    991:                nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                    992:                if (error)
                    993:                        return (0);
                    994:                nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                    995:                *tl++ = txdr_unsigned(retlen);
                    996:                if (stable == NFSV3WRITE_UNSTABLE)
                    997:                        *tl++ = txdr_unsigned(stable);
                    998:                else
                    999:                        *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
                   1000:                /*
                   1001:                 * Actually, there is no need to txdr these fields,
                   1002:                 * but it may make the values more human readable,
                   1003:                 * for debugging purposes.
                   1004:                 */
                   1005:                *tl++ = txdr_unsigned(boottime.tv_sec);
                   1006:                *tl = txdr_unsigned(boottime.tv_usec);
                   1007:        } else {
                   1008:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   1009:                nfsm_srvfillattr(&va, fp);
                   1010:        }
                   1011:        nfsm_srvdone;
                   1012: }
                   1013:
                   1014: /*
                   1015:  * NFS write service with write gathering support. Called when
                   1016:  * nfsrvw_procrastinate > 0.
                   1017:  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
                   1018:  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
                   1019:  * Jan. 1994.
                   1020:  */
                   1021: int
1.79      fvdl     1022: nfsrv_writegather(ndp, slp, procp, mrq)
1.23      fvdl     1023:        struct nfsrv_descript **ndp;
                   1024:        struct nfssvc_sock *slp;
1.79      fvdl     1025:        struct proc *procp;
1.23      fvdl     1026:        struct mbuf **mrq;
                   1027: {
1.54      augustss 1028:        struct iovec *ivp;
                   1029:        struct mbuf *mp;
                   1030:        struct nfsrv_descript *wp, *nfsd, *owp, *swp;
                   1031:        struct nfs_fattr *fp;
                   1032:        int i = 0;
1.23      fvdl     1033:        struct iovec *iov;
                   1034:        struct nfsrvw_delayhash *wpp;
                   1035:        struct ucred *cred;
                   1036:        struct vattr va, forat;
1.54      augustss 1037:        u_int32_t *tl;
                   1038:        int32_t t1;
1.23      fvdl     1039:        caddr_t bpos, dpos;
                   1040:        int error = 0, rdonly, cache, len = 0, forat_ret = 1;
                   1041:        int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
                   1042:        char *cp2;
1.67      matt     1043:        struct mbuf *mb, *mreq, *mrep, *md;
1.23      fvdl     1044:        struct vnode *vp;
                   1045:        struct uio io, *uiop = &io;
                   1046:        u_quad_t frev, cur_usec;
                   1047:
                   1048:        *mrq = NULL;
                   1049:        if (*ndp) {
                   1050:            nfsd = *ndp;
                   1051:            *ndp = NULL;
                   1052:            mrep = nfsd->nd_mrep;
                   1053:            md = nfsd->nd_md;
                   1054:            dpos = nfsd->nd_dpos;
                   1055:            cred = &nfsd->nd_cr;
                   1056:            v3 = (nfsd->nd_flag & ND_NFSV3);
                   1057:            LIST_INIT(&nfsd->nd_coalesce);
                   1058:            nfsd->nd_mreq = NULL;
                   1059:            nfsd->nd_stable = NFSV3WRITE_FILESYNC;
                   1060:            cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
                   1061:            nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
                   1062:
                   1063:            /*
                   1064:             * Now, get the write header..
                   1065:             */
                   1066:            nfsm_srvmtofh(&nfsd->nd_fh);
                   1067:            if (v3) {
                   1068:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair     1069:                nfsd->nd_off = fxdr_hyper(tl);
1.23      fvdl     1070:                tl += 3;
                   1071:                nfsd->nd_stable = fxdr_unsigned(int, *tl++);
                   1072:            } else {
                   1073:                nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                   1074:                nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
                   1075:                tl += 2;
                   1076:            }
                   1077:            len = fxdr_unsigned(int32_t, *tl);
                   1078:            nfsd->nd_len = len;
                   1079:            nfsd->nd_eoff = nfsd->nd_off + len;
                   1080:
                   1081:            /*
                   1082:             * Trim the header out of the mbuf list and trim off any trailing
                   1083:             * junk so that the mbuf list has only the write data.
                   1084:             */
                   1085:            zeroing = 1;
                   1086:            i = 0;
                   1087:            mp = mrep;
                   1088:            while (mp) {
                   1089:                if (mp == md) {
                   1090:                    zeroing = 0;
                   1091:                    adjust = dpos - mtod(mp, caddr_t);
                   1092:                    mp->m_len -= adjust;
                   1093:                    if (mp->m_len > 0 && adjust > 0)
                   1094:                        NFSMADV(mp, adjust);
                   1095:                }
                   1096:                if (zeroing)
                   1097:                    mp->m_len = 0;
                   1098:                else {
                   1099:                    i += mp->m_len;
                   1100:                    if (i > len) {
                   1101:                        mp->m_len -= (i - len);
                   1102:                        zeroing = 1;
                   1103:                    }
                   1104:                }
                   1105:                mp = mp->m_next;
                   1106:            }
                   1107:            if (len > NFS_MAXDATA || len < 0  || i < len) {
                   1108: nfsmout:
                   1109:                m_freem(mrep);
                   1110:                error = EIO;
                   1111:                nfsm_writereply(2 * NFSX_UNSIGNED, v3);
                   1112:                if (v3)
                   1113:                    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1114:                nfsd->nd_mreq = mreq;
                   1115:                nfsd->nd_mrep = NULL;
                   1116:                nfsd->nd_time = 0;
                   1117:            }
                   1118:
                   1119:            /*
                   1120:             * Add this entry to the hash and time queues.
                   1121:             */
                   1122:            s = splsoftclock();
                   1123:            owp = NULL;
1.70      yamt     1124:            wp = LIST_FIRST(&slp->ns_tq);
1.23      fvdl     1125:            while (wp && wp->nd_time < nfsd->nd_time) {
                   1126:                owp = wp;
1.70      yamt     1127:                wp = LIST_NEXT(wp, nd_tq);
1.23      fvdl     1128:            }
                   1129:            if (owp) {
                   1130:                LIST_INSERT_AFTER(owp, nfsd, nd_tq);
                   1131:            } else {
                   1132:                LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
                   1133:            }
                   1134:            if (nfsd->nd_mrep) {
                   1135:                wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
                   1136:                owp = NULL;
1.70      yamt     1137:                wp = LIST_FIRST(wpp);
1.23      fvdl     1138:                while (wp &&
1.44      perry    1139:                    memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1.23      fvdl     1140:                    owp = wp;
1.70      yamt     1141:                    wp = LIST_NEXT(wp, nd_hash);
1.23      fvdl     1142:                }
                   1143:                while (wp && wp->nd_off < nfsd->nd_off &&
1.44      perry    1144:                    !memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1.23      fvdl     1145:                    owp = wp;
1.70      yamt     1146:                    wp = LIST_NEXT(wp, nd_hash);
1.23      fvdl     1147:                }
                   1148:                if (owp) {
                   1149:                    LIST_INSERT_AFTER(owp, nfsd, nd_hash);
                   1150:
                   1151:                    /*
                   1152:                     * Search the hash list for overlapping entries and
                   1153:                     * coalesce.
                   1154:                     */
                   1155:                    for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1.70      yamt     1156:                        wp = LIST_NEXT(nfsd, nd_hash);
1.23      fvdl     1157:                        if (NFSW_SAMECRED(owp, nfsd))
                   1158:                            nfsrvw_coalesce(owp, nfsd);
                   1159:                    }
                   1160:                } else {
                   1161:                    LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
                   1162:                }
                   1163:            }
                   1164:            splx(s);
1.1       cgd      1165:        }
1.23      fvdl     1166:
1.1       cgd      1167:        /*
1.23      fvdl     1168:         * Now, do VOP_WRITE()s for any one(s) that need to be done now
                   1169:         * and generate the associated reply mbuf list(s).
1.1       cgd      1170:         */
1.23      fvdl     1171: loop1:
                   1172:        cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
                   1173:        s = splsoftclock();
1.70      yamt     1174:        for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
                   1175:                owp = LIST_NEXT(nfsd, nd_tq);
1.23      fvdl     1176:                if (nfsd->nd_time > cur_usec)
                   1177:                    break;
                   1178:                if (nfsd->nd_mreq)
                   1179:                    continue;
                   1180:                LIST_REMOVE(nfsd, nd_tq);
                   1181:                LIST_REMOVE(nfsd, nd_hash);
                   1182:                splx(s);
                   1183:                mrep = nfsd->nd_mrep;
                   1184:                nfsd->nd_mrep = NULL;
                   1185:                cred = &nfsd->nd_cr;
                   1186:                v3 = (nfsd->nd_flag & ND_NFSV3);
                   1187:                forat_ret = aftat_ret = 1;
                   1188:                error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1.35      fvdl     1189:                    nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH),
1.78      thorpej  1190:                    FALSE);
1.23      fvdl     1191:                if (!error) {
                   1192:                    if (v3)
1.79      fvdl     1193:                        forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
1.23      fvdl     1194:                    if (vp->v_type != VREG) {
                   1195:                        if (v3)
                   1196:                            error = EINVAL;
1.1       cgd      1197:                        else
1.23      fvdl     1198:                            error = (vp->v_type == VDIR) ? EISDIR : EACCES;
                   1199:                    }
                   1200:                } else
                   1201:                    vp = NULL;
                   1202:                if (!error) {
                   1203:                    nqsrv_getl(vp, ND_WRITE);
1.79      fvdl     1204:                    error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
1.23      fvdl     1205:                }
                   1206:
                   1207:                if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
                   1208:                    ioflags = IO_NODELOCKED;
                   1209:                else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
                   1210:                    ioflags = (IO_SYNC | IO_NODELOCKED);
                   1211:                else
                   1212:                    ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
                   1213:                uiop->uio_rw = UIO_WRITE;
                   1214:                uiop->uio_segflg = UIO_SYSSPACE;
1.79      fvdl     1215:                uiop->uio_procp = (struct proc *)0;
1.23      fvdl     1216:                uiop->uio_offset = nfsd->nd_off;
                   1217:                uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
                   1218:                if (uiop->uio_resid > 0) {
                   1219:                    mp = mrep;
                   1220:                    i = 0;
                   1221:                    while (mp) {
                   1222:                        if (mp->m_len > 0)
                   1223:                            i++;
                   1224:                        mp = mp->m_next;
                   1225:                    }
                   1226:                    uiop->uio_iovcnt = i;
1.56      thorpej  1227:                    iov = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
1.23      fvdl     1228:                    uiop->uio_iov = ivp = iov;
                   1229:                    mp = mrep;
                   1230:                    while (mp) {
                   1231:                        if (mp->m_len > 0) {
                   1232:                            ivp->iov_base = mtod(mp, caddr_t);
                   1233:                            ivp->iov_len = mp->m_len;
                   1234:                            ivp++;
                   1235:                        }
1.1       cgd      1236:                        mp = mp->m_next;
1.23      fvdl     1237:                    }
                   1238:                    if (!error) {
                   1239:                        error = VOP_WRITE(vp, uiop, ioflags, cred);
                   1240:                        nfsstats.srvvop_writes++;
                   1241:                    }
1.56      thorpej  1242:                    free((caddr_t)iov, M_TEMP);
1.1       cgd      1243:                }
1.23      fvdl     1244:                m_freem(mrep);
                   1245:                if (vp) {
1.79      fvdl     1246:                    aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl     1247:                    vput(vp);
1.1       cgd      1248:                }
1.23      fvdl     1249:
                   1250:                /*
                   1251:                 * Loop around generating replies for all write rpcs that have
                   1252:                 * now been completed.
                   1253:                 */
                   1254:                swp = nfsd;
                   1255:                do {
                   1256:                    if (error) {
                   1257:                        nfsm_writereply(NFSX_WCCDATA(v3), v3);
                   1258:                        if (v3) {
                   1259:                            nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1260:                        }
                   1261:                    } else {
                   1262:                        nfsm_writereply(NFSX_PREOPATTR(v3) +
                   1263:                            NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
                   1264:                            NFSX_WRITEVERF(v3), v3);
                   1265:                        if (v3) {
                   1266:                            nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
                   1267:                            nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
                   1268:                            *tl++ = txdr_unsigned(nfsd->nd_len);
                   1269:                            *tl++ = txdr_unsigned(swp->nd_stable);
                   1270:                            /*
                   1271:                             * Actually, there is no need to txdr these fields,
                   1272:                             * but it may make the values more human readable,
                   1273:                             * for debugging purposes.
                   1274:                             */
                   1275:                            *tl++ = txdr_unsigned(boottime.tv_sec);
                   1276:                            *tl = txdr_unsigned(boottime.tv_usec);
                   1277:                        } else {
                   1278:                            nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   1279:                            nfsm_srvfillattr(&va, fp);
                   1280:                        }
                   1281:                    }
                   1282:                    nfsd->nd_mreq = mreq;
                   1283:                    if (nfsd->nd_mrep)
                   1284:                        panic("nfsrv_write: nd_mrep not free");
                   1285:
                   1286:                    /*
                   1287:                     * Done. Put it at the head of the timer queue so that
                   1288:                     * the final phase can return the reply.
                   1289:                     */
                   1290:                    s = splsoftclock();
                   1291:                    if (nfsd != swp) {
                   1292:                        nfsd->nd_time = 0;
                   1293:                        LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
                   1294:                    }
1.70      yamt     1295:                    nfsd = LIST_FIRST(&swp->nd_coalesce);
1.23      fvdl     1296:                    if (nfsd) {
                   1297:                        LIST_REMOVE(nfsd, nd_tq);
                   1298:                    }
                   1299:                    splx(s);
                   1300:                } while (nfsd);
                   1301:                s = splsoftclock();
                   1302:                swp->nd_time = 0;
                   1303:                LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
                   1304:                splx(s);
                   1305:                goto loop1;
                   1306:        }
                   1307:        splx(s);
                   1308:
                   1309:        /*
                   1310:         * Search for a reply to return.
                   1311:         */
                   1312:        s = splsoftclock();
1.70      yamt     1313:        LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) {
1.23      fvdl     1314:                if (nfsd->nd_mreq) {
                   1315:                    LIST_REMOVE(nfsd, nd_tq);
                   1316:                    *mrq = nfsd->nd_mreq;
                   1317:                    *ndp = nfsd;
                   1318:                    break;
1.1       cgd      1319:                }
1.70      yamt     1320:        }
1.23      fvdl     1321:        splx(s);
                   1322:        return (0);
                   1323: }
                   1324:
                   1325: /*
                   1326:  * Coalesce the write request nfsd into owp. To do this we must:
                   1327:  * - remove nfsd from the queues
                   1328:  * - merge nfsd->nd_mrep into owp->nd_mrep
                   1329:  * - update the nd_eoff and nd_stable for owp
                   1330:  * - put nfsd on owp's nd_coalesce list
                   1331:  * NB: Must be called at splsoftclock().
                   1332:  */
                   1333: void
                   1334: nfsrvw_coalesce(owp, nfsd)
1.54      augustss 1335:         struct nfsrv_descript *owp;
                   1336:         struct nfsrv_descript *nfsd;
1.23      fvdl     1337: {
1.54      augustss 1338:         int overlap;
                   1339:         struct mbuf *mp;
1.70      yamt     1340:        struct nfsrv_descript *m;
1.23      fvdl     1341:
                   1342:         LIST_REMOVE(nfsd, nd_hash);
                   1343:         LIST_REMOVE(nfsd, nd_tq);
                   1344:         if (owp->nd_eoff < nfsd->nd_eoff) {
                   1345:             overlap = owp->nd_eoff - nfsd->nd_off;
                   1346:             if (overlap < 0)
                   1347:                 panic("nfsrv_coalesce: bad off");
                   1348:             if (overlap > 0)
                   1349:                 m_adj(nfsd->nd_mrep, overlap);
                   1350:             mp = owp->nd_mrep;
                   1351:             while (mp->m_next)
                   1352:                 mp = mp->m_next;
                   1353:             mp->m_next = nfsd->nd_mrep;
                   1354:             owp->nd_eoff = nfsd->nd_eoff;
                   1355:         } else
                   1356:             m_freem(nfsd->nd_mrep);
                   1357:         nfsd->nd_mrep = NULL;
                   1358:         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
                   1359:             owp->nd_stable = NFSV3WRITE_FILESYNC;
                   1360:         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
                   1361:             owp->nd_stable == NFSV3WRITE_UNSTABLE)
                   1362:             owp->nd_stable = NFSV3WRITE_DATASYNC;
                   1363:         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1.34      fvdl     1364:        /*
                   1365:         * nfsd might hold coalesce elements! Move them to owp.
                   1366:         * Otherwise, requests may be lost and clients will be stuck.
                   1367:         */
1.70      yamt     1368:        while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) {
                   1369:                LIST_REMOVE(m, nd_tq);
                   1370:                LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
                   1371:        }
1.1       cgd      1372: }
                   1373:
                   1374: /*
                   1375:  * nfs create service
1.15      mycroft  1376:  * now does a truncate to 0 length via. setattr if it already exists
1.1       cgd      1377:  */
1.22      christos 1378: int
1.79      fvdl     1379: nfsrv_create(nfsd, slp, procp, mrq)
1.23      fvdl     1380:        struct nfsrv_descript *nfsd;
                   1381:        struct nfssvc_sock *slp;
1.79      fvdl     1382:        struct proc *procp;
1.23      fvdl     1383:        struct mbuf **mrq;
1.1       cgd      1384: {
1.23      fvdl     1385:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1386:        struct mbuf *nam = nfsd->nd_nam;
                   1387:        caddr_t dpos = nfsd->nd_dpos;
                   1388:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 1389:        struct nfs_fattr *fp;
1.23      fvdl     1390:        struct vattr va, dirfor, diraft;
1.54      augustss 1391:        struct nfsv2_sattr *sp;
                   1392:        u_int32_t *tl;
1.1       cgd      1393:        struct nameidata nd;
1.54      augustss 1394:        caddr_t cp;
                   1395:        int32_t t1;
1.1       cgd      1396:        caddr_t bpos;
1.23      fvdl     1397:        int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
                   1398:        int rdev = 0;
                   1399:        int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1.1       cgd      1400:        char *cp2;
1.67      matt     1401:        struct mbuf *mb, *mreq;
1.23      fvdl     1402:        struct vnode *vp = NULL, *dirp = NULL;
                   1403:        nfsfh_t nfh;
1.1       cgd      1404:        fhandle_t *fhp;
1.23      fvdl     1405:        u_quad_t frev, tempsize;
                   1406:        u_char cverf[NFSX_V3CREATEVERF];
1.1       cgd      1407:
1.15      mycroft  1408:        nd.ni_cnd.cn_nameiop = 0;
1.1       cgd      1409:        fhp = &nfh.fh_generic;
                   1410:        nfsm_srvmtofh(fhp);
1.23      fvdl     1411:        nfsm_srvnamesiz(len);
1.15      mycroft  1412:        nd.ni_cnd.cn_cred = cred;
                   1413:        nd.ni_cnd.cn_nameiop = CREATE;
1.61      chs      1414:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     1415:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     1416:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1417:        if (dirp) {
                   1418:                if (v3)
1.79      fvdl     1419:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   1420:                                procp);
1.23      fvdl     1421:                else {
                   1422:                        vrele(dirp);
                   1423:                        dirp = (struct vnode *)0;
                   1424:                }
                   1425:        }
                   1426:        if (error) {
                   1427:                nfsm_reply(NFSX_WCCDATA(v3));
                   1428:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1429:                if (dirp)
                   1430:                        vrele(dirp);
                   1431:                return (0);
                   1432:        }
1.18      mycroft  1433:        VATTR_NULL(&va);
1.23      fvdl     1434:        if (v3) {
                   1435:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   1436:                how = fxdr_unsigned(int, *tl);
                   1437:                switch (how) {
                   1438:                case NFSV3CREATE_GUARDED:
                   1439:                        if (nd.ni_vp) {
                   1440:                                error = EEXIST;
                   1441:                                break;
                   1442:                        }
                   1443:                case NFSV3CREATE_UNCHECKED:
                   1444:                        nfsm_srvsattr(&va);
                   1445:                        break;
                   1446:                case NFSV3CREATE_EXCLUSIVE:
                   1447:                        nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1.44      perry    1448:                        memcpy(cverf, cp, NFSX_V3CREATEVERF);
1.23      fvdl     1449:                        exclusive_flag = 1;
                   1450:                        if (nd.ni_vp == NULL)
                   1451:                                va.va_mode = 0;
                   1452:                        break;
                   1453:                };
                   1454:                va.va_type = VREG;
                   1455:        } else {
                   1456:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                   1457:                va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
                   1458:                if (va.va_type == VNON)
                   1459:                        va.va_type = VREG;
                   1460:                va.va_mode = nfstov_mode(sp->sa_mode);
                   1461:                switch (va.va_type) {
                   1462:                case VREG:
                   1463:                        tsize = fxdr_unsigned(int32_t, sp->sa_size);
                   1464:                        if (tsize != -1)
                   1465:                                va.va_size = (u_quad_t)tsize;
                   1466:                        break;
                   1467:                case VCHR:
                   1468:                case VBLK:
                   1469:                case VFIFO:
                   1470:                        rdev = fxdr_unsigned(int32_t, sp->sa_size);
                   1471:                        break;
                   1472:                default:
                   1473:                        break;
                   1474:                };
                   1475:        }
                   1476:
1.1       cgd      1477:        /*
1.15      mycroft  1478:         * Iff doesn't exist, create it
                   1479:         * otherwise just truncate to 0 length
1.1       cgd      1480:         *   should I set the mode too ??
                   1481:         */
                   1482:        if (nd.ni_vp == NULL) {
1.18      mycroft  1483:                if (va.va_type == VREG || va.va_type == VSOCK) {
1.23      fvdl     1484:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1485:                        error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1486:                        if (!error) {
                   1487:                                if (exclusive_flag) {
                   1488:                                        exclusive_flag = 0;
                   1489:                                        VATTR_NULL(&va);
1.44      perry    1490:                                        memcpy((caddr_t)&va.va_atime, cverf,
1.23      fvdl     1491:                                                NFSX_V3CREATEVERF);
                   1492:                                        error = VOP_SETATTR(nd.ni_vp, &va, cred,
1.79      fvdl     1493:                                                procp);
1.23      fvdl     1494:                                }
                   1495:                        }
1.18      mycroft  1496:                } else if (va.va_type == VCHR || va.va_type == VBLK ||
                   1497:                        va.va_type == VFIFO) {
                   1498:                        if (va.va_type == VCHR && rdev == 0xffffffff)
                   1499:                                va.va_type = VFIFO;
1.46      mrg      1500:                        if (va.va_type != VFIFO &&
                   1501:                            (error = suser(cred, (u_short *)0))) {
1.15      mycroft  1502:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1503:                                vput(nd.ni_dvp);
1.23      fvdl     1504:                                nfsm_reply(0);
                   1505:                                return (error);
1.1       cgd      1506:                        } else
1.18      mycroft  1507:                                va.va_rdev = (dev_t)rdev;
1.23      fvdl     1508:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
1.22      christos 1509:                        error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
1.23      fvdl     1510:                            &va);
1.22      christos 1511:                        if (error) {
1.1       cgd      1512:                                nfsm_reply(0);
                   1513:                        }
1.15      mycroft  1514:                        if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1.1       cgd      1515:                                vrele(nd.ni_dvp);
                   1516:                                vput(nd.ni_vp);
1.15      mycroft  1517:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1518:                                error = EINVAL;
                   1519:                                nfsm_reply(0);
                   1520:                        }
                   1521:                } else {
1.15      mycroft  1522:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1523:                        vput(nd.ni_dvp);
                   1524:                        error = ENXIO;
                   1525:                }
                   1526:                vp = nd.ni_vp;
                   1527:        } else {
                   1528:                vp = nd.ni_vp;
                   1529:                if (nd.ni_dvp == vp)
                   1530:                        vrele(nd.ni_dvp);
                   1531:                else
                   1532:                        vput(nd.ni_dvp);
1.15      mycroft  1533:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.50      mycroft  1534:                if (!error && va.va_size != -1) {
1.22      christos 1535:                        error = nfsrv_access(vp, VWRITE, cred,
1.79      fvdl     1536:                            (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
1.23      fvdl     1537:                        if (!error) {
                   1538:                                nqsrv_getl(vp, ND_WRITE);
                   1539:                                tempsize = va.va_size;
                   1540:                                VATTR_NULL(&va);
                   1541:                                va.va_size = tempsize;
1.79      fvdl     1542:                                error = VOP_SETATTR(vp, &va, cred,
                   1543:                                         procp);
1.15      mycroft  1544:                        }
1.1       cgd      1545:                }
1.50      mycroft  1546:                if (error)
                   1547:                        vput(vp);
1.1       cgd      1548:        }
1.23      fvdl     1549:        if (!error) {
1.44      perry    1550:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     1551:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   1552:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   1553:                if (!error)
1.79      fvdl     1554:                        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd      1555:                vput(vp);
                   1556:        }
1.23      fvdl     1557:        if (v3) {
                   1558:                if (exclusive_flag && !error &&
1.44      perry    1559:                        memcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
1.23      fvdl     1560:                        error = EEXIST;
1.79      fvdl     1561:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     1562:                vrele(dirp);
                   1563:        }
                   1564:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
                   1565:        if (v3) {
                   1566:                if (!error) {
                   1567:                        nfsm_srvpostop_fh(fhp);
                   1568:                        nfsm_srvpostop_attr(0, &va);
                   1569:                }
                   1570:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1571:        } else {
                   1572:                nfsm_srvfhtom(fhp, v3);
                   1573:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   1574:                nfsm_srvfillattr(&va, fp);
                   1575:        }
                   1576:        return (0);
1.1       cgd      1577: nfsmout:
1.23      fvdl     1578:        if (dirp)
                   1579:                vrele(dirp);
1.15      mycroft  1580:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      1581:        if (nd.ni_dvp == nd.ni_vp)
                   1582:                vrele(nd.ni_dvp);
                   1583:        else
                   1584:                vput(nd.ni_dvp);
                   1585:        if (nd.ni_vp)
                   1586:                vput(nd.ni_vp);
                   1587:        return (error);
1.23      fvdl     1588: }
                   1589:
                   1590: /*
                   1591:  * nfs v3 mknod service
                   1592:  */
                   1593: int
1.79      fvdl     1594: nfsrv_mknod(nfsd, slp, procp, mrq)
1.23      fvdl     1595:        struct nfsrv_descript *nfsd;
                   1596:        struct nfssvc_sock *slp;
1.79      fvdl     1597:        struct proc *procp;
1.23      fvdl     1598:        struct mbuf **mrq;
                   1599: {
                   1600:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1601:        struct mbuf *nam = nfsd->nd_nam;
                   1602:        caddr_t dpos = nfsd->nd_dpos;
                   1603:        struct ucred *cred = &nfsd->nd_cr;
                   1604:        struct vattr va, dirfor, diraft;
1.54      augustss 1605:        u_int32_t *tl;
1.23      fvdl     1606:        struct nameidata nd;
1.54      augustss 1607:        int32_t t1;
1.23      fvdl     1608:        caddr_t bpos;
                   1609:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   1610:        u_int32_t major, minor;
                   1611:        enum vtype vtyp;
                   1612:        char *cp2;
1.67      matt     1613:        struct mbuf *mb, *mreq;
1.23      fvdl     1614:        struct vnode *vp, *dirp = (struct vnode *)0;
                   1615:        nfsfh_t nfh;
                   1616:        fhandle_t *fhp;
                   1617:        u_quad_t frev;
                   1618:
                   1619:        nd.ni_cnd.cn_nameiop = 0;
                   1620:        fhp = &nfh.fh_generic;
                   1621:        nfsm_srvmtofh(fhp);
                   1622:        nfsm_srvnamesiz(len);
                   1623:        nd.ni_cnd.cn_cred = cred;
                   1624:        nd.ni_cnd.cn_nameiop = CREATE;
1.61      chs      1625:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     1626:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     1627:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1628:        if (dirp)
1.79      fvdl     1629:                dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
1.23      fvdl     1630:        if (error) {
                   1631:                nfsm_reply(NFSX_WCCDATA(1));
                   1632:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1633:                if (dirp)
                   1634:                        vrele(dirp);
                   1635:                return (0);
                   1636:        }
                   1637:        nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   1638:        vtyp = nfsv3tov_type(*tl);
                   1639:        if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
                   1640:                error = NFSERR_BADTYPE;
                   1641:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.51      sommerfe 1642:                if (nd.ni_dvp == nd.ni_vp)
                   1643:                        vrele(nd.ni_dvp);
                   1644:                else
                   1645:                        vput(nd.ni_dvp);
                   1646:                if (nd.ni_vp)
                   1647:                        vput(nd.ni_vp);
1.23      fvdl     1648:                goto out;
                   1649:        }
                   1650:        VATTR_NULL(&va);
                   1651:        nfsm_srvsattr(&va);
                   1652:        if (vtyp == VCHR || vtyp == VBLK) {
                   1653:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                   1654:                major = fxdr_unsigned(u_int32_t, *tl++);
                   1655:                minor = fxdr_unsigned(u_int32_t, *tl);
                   1656:                va.va_rdev = makedev(major, minor);
                   1657:        }
1.1       cgd      1658:
1.23      fvdl     1659:        /*
                   1660:         * Iff doesn't exist, create it.
                   1661:         */
                   1662:        if (nd.ni_vp) {
                   1663:                error = EEXIST;
                   1664:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.51      sommerfe 1665:                if (nd.ni_dvp == nd.ni_vp)
                   1666:                        vrele(nd.ni_dvp);
                   1667:                else
                   1668:                        vput(nd.ni_dvp);
                   1669:                vput(nd.ni_vp);
1.23      fvdl     1670:                goto out;
                   1671:        }
                   1672:        va.va_type = vtyp;
                   1673:        if (vtyp == VSOCK) {
                   1674:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1675:                error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1676:        } else {
1.46      mrg      1677:                if (va.va_type != VFIFO &&
                   1678:                    (error = suser(cred, (u_short *)0))) {
1.23      fvdl     1679:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1680:                        vput(nd.ni_dvp);
                   1681:                        goto out;
                   1682:                }
                   1683:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1684:                error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   1685:                if (error) {
                   1686:                        goto out;
                   1687:                }
                   1688:                if (error)
                   1689:                        goto out;
                   1690:                if (nd.ni_cnd.cn_flags & ISSYMLINK) {
                   1691:                        vput(nd.ni_vp);
                   1692:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1693:                        error = EINVAL;
                   1694:                }
                   1695:        }
1.1       cgd      1696: out:
1.23      fvdl     1697:        vp = nd.ni_vp;
                   1698:        if (!error) {
1.44      perry    1699:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     1700:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   1701:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   1702:                if (!error)
1.79      fvdl     1703:                        error = VOP_GETATTR(vp, &va, cred, procp);
1.23      fvdl     1704:                vput(vp);
                   1705:        }
1.79      fvdl     1706:        diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     1707:        vrele(dirp);
                   1708:        nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
                   1709:        if (!error) {
                   1710:                nfsm_srvpostop_fh(fhp);
                   1711:                nfsm_srvpostop_attr(0, &va);
                   1712:        }
                   1713:        nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1714:        return (0);
                   1715: nfsmout:
                   1716:        if (dirp)
                   1717:                vrele(dirp);
                   1718:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1719:        if (nd.ni_dvp == nd.ni_vp)
                   1720:                vrele(nd.ni_dvp);
                   1721:        else
                   1722:                vput(nd.ni_dvp);
                   1723:        if (nd.ni_vp)
                   1724:                vput(nd.ni_vp);
                   1725:        return (error);
1.1       cgd      1726: }
                   1727:
                   1728: /*
                   1729:  * nfs remove service
                   1730:  */
1.22      christos 1731: int
1.79      fvdl     1732: nfsrv_remove(nfsd, slp, procp, mrq)
1.23      fvdl     1733:        struct nfsrv_descript *nfsd;
                   1734:        struct nfssvc_sock *slp;
1.79      fvdl     1735:        struct proc *procp;
1.23      fvdl     1736:        struct mbuf **mrq;
1.1       cgd      1737: {
1.23      fvdl     1738:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1739:        struct mbuf *nam = nfsd->nd_nam;
                   1740:        caddr_t dpos = nfsd->nd_dpos;
                   1741:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd      1742:        struct nameidata nd;
1.54      augustss 1743:        u_int32_t *tl;
                   1744:        int32_t t1;
1.1       cgd      1745:        caddr_t bpos;
1.23      fvdl     1746:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   1747:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      1748:        char *cp2;
                   1749:        struct mbuf *mb, *mreq;
1.23      fvdl     1750:        struct vnode *vp, *dirp;
                   1751:        struct vattr dirfor, diraft;
                   1752:        nfsfh_t nfh;
1.1       cgd      1753:        fhandle_t *fhp;
1.15      mycroft  1754:        u_quad_t frev;
1.1       cgd      1755:
1.23      fvdl     1756: #ifndef nolint
                   1757:        vp = (struct vnode *)0;
                   1758: #endif
1.1       cgd      1759:        fhp = &nfh.fh_generic;
                   1760:        nfsm_srvmtofh(fhp);
1.23      fvdl     1761:        nfsm_srvnamesiz(len);
1.15      mycroft  1762:        nd.ni_cnd.cn_cred = cred;
                   1763:        nd.ni_cnd.cn_nameiop = DELETE;
                   1764:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     1765:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     1766:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1767:        if (dirp) {
                   1768:                if (v3)
1.79      fvdl     1769:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   1770:                                procp);
1.1       cgd      1771:                else
1.23      fvdl     1772:                        vrele(dirp);
1.1       cgd      1773:        }
1.23      fvdl     1774:        if (!error) {
                   1775:                vp = nd.ni_vp;
                   1776:                if (vp->v_type == VDIR &&
                   1777:                    (error = suser(cred, (u_short *)0)) != 0)
                   1778:                        goto out;
                   1779:                /*
                   1780:                 * The root of a mounted filesystem cannot be deleted.
                   1781:                 */
                   1782:                if (vp->v_flag & VROOT) {
                   1783:                        error = EBUSY;
                   1784:                        goto out;
                   1785:                }
1.21      mycroft  1786: out:
1.23      fvdl     1787:                if (!error) {
                   1788:                        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   1789:                        nqsrv_getl(vp, ND_WRITE);
                   1790:                        error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   1791:                } else {
                   1792:                        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1793:                        if (nd.ni_dvp == vp)
                   1794:                                vrele(nd.ni_dvp);
                   1795:                        else
                   1796:                                vput(nd.ni_dvp);
                   1797:                        vput(vp);
                   1798:                }
                   1799:        }
                   1800:        if (dirp && v3) {
1.79      fvdl     1801:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     1802:                vrele(dirp);
                   1803:        }
                   1804:        nfsm_reply(NFSX_WCCDATA(v3));
                   1805:        if (v3) {
                   1806:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   1807:                return (0);
                   1808:        }
1.1       cgd      1809:        nfsm_srvdone;
                   1810: }
                   1811:
                   1812: /*
                   1813:  * nfs rename service
                   1814:  */
1.22      christos 1815: int
1.79      fvdl     1816: nfsrv_rename(nfsd, slp, procp, mrq)
1.23      fvdl     1817:        struct nfsrv_descript *nfsd;
                   1818:        struct nfssvc_sock *slp;
1.79      fvdl     1819:        struct proc *procp;
1.23      fvdl     1820:        struct mbuf **mrq;
1.1       cgd      1821: {
1.23      fvdl     1822:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   1823:        struct mbuf *nam = nfsd->nd_nam;
                   1824:        caddr_t dpos = nfsd->nd_dpos;
                   1825:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 1826:        u_int32_t *tl;
                   1827:        int32_t t1;
1.1       cgd      1828:        caddr_t bpos;
1.68      yamt     1829:        int error = 0, cache, fdirfor_ret = 1, fdiraft_ret = 1;
                   1830:        uint32_t len, len2;
1.23      fvdl     1831:        int tdirfor_ret = 1, tdiraft_ret = 1;
                   1832:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      1833:        char *cp2;
                   1834:        struct mbuf *mb, *mreq;
                   1835:        struct nameidata fromnd, tond;
1.23      fvdl     1836:        struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
                   1837:        struct vnode *tdirp = (struct vnode *)0;
                   1838:        struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
                   1839:        nfsfh_t fnfh, tnfh;
1.1       cgd      1840:        fhandle_t *ffhp, *tfhp;
1.15      mycroft  1841:        u_quad_t frev;
                   1842:        uid_t saved_uid;
1.1       cgd      1843:
1.23      fvdl     1844: #ifndef nolint
                   1845:        fvp = (struct vnode *)0;
                   1846: #endif
1.1       cgd      1847:        ffhp = &fnfh.fh_generic;
                   1848:        tfhp = &tnfh.fh_generic;
1.15      mycroft  1849:        fromnd.ni_cnd.cn_nameiop = 0;
                   1850:        tond.ni_cnd.cn_nameiop = 0;
1.1       cgd      1851:        nfsm_srvmtofh(ffhp);
1.23      fvdl     1852:        nfsm_srvnamesiz(len);
1.1       cgd      1853:        /*
1.15      mycroft  1854:         * Remember our original uid so that we can reset cr_uid before
                   1855:         * the second nfs_namei() call, in case it is remapped.
1.1       cgd      1856:         */
1.15      mycroft  1857:        saved_uid = cred->cr_uid;
                   1858:        fromnd.ni_cnd.cn_cred = cred;
                   1859:        fromnd.ni_cnd.cn_nameiop = DELETE;
                   1860:        fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1.23      fvdl     1861:        error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
1.79      fvdl     1862:                &dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1863:        if (fdirp) {
                   1864:                if (v3)
1.79      fvdl     1865:                        fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
                   1866:                                procp);
1.23      fvdl     1867:                else {
                   1868:                        vrele(fdirp);
                   1869:                        fdirp = (struct vnode *)0;
                   1870:                }
                   1871:        }
                   1872:        if (error) {
                   1873:                nfsm_reply(2 * NFSX_WCCDATA(v3));
                   1874:                nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
                   1875:                nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
                   1876:                if (fdirp)
                   1877:                        vrele(fdirp);
                   1878:                return (0);
                   1879:        }
1.1       cgd      1880:        fvp = fromnd.ni_vp;
                   1881:        nfsm_srvmtofh(tfhp);
1.68      yamt     1882:        if (v3) {
                   1883:                nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
                   1884:                len2 = fxdr_unsigned(uint32_t, *tl);
                   1885:                /* len2 will be checked by nfs_namei */
                   1886:        }
                   1887:        else {
                   1888:                /* NFSv2 */
                   1889:                nfsm_strsiz(len2, NFS_MAXNAMLEN);
                   1890:        }
1.15      mycroft  1891:        cred->cr_uid = saved_uid;
                   1892:        tond.ni_cnd.cn_cred = cred;
                   1893:        tond.ni_cnd.cn_nameiop = RENAME;
                   1894:        tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1.23      fvdl     1895:        error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
1.79      fvdl     1896:                &dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     1897:        if (tdirp) {
                   1898:                if (v3)
1.79      fvdl     1899:                        tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
                   1900:                                procp);
1.23      fvdl     1901:                else {
                   1902:                        vrele(tdirp);
                   1903:                        tdirp = (struct vnode *)0;
                   1904:                }
                   1905:        }
1.22      christos 1906:        if (error) {
1.15      mycroft  1907:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      1908:                vrele(fromnd.ni_dvp);
                   1909:                vrele(fvp);
                   1910:                goto out1;
                   1911:        }
                   1912:        tdvp = tond.ni_dvp;
                   1913:        tvp = tond.ni_vp;
                   1914:        if (tvp != NULL) {
                   1915:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1.23      fvdl     1916:                        if (v3)
                   1917:                                error = EEXIST;
                   1918:                        else
                   1919:                                error = EISDIR;
1.1       cgd      1920:                        goto out;
                   1921:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1.23      fvdl     1922:                        if (v3)
                   1923:                                error = EEXIST;
                   1924:                        else
                   1925:                                error = ENOTDIR;
1.1       cgd      1926:                        goto out;
                   1927:                }
1.15      mycroft  1928:                if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1.23      fvdl     1929:                        if (v3)
                   1930:                                error = EXDEV;
                   1931:                        else
                   1932:                                error = ENOTEMPTY;
1.15      mycroft  1933:                        goto out;
                   1934:                }
                   1935:        }
                   1936:        if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1.23      fvdl     1937:                if (v3)
                   1938:                        error = EXDEV;
                   1939:                else
                   1940:                        error = ENOTEMPTY;
1.15      mycroft  1941:                goto out;
1.1       cgd      1942:        }
                   1943:        if (fvp->v_mount != tdvp->v_mount) {
1.23      fvdl     1944:                if (v3)
                   1945:                        error = EXDEV;
                   1946:                else
                   1947:                        error = ENOTEMPTY;
1.1       cgd      1948:                goto out;
                   1949:        }
1.45      thorpej  1950:        if (fvp == tdvp) {
1.23      fvdl     1951:                if (v3)
                   1952:                        error = EINVAL;
                   1953:                else
                   1954:                        error = ENOTEMPTY;
1.45      thorpej  1955:        }
1.1       cgd      1956:        /*
                   1957:         * If source is the same as the destination (that is the
                   1958:         * same vnode with the same name in the same directory),
                   1959:         * then there is nothing to do.
                   1960:         */
                   1961:        if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1.15      mycroft  1962:            fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1.44      perry    1963:            !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1.15      mycroft  1964:              fromnd.ni_cnd.cn_namelen))
1.1       cgd      1965:                error = -1;
                   1966: out:
                   1967:        if (!error) {
1.23      fvdl     1968:                nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
                   1969:                nqsrv_getl(tdvp, ND_WRITE);
1.30      fvdl     1970:                if (tvp) {
1.23      fvdl     1971:                        nqsrv_getl(tvp, ND_WRITE);
1.30      fvdl     1972:                }
1.15      mycroft  1973:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
                   1974:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1.1       cgd      1975:        } else {
1.15      mycroft  1976:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1.1       cgd      1977:                if (tdvp == tvp)
                   1978:                        vrele(tdvp);
                   1979:                else
                   1980:                        vput(tdvp);
                   1981:                if (tvp)
                   1982:                        vput(tvp);
1.15      mycroft  1983:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      1984:                vrele(fromnd.ni_dvp);
                   1985:                vrele(fvp);
1.23      fvdl     1986:                if (error == -1)
                   1987:                        error = 0;
1.1       cgd      1988:        }
                   1989:        vrele(tond.ni_startdir);
1.57      thorpej  1990:        PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
1.1       cgd      1991: out1:
1.23      fvdl     1992:        if (fdirp) {
1.79      fvdl     1993:                fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
1.23      fvdl     1994:                vrele(fdirp);
                   1995:        }
                   1996:        if (tdirp) {
1.79      fvdl     1997:                tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
1.23      fvdl     1998:                vrele(tdirp);
                   1999:        }
1.1       cgd      2000:        vrele(fromnd.ni_startdir);
1.57      thorpej  2001:        PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
1.23      fvdl     2002:        nfsm_reply(2 * NFSX_WCCDATA(v3));
                   2003:        if (v3) {
                   2004:                nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
                   2005:                nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
                   2006:        }
                   2007:        return (0);
1.1       cgd      2008:
                   2009: nfsmout:
1.23      fvdl     2010:        if (fdirp)
                   2011:                vrele(fdirp);
                   2012:        if (tdirp)
                   2013:                vrele(tdirp);
                   2014:        if (tond.ni_cnd.cn_nameiop) {
1.1       cgd      2015:                vrele(tond.ni_startdir);
1.57      thorpej  2016:                PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
1.1       cgd      2017:        }
1.23      fvdl     2018:        if (fromnd.ni_cnd.cn_nameiop) {
1.1       cgd      2019:                vrele(fromnd.ni_startdir);
1.57      thorpej  2020:                PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
1.15      mycroft  2021:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1.1       cgd      2022:                vrele(fromnd.ni_dvp);
                   2023:                vrele(fvp);
                   2024:        }
                   2025:        return (error);
                   2026: }
                   2027:
                   2028: /*
                   2029:  * nfs link service
                   2030:  */
1.22      christos 2031: int
1.79      fvdl     2032: nfsrv_link(nfsd, slp, procp, mrq)
1.23      fvdl     2033:        struct nfsrv_descript *nfsd;
                   2034:        struct nfssvc_sock *slp;
1.79      fvdl     2035:        struct proc *procp;
1.23      fvdl     2036:        struct mbuf **mrq;
1.1       cgd      2037: {
1.23      fvdl     2038:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2039:        struct mbuf *nam = nfsd->nd_nam;
                   2040:        caddr_t dpos = nfsd->nd_dpos;
                   2041:        struct ucred *cred = &nfsd->nd_cr;
1.1       cgd      2042:        struct nameidata nd;
1.54      augustss 2043:        u_int32_t *tl;
                   2044:        int32_t t1;
1.1       cgd      2045:        caddr_t bpos;
1.23      fvdl     2046:        int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   2047:        int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      2048:        char *cp2;
                   2049:        struct mbuf *mb, *mreq;
1.23      fvdl     2050:        struct vnode *vp, *xp, *dirp = (struct vnode *)0;
                   2051:        struct vattr dirfor, diraft, at;
                   2052:        nfsfh_t nfh, dnfh;
1.1       cgd      2053:        fhandle_t *fhp, *dfhp;
1.15      mycroft  2054:        u_quad_t frev;
1.1       cgd      2055:
                   2056:        fhp = &nfh.fh_generic;
                   2057:        dfhp = &dnfh.fh_generic;
                   2058:        nfsm_srvmtofh(fhp);
                   2059:        nfsm_srvmtofh(dfhp);
1.23      fvdl     2060:        nfsm_srvnamesiz(len);
                   2061:        error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
1.78      thorpej  2062:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2063:        if (error) {
                   2064:                nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2065:                nfsm_srvpostop_attr(getret, &at);
                   2066:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2067:                return (0);
                   2068:        }
                   2069:        if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0)
                   2070:                goto out1;
1.15      mycroft  2071:        nd.ni_cnd.cn_cred = cred;
                   2072:        nd.ni_cnd.cn_nameiop = CREATE;
                   2073:        nd.ni_cnd.cn_flags = LOCKPARENT;
1.23      fvdl     2074:        error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
1.79      fvdl     2075:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2076:        if (dirp) {
                   2077:                if (v3)
1.79      fvdl     2078:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2079:                                procp);
1.23      fvdl     2080:                else {
                   2081:                        vrele(dirp);
                   2082:                        dirp = (struct vnode *)0;
                   2083:                }
                   2084:        }
1.22      christos 2085:        if (error)
1.23      fvdl     2086:                goto out1;
                   2087:        xp = nd.ni_vp;
                   2088:        if (xp != NULL) {
                   2089:                error = EEXIST;
1.1       cgd      2090:                goto out;
1.23      fvdl     2091:        }
                   2092:        xp = nd.ni_dvp;
                   2093:        if (vp->v_mount != xp->v_mount)
                   2094:                error = EXDEV;
                   2095: out:
                   2096:        if (!error) {
                   2097:                nqsrv_getl(vp, ND_WRITE);
                   2098:                nqsrv_getl(xp, ND_WRITE);
                   2099:                error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
                   2100:        } else {
1.15      mycroft  2101:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2102:                if (nd.ni_dvp == nd.ni_vp)
                   2103:                        vrele(nd.ni_dvp);
                   2104:                else
                   2105:                        vput(nd.ni_dvp);
1.23      fvdl     2106:                if (nd.ni_vp)
                   2107:                        vrele(nd.ni_vp);
                   2108:        }
                   2109: out1:
                   2110:        if (v3)
1.79      fvdl     2111:                getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     2112:        if (dirp) {
1.79      fvdl     2113:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     2114:                vrele(dirp);
1.1       cgd      2115:        }
                   2116:        vrele(vp);
1.23      fvdl     2117:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2118:        if (v3) {
                   2119:                nfsm_srvpostop_attr(getret, &at);
                   2120:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2121:                return (0);
                   2122:        }
1.1       cgd      2123:        nfsm_srvdone;
                   2124: }
                   2125:
                   2126: /*
                   2127:  * nfs symbolic link service
                   2128:  */
1.22      christos 2129: int
1.79      fvdl     2130: nfsrv_symlink(nfsd, slp, procp, mrq)
1.23      fvdl     2131:        struct nfsrv_descript *nfsd;
                   2132:        struct nfssvc_sock *slp;
1.79      fvdl     2133:        struct proc *procp;
1.23      fvdl     2134:        struct mbuf **mrq;
1.1       cgd      2135: {
1.23      fvdl     2136:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2137:        struct mbuf *nam = nfsd->nd_nam;
                   2138:        caddr_t dpos = nfsd->nd_dpos;
                   2139:        struct ucred *cred = &nfsd->nd_cr;
                   2140:        struct vattr va, dirfor, diraft;
1.1       cgd      2141:        struct nameidata nd;
1.54      augustss 2142:        u_int32_t *tl;
                   2143:        int32_t t1;
1.1       cgd      2144:        struct nfsv2_sattr *sp;
1.23      fvdl     2145:        char *bpos, *pathcp = NULL, *cp2;
1.1       cgd      2146:        struct uio io;
                   2147:        struct iovec iv;
1.68      yamt     2148:        int error = 0, cache, dirfor_ret = 1, diraft_ret = 1;
                   2149:        uint32_t len, len2;
1.23      fvdl     2150:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.67      matt     2151:        struct mbuf *mb, *mreq;
1.23      fvdl     2152:        struct vnode *dirp = (struct vnode *)0;
                   2153:        nfsfh_t nfh;
1.1       cgd      2154:        fhandle_t *fhp;
1.15      mycroft  2155:        u_quad_t frev;
1.1       cgd      2156:
1.23      fvdl     2157:        nd.ni_cnd.cn_nameiop = 0;
1.1       cgd      2158:        fhp = &nfh.fh_generic;
                   2159:        nfsm_srvmtofh(fhp);
1.23      fvdl     2160:        nfsm_srvnamesiz(len);
1.15      mycroft  2161:        nd.ni_cnd.cn_cred = cred;
                   2162:        nd.ni_cnd.cn_nameiop = CREATE;
1.61      chs      2163:        nd.ni_cnd.cn_flags = LOCKPARENT;
1.23      fvdl     2164:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     2165:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2166:        if (dirp) {
                   2167:                if (v3)
1.79      fvdl     2168:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2169:                                procp);
1.23      fvdl     2170:                else {
                   2171:                        vrele(dirp);
                   2172:                        dirp = (struct vnode *)0;
                   2173:                }
                   2174:        }
1.22      christos 2175:        if (error)
1.1       cgd      2176:                goto out;
1.23      fvdl     2177:        VATTR_NULL(&va);
1.68      yamt     2178:        if (v3) {
1.23      fvdl     2179:                nfsm_srvsattr(&va);
1.68      yamt     2180:                nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
                   2181:                len2 = fxdr_unsigned(uint32_t, *tl);
                   2182:                if (len2 > PATH_MAX) {
                   2183:                        /* XXX should check _PC_NO_TRUNC */
                   2184:                        error = ENAMETOOLONG;
                   2185:                        goto abortop;
                   2186:                }
                   2187:        }
                   2188:        else {
                   2189:                /* NFSv2 */
                   2190:                nfsm_strsiz(len2, NFS_MAXPATHLEN);
                   2191:        }
1.56      thorpej  2192:        pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
1.1       cgd      2193:        iv.iov_base = pathcp;
                   2194:        iv.iov_len = len2;
                   2195:        io.uio_resid = len2;
                   2196:        io.uio_offset = 0;
                   2197:        io.uio_iov = &iv;
                   2198:        io.uio_iovcnt = 1;
                   2199:        io.uio_segflg = UIO_SYSSPACE;
                   2200:        io.uio_rw = UIO_READ;
1.79      fvdl     2201:        io.uio_procp = (struct proc *)0;
1.1       cgd      2202:        nfsm_mtouio(&io, len2);
1.23      fvdl     2203:        if (!v3) {
                   2204:                nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
                   2205:                va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
                   2206:        }
1.1       cgd      2207:        *(pathcp + len2) = '\0';
                   2208:        if (nd.ni_vp) {
1.68      yamt     2209:                error = EEXIST;
                   2210: abortop:
1.15      mycroft  2211:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2212:                if (nd.ni_dvp == nd.ni_vp)
                   2213:                        vrele(nd.ni_dvp);
                   2214:                else
                   2215:                        vput(nd.ni_dvp);
1.68      yamt     2216:                if (nd.ni_vp)
                   2217:                        vrele(nd.ni_vp);
1.1       cgd      2218:                goto out;
                   2219:        }
1.23      fvdl     2220:        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2221:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
1.61      chs      2222:        if (!error) {
1.23      fvdl     2223:            if (v3) {
1.60      assar    2224:                memset((caddr_t)fhp, 0, sizeof(nfh));
                   2225:                fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
                   2226:                error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
                   2227:                if (!error)
1.79      fvdl     2228:                    error = VOP_GETATTR(nd.ni_vp, &va, cred,
                   2229:                                        procp);
1.60      assar    2230:                vput(nd.ni_vp);
                   2231:            } else {
                   2232:                vput(nd.ni_vp);
                   2233:            }
1.23      fvdl     2234:        }
1.1       cgd      2235: out:
                   2236:        if (pathcp)
1.56      thorpej  2237:                free(pathcp, M_TEMP);
1.23      fvdl     2238:        if (dirp) {
1.79      fvdl     2239:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     2240:                vrele(dirp);
                   2241:        }
                   2242:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2243:        if (v3) {
                   2244:                if (!error) {
                   2245:                        nfsm_srvpostop_fh(fhp);
                   2246:                        nfsm_srvpostop_attr(0, &va);
                   2247:                }
                   2248:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2249:        }
                   2250:        return (0);
1.1       cgd      2251: nfsmout:
1.23      fvdl     2252:        if (dirp)
                   2253:                vrele(dirp);
1.15      mycroft  2254:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2255:        if (nd.ni_dvp == nd.ni_vp)
                   2256:                vrele(nd.ni_dvp);
                   2257:        else
                   2258:                vput(nd.ni_dvp);
                   2259:        if (nd.ni_vp)
                   2260:                vrele(nd.ni_vp);
                   2261:        if (pathcp)
1.56      thorpej  2262:                free(pathcp, M_TEMP);
1.1       cgd      2263:        return (error);
                   2264: }
                   2265:
                   2266: /*
                   2267:  * nfs mkdir service
                   2268:  */
1.22      christos 2269: int
1.79      fvdl     2270: nfsrv_mkdir(nfsd, slp, procp, mrq)
1.23      fvdl     2271:        struct nfsrv_descript *nfsd;
                   2272:        struct nfssvc_sock *slp;
1.79      fvdl     2273:        struct proc *procp;
1.23      fvdl     2274:        struct mbuf **mrq;
1.1       cgd      2275: {
1.23      fvdl     2276:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2277:        struct mbuf *nam = nfsd->nd_nam;
                   2278:        caddr_t dpos = nfsd->nd_dpos;
                   2279:        struct ucred *cred = &nfsd->nd_cr;
                   2280:        struct vattr va, dirfor, diraft;
1.54      augustss 2281:        struct nfs_fattr *fp;
1.1       cgd      2282:        struct nameidata nd;
1.54      augustss 2283:        caddr_t cp;
                   2284:        u_int32_t *tl;
                   2285:        int32_t t1;
1.1       cgd      2286:        caddr_t bpos;
1.23      fvdl     2287:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   2288:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      2289:        char *cp2;
1.67      matt     2290:        struct mbuf *mb, *mreq;
1.23      fvdl     2291:        struct vnode *vp, *dirp = (struct vnode *)0;
                   2292:        nfsfh_t nfh;
1.1       cgd      2293:        fhandle_t *fhp;
1.15      mycroft  2294:        u_quad_t frev;
1.1       cgd      2295:
                   2296:        fhp = &nfh.fh_generic;
                   2297:        nfsm_srvmtofh(fhp);
1.23      fvdl     2298:        nfsm_srvnamesiz(len);
1.15      mycroft  2299:        nd.ni_cnd.cn_cred = cred;
                   2300:        nd.ni_cnd.cn_nameiop = CREATE;
                   2301:        nd.ni_cnd.cn_flags = LOCKPARENT;
1.23      fvdl     2302:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     2303:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2304:        if (dirp) {
                   2305:                if (v3)
1.79      fvdl     2306:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2307:                                procp);
1.23      fvdl     2308:                else {
                   2309:                        vrele(dirp);
                   2310:                        dirp = (struct vnode *)0;
                   2311:                }
                   2312:        }
                   2313:        if (error) {
                   2314:                nfsm_reply(NFSX_WCCDATA(v3));
                   2315:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2316:                if (dirp)
                   2317:                        vrele(dirp);
                   2318:                return (0);
                   2319:        }
1.18      mycroft  2320:        VATTR_NULL(&va);
1.23      fvdl     2321:        if (v3) {
                   2322:                nfsm_srvsattr(&va);
                   2323:        } else {
                   2324:                nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                   2325:                va.va_mode = nfstov_mode(*tl++);
                   2326:        }
1.18      mycroft  2327:        va.va_type = VDIR;
1.1       cgd      2328:        vp = nd.ni_vp;
                   2329:        if (vp != NULL) {
1.15      mycroft  2330:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2331:                if (nd.ni_dvp == vp)
                   2332:                        vrele(nd.ni_dvp);
                   2333:                else
                   2334:                        vput(nd.ni_dvp);
                   2335:                vrele(vp);
                   2336:                error = EEXIST;
1.23      fvdl     2337:                goto out;
1.1       cgd      2338:        }
1.23      fvdl     2339:        nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2340:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
                   2341:        if (!error) {
                   2342:                vp = nd.ni_vp;
1.44      perry    2343:                memset((caddr_t)fhp, 0, sizeof(nfh));
1.23      fvdl     2344:                fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   2345:                error = VFS_VPTOFH(vp, &fhp->fh_fid);
                   2346:                if (!error)
1.79      fvdl     2347:                        error = VOP_GETATTR(vp, &va, cred, procp);
1.1       cgd      2348:                vput(vp);
                   2349:        }
1.23      fvdl     2350: out:
                   2351:        if (dirp) {
1.79      fvdl     2352:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     2353:                vrele(dirp);
                   2354:        }
                   2355:        nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
                   2356:        if (v3) {
                   2357:                if (!error) {
                   2358:                        nfsm_srvpostop_fh(fhp);
                   2359:                        nfsm_srvpostop_attr(0, &va);
                   2360:                }
                   2361:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2362:        } else {
                   2363:                nfsm_srvfhtom(fhp, v3);
                   2364:                nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
                   2365:                nfsm_srvfillattr(&va, fp);
                   2366:        }
                   2367:        return (0);
1.1       cgd      2368: nfsmout:
1.23      fvdl     2369:        if (dirp)
                   2370:                vrele(dirp);
1.15      mycroft  2371:        VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2372:        if (nd.ni_dvp == nd.ni_vp)
                   2373:                vrele(nd.ni_dvp);
                   2374:        else
                   2375:                vput(nd.ni_dvp);
                   2376:        if (nd.ni_vp)
                   2377:                vrele(nd.ni_vp);
                   2378:        return (error);
                   2379: }
                   2380:
                   2381: /*
                   2382:  * nfs rmdir service
                   2383:  */
1.22      christos 2384: int
1.79      fvdl     2385: nfsrv_rmdir(nfsd, slp, procp, mrq)
1.23      fvdl     2386:        struct nfsrv_descript *nfsd;
                   2387:        struct nfssvc_sock *slp;
1.79      fvdl     2388:        struct proc *procp;
1.23      fvdl     2389:        struct mbuf **mrq;
1.1       cgd      2390: {
1.23      fvdl     2391:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2392:        struct mbuf *nam = nfsd->nd_nam;
                   2393:        caddr_t dpos = nfsd->nd_dpos;
                   2394:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2395:        u_int32_t *tl;
                   2396:        int32_t t1;
1.1       cgd      2397:        caddr_t bpos;
1.23      fvdl     2398:        int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
                   2399:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      2400:        char *cp2;
                   2401:        struct mbuf *mb, *mreq;
1.23      fvdl     2402:        struct vnode *vp, *dirp = (struct vnode *)0;
                   2403:        struct vattr dirfor, diraft;
                   2404:        nfsfh_t nfh;
1.1       cgd      2405:        fhandle_t *fhp;
                   2406:        struct nameidata nd;
1.15      mycroft  2407:        u_quad_t frev;
1.1       cgd      2408:
                   2409:        fhp = &nfh.fh_generic;
                   2410:        nfsm_srvmtofh(fhp);
1.23      fvdl     2411:        nfsm_srvnamesiz(len);
1.15      mycroft  2412:        nd.ni_cnd.cn_cred = cred;
                   2413:        nd.ni_cnd.cn_nameiop = DELETE;
                   2414:        nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1.23      fvdl     2415:        error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1.79      fvdl     2416:                &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     2417:        if (dirp) {
                   2418:                if (v3)
1.79      fvdl     2419:                        dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
                   2420:                                procp);
1.23      fvdl     2421:                else {
                   2422:                        vrele(dirp);
                   2423:                        dirp = (struct vnode *)0;
                   2424:                }
                   2425:        }
                   2426:        if (error) {
                   2427:                nfsm_reply(NFSX_WCCDATA(v3));
                   2428:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2429:                if (dirp)
                   2430:                        vrele(dirp);
                   2431:                return (0);
                   2432:        }
1.1       cgd      2433:        vp = nd.ni_vp;
                   2434:        if (vp->v_type != VDIR) {
                   2435:                error = ENOTDIR;
                   2436:                goto out;
                   2437:        }
                   2438:        /*
                   2439:         * No rmdir "." please.
                   2440:         */
                   2441:        if (nd.ni_dvp == vp) {
                   2442:                error = EINVAL;
                   2443:                goto out;
                   2444:        }
                   2445:        /*
                   2446:         * The root of a mounted filesystem cannot be deleted.
                   2447:         */
                   2448:        if (vp->v_flag & VROOT)
                   2449:                error = EBUSY;
                   2450: out:
                   2451:        if (!error) {
1.23      fvdl     2452:                nqsrv_getl(nd.ni_dvp, ND_WRITE);
                   2453:                nqsrv_getl(vp, ND_WRITE);
1.15      mycroft  2454:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1.1       cgd      2455:        } else {
1.15      mycroft  2456:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1.1       cgd      2457:                if (nd.ni_dvp == nd.ni_vp)
                   2458:                        vrele(nd.ni_dvp);
                   2459:                else
                   2460:                        vput(nd.ni_dvp);
                   2461:                vput(vp);
                   2462:        }
1.23      fvdl     2463:        if (dirp) {
1.79      fvdl     2464:                diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
1.23      fvdl     2465:                vrele(dirp);
                   2466:        }
                   2467:        nfsm_reply(NFSX_WCCDATA(v3));
                   2468:        if (v3) {
                   2469:                nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
                   2470:                return (0);
                   2471:        }
1.1       cgd      2472:        nfsm_srvdone;
                   2473: }
                   2474:
                   2475: /*
                   2476:  * nfs readdir service
                   2477:  * - mallocs what it thinks is enough to read
                   2478:  *     count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
                   2479:  * - calls VOP_READDIR()
                   2480:  * - loops around building the reply
                   2481:  *     if the output generated exceeds count break out of loop
                   2482:  *     The nfsm_clget macro is used here so that the reply will be packed
                   2483:  *     tightly in mbuf clusters.
                   2484:  * - it only knows that it has encountered eof when the VOP_READDIR()
                   2485:  *     reads nothing
                   2486:  * - as such one readdir rpc will return eof false although you are there
                   2487:  *     and then the next will return eof
1.11      ws       2488:  * - it trims out records with d_fileno == 0
1.1       cgd      2489:  *     this doesn't matter for Unix clients, but they might confuse clients
                   2490:  *     for other os'.
1.25      jtk      2491:  * - it trims out records with d_type == DT_WHT
                   2492:  *     these cannot be seen through NFS (unless we extend the protocol)
1.1       cgd      2493:  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
                   2494:  *     than requested, but this may not apply to all filesystems. For
                   2495:  *     example, client NFS does not { although it is never remote mounted
                   2496:  *     anyhow }
1.23      fvdl     2497:  *     The alternate call nfsrv_readdirplus() does lookups as well.
1.1       cgd      2498:  * PS: The NFS protocol spec. does not clarify what the "count" byte
                   2499:  *     argument is a count of.. just name strings and file id's or the
                   2500:  *     entire reply rpc or ...
                   2501:  *     I tried just file name and id sizes and it confused the Sun client,
                   2502:  *     so I am using the full rpc size now. The "paranoia.." comment refers
                   2503:  *     to including the status longwords that are not a part of the dir.
                   2504:  *     "entry" structures, but are in the rpc.
                   2505:  */
1.15      mycroft  2506: struct flrep {
1.23      fvdl     2507:        nfsuint64 fl_off;
                   2508:        u_int32_t fl_postopok;
                   2509:        u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
                   2510:        u_int32_t fl_fhok;
                   2511:        u_int32_t fl_fhsize;
                   2512:        u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
1.15      mycroft  2513: };
                   2514:
1.22      christos 2515: int
1.79      fvdl     2516: nfsrv_readdir(nfsd, slp, procp, mrq)
1.23      fvdl     2517:        struct nfsrv_descript *nfsd;
                   2518:        struct nfssvc_sock *slp;
1.79      fvdl     2519:        struct proc *procp;
1.23      fvdl     2520:        struct mbuf **mrq;
1.1       cgd      2521: {
1.23      fvdl     2522:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2523:        struct mbuf *nam = nfsd->nd_nam;
                   2524:        caddr_t dpos = nfsd->nd_dpos;
                   2525:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2526:        char *bp, *be;
                   2527:        struct mbuf *mp;
                   2528:        struct dirent *dp;
                   2529:        caddr_t cp;
                   2530:        u_int32_t *tl;
                   2531:        int32_t t1;
1.1       cgd      2532:        caddr_t bpos;
1.67      matt     2533:        struct mbuf *mb, *mreq, *mp2;
1.15      mycroft  2534:        char *cpos, *cend, *cp2, *rbuf;
1.1       cgd      2535:        struct vnode *vp;
1.23      fvdl     2536:        struct vattr at;
                   2537:        nfsfh_t nfh;
1.1       cgd      2538:        fhandle_t *fhp;
                   2539:        struct uio io;
                   2540:        struct iovec iv;
1.23      fvdl     2541:        int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
                   2542:        int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
                   2543:        int v3 = (nfsd->nd_flag & ND_NFSV3);
                   2544:        u_quad_t frev, off, toff, verf;
1.38      fvdl     2545:        off_t *cookies = NULL, *cookiep;
                   2546:        nfsuint64 jar;
1.15      mycroft  2547:
1.1       cgd      2548:        fhp = &nfh.fh_generic;
                   2549:        nfsm_srvmtofh(fhp);
1.23      fvdl     2550:        if (v3) {
                   2551:                nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1.48      fair     2552:                toff = fxdr_hyper(tl);
1.23      fvdl     2553:                tl += 2;
1.48      fair     2554:                verf = fxdr_hyper(tl);
1.23      fvdl     2555:                tl += 2;
                   2556:        } else {
                   2557:                nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
                   2558:                toff = fxdr_unsigned(u_quad_t, *tl++);
                   2559:        }
                   2560:        off = toff;
1.1       cgd      2561:        cnt = fxdr_unsigned(int, *tl);
1.23      fvdl     2562:        siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
                   2563:        xfer = NFS_SRVMAXDATA(nfsd);
                   2564:        if (siz > xfer)
                   2565:                siz = xfer;
1.1       cgd      2566:        fullsiz = siz;
1.23      fvdl     2567:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  2568:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.39      fvdl     2569:        if (!error && vp->v_type != VDIR) {
                   2570:                error = ENOTDIR;
                   2571:                vput(vp);
                   2572:        }
1.23      fvdl     2573:        if (error) {
                   2574:                nfsm_reply(NFSX_UNSIGNED);
                   2575:                nfsm_srvpostop_attr(getret, &at);
                   2576:                return (0);
                   2577:        }
                   2578:        nqsrv_getl(vp, ND_READ);
                   2579:        if (v3) {
1.79      fvdl     2580:                error = getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     2581: #ifdef NFS3_STRICTVERF
                   2582:                /*
                   2583:                 * XXX This check is too strict for Solaris 2.5 clients.
                   2584:                 */
                   2585:                if (!error && toff && verf != at.va_filerev)
                   2586:                        error = NFSERR_BAD_COOKIE;
                   2587: #endif
                   2588:        }
                   2589:        if (!error)
1.79      fvdl     2590:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
1.22      christos 2591:        if (error) {
1.1       cgd      2592:                vput(vp);
1.23      fvdl     2593:                nfsm_reply(NFSX_POSTOPATTR(v3));
                   2594:                nfsm_srvpostop_attr(getret, &at);
                   2595:                return (0);
1.1       cgd      2596:        }
1.42      fvdl     2597:        VOP_UNLOCK(vp, 0);
1.56      thorpej  2598:        rbuf = malloc(siz, M_TEMP, M_WAITOK);
1.1       cgd      2599: again:
                   2600:        iv.iov_base = rbuf;
                   2601:        iv.iov_len = fullsiz;
                   2602:        io.uio_iov = &iv;
                   2603:        io.uio_iovcnt = 1;
1.15      mycroft  2604:        io.uio_offset = (off_t)off;
1.1       cgd      2605:        io.uio_resid = fullsiz;
                   2606:        io.uio_segflg = UIO_SYSSPACE;
                   2607:        io.uio_rw = UIO_READ;
1.79      fvdl     2608:        io.uio_procp = (struct proc *)0;
1.23      fvdl     2609:        eofflag = 0;
1.42      fvdl     2610:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.23      fvdl     2611:
1.42      fvdl     2612:        error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
1.23      fvdl     2613:
1.15      mycroft  2614:        off = (off_t)io.uio_offset;
1.23      fvdl     2615:        if (!cookies && !error)
                   2616:                error = NFSERR_PERM;
                   2617:        if (v3) {
1.79      fvdl     2618:                getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     2619:                if (!error)
                   2620:                        error = getret;
                   2621:        }
                   2622:
1.42      fvdl     2623:        VOP_UNLOCK(vp, 0);
1.1       cgd      2624:        if (error) {
                   2625:                vrele(vp);
1.56      thorpej  2626:                free((caddr_t)rbuf, M_TEMP);
1.23      fvdl     2627:                if (cookies)
                   2628:                        free((caddr_t)cookies, M_TEMP);
                   2629:                nfsm_reply(NFSX_POSTOPATTR(v3));
                   2630:                nfsm_srvpostop_attr(getret, &at);
                   2631:                return (0);
1.1       cgd      2632:        }
                   2633:        if (io.uio_resid) {
                   2634:                siz -= io.uio_resid;
                   2635:
                   2636:                /*
                   2637:                 * If nothing read, return eof
                   2638:                 * rpc reply
                   2639:                 */
                   2640:                if (siz == 0) {
                   2641:                        vrele(vp);
1.23      fvdl     2642:                        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
                   2643:                                2 * NFSX_UNSIGNED);
                   2644:                        if (v3) {
                   2645:                                nfsm_srvpostop_attr(getret, &at);
                   2646:                                nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.48      fair     2647:                                txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2648:                                tl += 2;
                   2649:                        } else
                   2650:                                nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.1       cgd      2651:                        *tl++ = nfs_false;
                   2652:                        *tl = nfs_true;
1.56      thorpej  2653:                        free((caddr_t)rbuf, M_TEMP);
                   2654:                        free((caddr_t)cookies, M_TEMP);
1.1       cgd      2655:                        return (0);
                   2656:                }
                   2657:        }
                   2658:
                   2659:        /*
                   2660:         * Check for degenerate cases of nothing useful read.
                   2661:         * If so go try again
                   2662:         */
1.8       ws       2663:        cpos = rbuf;
1.1       cgd      2664:        cend = rbuf + siz;
1.23      fvdl     2665:        dp = (struct dirent *)cpos;
                   2666:        cookiep = cookies;
                   2667:
1.28      fvdl     2668:        while (cpos < cend && ncookies > 0 &&
                   2669:                (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
1.23      fvdl     2670:                cpos += dp->d_reclen;
1.11      ws       2671:                dp = (struct dirent *)cpos;
1.23      fvdl     2672:                cookiep++;
                   2673:                ncookies--;
1.1       cgd      2674:        }
1.23      fvdl     2675:        if (cpos >= cend || ncookies == 0) {
                   2676:                toff = off;
1.1       cgd      2677:                siz = fullsiz;
                   2678:                goto again;
                   2679:        }
                   2680:
1.23      fvdl     2681:        len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
                   2682:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
                   2683:        if (v3) {
                   2684:                nfsm_srvpostop_attr(getret, &at);
                   2685:                nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair     2686:                txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2687:        }
1.15      mycroft  2688:        mp = mp2 = mb;
                   2689:        bp = bpos;
                   2690:        be = bp + M_TRAILINGSPACE(mp);
                   2691:
                   2692:        /* Loop through the records and build reply */
1.23      fvdl     2693:        while (cpos < cend && ncookies > 0) {
1.25      jtk      2694:                if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
1.15      mycroft  2695:                        nlen = dp->d_namlen;
                   2696:                        rem = nfsm_rndup(nlen)-nlen;
1.23      fvdl     2697:                        len += (4 * NFSX_UNSIGNED + nlen + rem);
                   2698:                        if (v3)
                   2699:                                len += 2 * NFSX_UNSIGNED;
1.15      mycroft  2700:                        if (len > cnt) {
                   2701:                                eofflag = 0;
                   2702:                                break;
                   2703:                        }
                   2704:                        /*
                   2705:                         * Build the directory record xdr from
                   2706:                         * the dirent entry.
                   2707:                         */
                   2708:                        nfsm_clget;
                   2709:                        *tl = nfs_true;
                   2710:                        bp += NFSX_UNSIGNED;
1.23      fvdl     2711:                        if (v3) {
                   2712:                                nfsm_clget;
                   2713:                                *tl = 0;
                   2714:                                bp += NFSX_UNSIGNED;
                   2715:                        }
1.15      mycroft  2716:                        nfsm_clget;
                   2717:                        *tl = txdr_unsigned(dp->d_fileno);
                   2718:                        bp += NFSX_UNSIGNED;
                   2719:                        nfsm_clget;
                   2720:                        *tl = txdr_unsigned(nlen);
                   2721:                        bp += NFSX_UNSIGNED;
                   2722:
                   2723:                        /* And loop around copying the name */
                   2724:                        xfer = nlen;
                   2725:                        cp = dp->d_name;
                   2726:                        while (xfer > 0) {
                   2727:                                nfsm_clget;
                   2728:                                if ((bp+xfer) > be)
                   2729:                                        tsiz = be-bp;
                   2730:                                else
                   2731:                                        tsiz = xfer;
1.44      perry    2732:                                memcpy(bp, cp, tsiz);
1.15      mycroft  2733:                                bp += tsiz;
                   2734:                                xfer -= tsiz;
                   2735:                                if (xfer > 0)
                   2736:                                        cp += tsiz;
                   2737:                        }
1.23      fvdl     2738:                        /* And null pad to an int32_t boundary */
1.15      mycroft  2739:                        for (i = 0; i < rem; i++)
                   2740:                                *bp++ = '\0';
                   2741:                        nfsm_clget;
                   2742:
                   2743:                        /* Finish off the record */
1.48      fair     2744:                        txdr_hyper(*cookiep, &jar);
1.23      fvdl     2745:                        if (v3) {
1.38      fvdl     2746:                                *tl = jar.nfsuquad[0];
1.23      fvdl     2747:                                bp += NFSX_UNSIGNED;
                   2748:                                nfsm_clget;
                   2749:                        }
1.38      fvdl     2750:                        *tl = jar.nfsuquad[1];
1.15      mycroft  2751:                        bp += NFSX_UNSIGNED;
                   2752:                }
                   2753:                cpos += dp->d_reclen;
                   2754:                dp = (struct dirent *)cpos;
1.23      fvdl     2755:                cookiep++;
                   2756:                ncookies--;
1.15      mycroft  2757:        }
1.1       cgd      2758:        vrele(vp);
1.15      mycroft  2759:        nfsm_clget;
                   2760:        *tl = nfs_false;
                   2761:        bp += NFSX_UNSIGNED;
                   2762:        nfsm_clget;
                   2763:        if (eofflag)
                   2764:                *tl = nfs_true;
                   2765:        else
                   2766:                *tl = nfs_false;
                   2767:        bp += NFSX_UNSIGNED;
                   2768:        if (mp != mb) {
                   2769:                if (bp < be)
                   2770:                        mp->m_len = bp - mtod(mp, caddr_t);
                   2771:        } else
                   2772:                mp->m_len += bp - bpos;
1.56      thorpej  2773:        free((caddr_t)rbuf, M_TEMP);
                   2774:        free((caddr_t)cookies, M_TEMP);
1.15      mycroft  2775:        nfsm_srvdone;
                   2776: }
                   2777:
1.22      christos 2778: int
1.79      fvdl     2779: nfsrv_readdirplus(nfsd, slp, procp, mrq)
1.23      fvdl     2780:        struct nfsrv_descript *nfsd;
                   2781:        struct nfssvc_sock *slp;
1.79      fvdl     2782:        struct proc *procp;
1.23      fvdl     2783:        struct mbuf **mrq;
1.15      mycroft  2784: {
1.23      fvdl     2785:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   2786:        struct mbuf *nam = nfsd->nd_nam;
                   2787:        caddr_t dpos = nfsd->nd_dpos;
                   2788:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 2789:        char *bp, *be;
                   2790:        struct mbuf *mp;
                   2791:        struct dirent *dp;
                   2792:        caddr_t cp;
                   2793:        u_int32_t *tl;
                   2794:        int32_t t1;
1.15      mycroft  2795:        caddr_t bpos;
1.67      matt     2796:        struct mbuf *mb, *mreq, *mp2;
1.15      mycroft  2797:        char *cpos, *cend, *cp2, *rbuf;
                   2798:        struct vnode *vp, *nvp;
                   2799:        struct flrep fl;
1.23      fvdl     2800:        nfsfh_t nfh;
                   2801:        fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
1.15      mycroft  2802:        struct uio io;
                   2803:        struct iovec iv;
1.23      fvdl     2804:        struct vattr va, at, *vap = &va;
                   2805:        struct nfs_fattr *fp;
                   2806:        int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
                   2807:        int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
                   2808:        u_quad_t frev, off, toff, verf;
1.38      fvdl     2809:        off_t *cookies = NULL, *cookiep;
1.15      mycroft  2810:
                   2811:        fhp = &nfh.fh_generic;
                   2812:        nfsm_srvmtofh(fhp);
1.23      fvdl     2813:        nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
1.48      fair     2814:        toff = fxdr_hyper(tl);
1.23      fvdl     2815:        tl += 2;
1.48      fair     2816:        verf = fxdr_hyper(tl);
1.23      fvdl     2817:        tl += 2;
                   2818:        siz = fxdr_unsigned(int, *tl++);
                   2819:        cnt = fxdr_unsigned(int, *tl);
                   2820:        off = toff;
                   2821:        siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
                   2822:        xfer = NFS_SRVMAXDATA(nfsd);
                   2823:        if (siz > xfer)
                   2824:                siz = xfer;
1.15      mycroft  2825:        fullsiz = siz;
1.23      fvdl     2826:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  2827:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.39      fvdl     2828:        if (!error && vp->v_type != VDIR) {
                   2829:                error = ENOTDIR;
                   2830:                vput(vp);
                   2831:        }
1.23      fvdl     2832:        if (error) {
                   2833:                nfsm_reply(NFSX_UNSIGNED);
                   2834:                nfsm_srvpostop_attr(getret, &at);
                   2835:                return (0);
                   2836:        }
1.79      fvdl     2837:        error = getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     2838: #ifdef NFS3_STRICTVERF
                   2839:        /*
                   2840:         * XXX This check is too strict for Solaris 2.5 clients.
                   2841:         */
                   2842:        if (!error && toff && verf != at.va_filerev)
                   2843:                error = NFSERR_BAD_COOKIE;
                   2844: #endif
                   2845:        if (!error) {
                   2846:                nqsrv_getl(vp, ND_READ);
1.79      fvdl     2847:                error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
1.23      fvdl     2848:        }
1.22      christos 2849:        if (error) {
1.15      mycroft  2850:                vput(vp);
1.23      fvdl     2851:                nfsm_reply(NFSX_V3POSTOPATTR);
                   2852:                nfsm_srvpostop_attr(getret, &at);
                   2853:                return (0);
1.15      mycroft  2854:        }
1.42      fvdl     2855:        VOP_UNLOCK(vp, 0);
1.23      fvdl     2856:
1.56      thorpej  2857:        rbuf = malloc(siz, M_TEMP, M_WAITOK);
1.15      mycroft  2858: again:
                   2859:        iv.iov_base = rbuf;
                   2860:        iv.iov_len = fullsiz;
                   2861:        io.uio_iov = &iv;
                   2862:        io.uio_iovcnt = 1;
                   2863:        io.uio_offset = (off_t)off;
                   2864:        io.uio_resid = fullsiz;
                   2865:        io.uio_segflg = UIO_SYSSPACE;
                   2866:        io.uio_rw = UIO_READ;
1.79      fvdl     2867:        io.uio_procp = (struct proc *)0;
1.23      fvdl     2868:        eofflag = 0;
                   2869:
1.42      fvdl     2870:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2871:
                   2872:        error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
1.23      fvdl     2873:
                   2874:        off = (u_quad_t)io.uio_offset;
1.79      fvdl     2875:        getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     2876:
1.42      fvdl     2877:        VOP_UNLOCK(vp, 0);
1.36      fvdl     2878:
                   2879:        /*
                   2880:         * If the VGET operation doesn't work for this filesystem,
                   2881:         * we can't support readdirplus. Returning NOTSUPP should
                   2882:         * make clients fall back to plain readdir.
                   2883:         * There's no need to check for VPTOFH as well, we wouldn't
                   2884:         * even be here otherwise.
                   2885:         */
                   2886:        if (!getret) {
1.78      thorpej  2887:                if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, &nvp)))
1.36      fvdl     2888:                        getret = (getret == EOPNOTSUPP) ?
                   2889:                                NFSERR_NOTSUPP : NFSERR_IO;
                   2890:                else
                   2891:                        vput(nvp);
                   2892:        }
                   2893:
1.23      fvdl     2894:        if (!cookies && !error)
                   2895:                error = NFSERR_PERM;
                   2896:        if (!error)
                   2897:                error = getret;
1.15      mycroft  2898:        if (error) {
                   2899:                vrele(vp);
1.23      fvdl     2900:                if (cookies)
1.56      thorpej  2901:                        free((caddr_t)cookies, M_TEMP);
                   2902:                free((caddr_t)rbuf, M_TEMP);
1.23      fvdl     2903:                nfsm_reply(NFSX_V3POSTOPATTR);
                   2904:                nfsm_srvpostop_attr(getret, &at);
                   2905:                return (0);
1.15      mycroft  2906:        }
                   2907:        if (io.uio_resid) {
                   2908:                siz -= io.uio_resid;
                   2909:
                   2910:                /*
                   2911:                 * If nothing read, return eof
                   2912:                 * rpc reply
                   2913:                 */
                   2914:                if (siz == 0) {
                   2915:                        vrele(vp);
1.23      fvdl     2916:                        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
                   2917:                                2 * NFSX_UNSIGNED);
                   2918:                        nfsm_srvpostop_attr(getret, &at);
                   2919:                        nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1.48      fair     2920:                        txdr_hyper(at.va_filerev, tl);
1.23      fvdl     2921:                        tl += 2;
1.15      mycroft  2922:                        *tl++ = nfs_false;
                   2923:                        *tl = nfs_true;
1.56      thorpej  2924:                        free((caddr_t)cookies, M_TEMP);
                   2925:                        free((caddr_t)rbuf, M_TEMP);
1.15      mycroft  2926:                        return (0);
                   2927:                }
                   2928:        }
                   2929:
                   2930:        /*
                   2931:         * Check for degenerate cases of nothing useful read.
                   2932:         * If so go try again
                   2933:         */
                   2934:        cpos = rbuf;
                   2935:        cend = rbuf + siz;
1.23      fvdl     2936:        dp = (struct dirent *)cpos;
                   2937:        cookiep = cookies;
                   2938:
1.29      fvdl     2939:        while (cpos < cend && ncookies > 0 &&
                   2940:                (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
1.23      fvdl     2941:                cpos += dp->d_reclen;
1.15      mycroft  2942:                dp = (struct dirent *)cpos;
1.23      fvdl     2943:                cookiep++;
                   2944:                ncookies--;
1.15      mycroft  2945:        }
1.23      fvdl     2946:        if (cpos >= cend || ncookies == 0) {
                   2947:                toff = off;
1.15      mycroft  2948:                siz = fullsiz;
                   2949:                goto again;
                   2950:        }
                   2951:
1.23      fvdl     2952:        dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
                   2953:        nfsm_reply(cnt);
                   2954:        nfsm_srvpostop_attr(getret, &at);
                   2955:        nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1.48      fair     2956:        txdr_hyper(at.va_filerev, tl);
1.15      mycroft  2957:        mp = mp2 = mb;
                   2958:        bp = bpos;
                   2959:        be = bp + M_TRAILINGSPACE(mp);
1.1       cgd      2960:
                   2961:        /* Loop through the records and build reply */
1.23      fvdl     2962:        while (cpos < cend && ncookies > 0) {
1.25      jtk      2963:                if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
1.1       cgd      2964:                        nlen = dp->d_namlen;
                   2965:                        rem = nfsm_rndup(nlen)-nlen;
                   2966:
                   2967:                        /*
1.15      mycroft  2968:                         * For readdir_and_lookup get the vnode using
                   2969:                         * the file number.
1.1       cgd      2970:                         */
1.78      thorpej  2971:                        if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
1.15      mycroft  2972:                                goto invalid;
1.44      perry    2973:                        memset((caddr_t)nfhp, 0, NFSX_V3FH);
1.23      fvdl     2974:                        nfhp->fh_fsid =
1.15      mycroft  2975:                                nvp->v_mount->mnt_stat.f_fsid;
1.23      fvdl     2976:                        if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
1.15      mycroft  2977:                                vput(nvp);
                   2978:                                goto invalid;
                   2979:                        }
1.79      fvdl     2980:                        if (VOP_GETATTR(nvp, vap, cred, procp)) {
1.15      mycroft  2981:                                vput(nvp);
                   2982:                                goto invalid;
                   2983:                        }
                   2984:                        vput(nvp);
1.23      fvdl     2985:
                   2986:                        /*
                   2987:                         * If either the dircount or maxcount will be
                   2988:                         * exceeded, get out now. Both of these lengths
                   2989:                         * are calculated conservatively, including all
                   2990:                         * XDR overheads.
                   2991:                         */
1.52      fvdl     2992:                        len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
1.23      fvdl     2993:                                NFSX_V3POSTOPATTR);
                   2994:                        dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
                   2995:                        if (len > cnt || dirlen > fullsiz) {
1.1       cgd      2996:                                eofflag = 0;
                   2997:                                break;
                   2998:                        }
1.23      fvdl     2999:
1.15      mycroft  3000:                        /*
                   3001:                         * Build the directory record xdr from
                   3002:                         * the dirent entry.
                   3003:                         */
1.23      fvdl     3004:                        fp = (struct nfs_fattr *)&fl.fl_fattr;
                   3005:                        nfsm_srvfillattr(vap, fp);
                   3006:                        fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
                   3007:                        fl.fl_fhok = nfs_true;
                   3008:                        fl.fl_postopok = nfs_true;
1.48      fair     3009:                        txdr_hyper(*cookiep, fl.fl_off.nfsuquad);
1.23      fvdl     3010:
1.1       cgd      3011:                        nfsm_clget;
                   3012:                        *tl = nfs_true;
                   3013:                        bp += NFSX_UNSIGNED;
1.23      fvdl     3014:                        nfsm_clget;
                   3015:                        *tl = 0;
                   3016:                        bp += NFSX_UNSIGNED;
1.1       cgd      3017:                        nfsm_clget;
1.11      ws       3018:                        *tl = txdr_unsigned(dp->d_fileno);
1.1       cgd      3019:                        bp += NFSX_UNSIGNED;
                   3020:                        nfsm_clget;
                   3021:                        *tl = txdr_unsigned(nlen);
                   3022:                        bp += NFSX_UNSIGNED;
                   3023:
1.15      mycroft  3024:                        /* And loop around copying the name */
1.1       cgd      3025:                        xfer = nlen;
                   3026:                        cp = dp->d_name;
                   3027:                        while (xfer > 0) {
                   3028:                                nfsm_clget;
1.23      fvdl     3029:                                if ((bp + xfer) > be)
                   3030:                                        tsiz = be - bp;
1.1       cgd      3031:                                else
                   3032:                                        tsiz = xfer;
1.44      perry    3033:                                memcpy(bp, cp, tsiz);
1.1       cgd      3034:                                bp += tsiz;
                   3035:                                xfer -= tsiz;
                   3036:                                if (xfer > 0)
                   3037:                                        cp += tsiz;
                   3038:                        }
1.23      fvdl     3039:                        /* And null pad to an int32_t boundary */
1.1       cgd      3040:                        for (i = 0; i < rem; i++)
                   3041:                                *bp++ = '\0';
                   3042:
1.23      fvdl     3043:                        /*
                   3044:                         * Now copy the flrep structure out.
                   3045:                         */
                   3046:                        xfer = sizeof (struct flrep);
                   3047:                        cp = (caddr_t)&fl;
                   3048:                        while (xfer > 0) {
                   3049:                                nfsm_clget;
                   3050:                                if ((bp + xfer) > be)
                   3051:                                        tsiz = be - bp;
                   3052:                                else
                   3053:                                        tsiz = xfer;
1.44      perry    3054:                                memcpy(bp, cp, tsiz);
1.23      fvdl     3055:                                bp += tsiz;
                   3056:                                xfer -= tsiz;
                   3057:                                if (xfer > 0)
                   3058:                                        cp += tsiz;
                   3059:                        }
1.8       ws       3060:                }
1.15      mycroft  3061: invalid:
1.1       cgd      3062:                cpos += dp->d_reclen;
1.11      ws       3063:                dp = (struct dirent *)cpos;
1.23      fvdl     3064:                cookiep++;
                   3065:                ncookies--;
1.1       cgd      3066:        }
1.15      mycroft  3067:        vrele(vp);
1.1       cgd      3068:        nfsm_clget;
                   3069:        *tl = nfs_false;
                   3070:        bp += NFSX_UNSIGNED;
                   3071:        nfsm_clget;
                   3072:        if (eofflag)
                   3073:                *tl = nfs_true;
                   3074:        else
                   3075:                *tl = nfs_false;
                   3076:        bp += NFSX_UNSIGNED;
1.15      mycroft  3077:        if (mp != mb) {
                   3078:                if (bp < be)
                   3079:                        mp->m_len = bp - mtod(mp, caddr_t);
                   3080:        } else
                   3081:                mp->m_len += bp - bpos;
1.56      thorpej  3082:        free((caddr_t)cookies, M_TEMP);
                   3083:        free((caddr_t)rbuf, M_TEMP);
1.23      fvdl     3084:        nfsm_srvdone;
                   3085: }
                   3086:
                   3087: /*
                   3088:  * nfs commit service
                   3089:  */
                   3090: int
1.79      fvdl     3091: nfsrv_commit(nfsd, slp, procp, mrq)
1.23      fvdl     3092:        struct nfsrv_descript *nfsd;
                   3093:        struct nfssvc_sock *slp;
1.79      fvdl     3094:        struct proc *procp;
1.23      fvdl     3095:        struct mbuf **mrq;
                   3096: {
                   3097:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3098:        struct mbuf *nam = nfsd->nd_nam;
                   3099:        caddr_t dpos = nfsd->nd_dpos;
                   3100:        struct ucred *cred = &nfsd->nd_cr;
                   3101:        struct vattr bfor, aft;
                   3102:        struct vnode *vp;
                   3103:        nfsfh_t nfh;
                   3104:        fhandle_t *fhp;
1.54      augustss 3105:        u_int32_t *tl;
                   3106:        int32_t t1;
1.23      fvdl     3107:        caddr_t bpos;
                   3108:        int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
                   3109:        char *cp2;
1.67      matt     3110:        struct mbuf *mb, *mreq;
1.65      bouyer   3111:        u_quad_t frev, off, end;
1.23      fvdl     3112:
                   3113: #ifndef nolint
                   3114:        cache = 0;
                   3115: #endif
                   3116:        fhp = &nfh.fh_generic;
                   3117:        nfsm_srvmtofh(fhp);
                   3118:        nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
                   3119:
1.48      fair     3120:        off = fxdr_hyper(tl);
1.23      fvdl     3121:        tl += 2;
                   3122:        cnt = fxdr_unsigned(int, *tl);
                   3123:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  3124:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3125:        if (error) {
                   3126:                nfsm_reply(2 * NFSX_UNSIGNED);
                   3127:                nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
                   3128:                return (0);
                   3129:        }
1.79      fvdl     3130:        for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
1.65      bouyer   3131:        end = (cnt > 0) ? off + cnt : vp->v_size;
                   3132:        if (end < off || end > vp->v_size)
                   3133:                end = vp->v_size;
1.80      bouyer   3134:        if (off < vp->v_size)
                   3135:                error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end, procp);
                   3136:        /* else error == 0, from nfsrv_fhtovp() */
1.79      fvdl     3137:        aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
1.23      fvdl     3138:        vput(vp);
                   3139:        nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
                   3140:        nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
                   3141:        if (!error) {
                   3142:                nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
                   3143:                *tl++ = txdr_unsigned(boottime.tv_sec);
                   3144:                *tl = txdr_unsigned(boottime.tv_usec);
                   3145:        } else
                   3146:                return (0);
1.1       cgd      3147:        nfsm_srvdone;
                   3148: }
                   3149:
                   3150: /*
                   3151:  * nfs statfs service
                   3152:  */
1.22      christos 3153: int
1.79      fvdl     3154: nfsrv_statfs(nfsd, slp, procp, mrq)
1.23      fvdl     3155:        struct nfsrv_descript *nfsd;
                   3156:        struct nfssvc_sock *slp;
1.79      fvdl     3157:        struct proc *procp;
1.23      fvdl     3158:        struct mbuf **mrq;
1.1       cgd      3159: {
1.23      fvdl     3160:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3161:        struct mbuf *nam = nfsd->nd_nam;
                   3162:        caddr_t dpos = nfsd->nd_dpos;
                   3163:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3164:        struct statfs *sf;
                   3165:        struct nfs_statfs *sfp;
                   3166:        u_int32_t *tl;
                   3167:        int32_t t1;
1.1       cgd      3168:        caddr_t bpos;
1.23      fvdl     3169:        int error = 0, rdonly, cache, getret = 1;
                   3170:        int v3 = (nfsd->nd_flag & ND_NFSV3);
1.1       cgd      3171:        char *cp2;
1.67      matt     3172:        struct mbuf *mb, *mreq;
1.1       cgd      3173:        struct vnode *vp;
1.23      fvdl     3174:        struct vattr at;
                   3175:        nfsfh_t nfh;
1.1       cgd      3176:        fhandle_t *fhp;
                   3177:        struct statfs statfs;
1.23      fvdl     3178:        u_quad_t frev, tval;
1.1       cgd      3179:
1.23      fvdl     3180: #ifndef nolint
                   3181:        cache = 0;
                   3182: #endif
1.1       cgd      3183:        fhp = &nfh.fh_generic;
                   3184:        nfsm_srvmtofh(fhp);
1.23      fvdl     3185:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  3186:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3187:        if (error) {
                   3188:                nfsm_reply(NFSX_UNSIGNED);
                   3189:                nfsm_srvpostop_attr(getret, &at);
                   3190:                return (0);
                   3191:        }
1.1       cgd      3192:        sf = &statfs;
1.79      fvdl     3193:        error = VFS_STATFS(vp->v_mount, sf, procp);
                   3194:        getret = VOP_GETATTR(vp, &at, cred, procp);
1.1       cgd      3195:        vput(vp);
1.23      fvdl     3196:        nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
                   3197:        if (v3)
                   3198:                nfsm_srvpostop_attr(getret, &at);
                   3199:        if (error)
                   3200:                return (0);
                   3201:        nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
                   3202:        if (v3) {
1.47      mycroft  3203:                tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_bsize);
1.48      fair     3204:                txdr_hyper(tval, &sfp->sf_tbytes);
1.47      mycroft  3205:                tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_bsize);
1.48      fair     3206:                txdr_hyper(tval, &sfp->sf_fbytes);
1.47      mycroft  3207:                tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_bsize);
1.48      fair     3208:                txdr_hyper(tval, &sfp->sf_abytes);
1.47      mycroft  3209:                tval = (u_quad_t)sf->f_files;
1.48      fair     3210:                txdr_hyper(tval, &sfp->sf_tfiles);
1.47      mycroft  3211:                tval = (u_quad_t)sf->f_ffree;
1.48      fair     3212:                txdr_hyper(tval, &sfp->sf_ffiles);
                   3213:                txdr_hyper(tval, &sfp->sf_afiles);
1.23      fvdl     3214:                sfp->sf_invarsec = 0;
                   3215:        } else {
                   3216:                sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
                   3217:                sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
                   3218:                sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
                   3219:                sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
                   3220:                sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
                   3221:        }
                   3222:        nfsm_srvdone;
                   3223: }
                   3224:
                   3225: /*
                   3226:  * nfs fsinfo service
                   3227:  */
                   3228: int
1.79      fvdl     3229: nfsrv_fsinfo(nfsd, slp, procp, mrq)
1.23      fvdl     3230:        struct nfsrv_descript *nfsd;
                   3231:        struct nfssvc_sock *slp;
1.79      fvdl     3232:        struct proc *procp;
1.23      fvdl     3233:        struct mbuf **mrq;
                   3234: {
                   3235:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3236:        struct mbuf *nam = nfsd->nd_nam;
                   3237:        caddr_t dpos = nfsd->nd_dpos;
                   3238:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3239:        u_int32_t *tl;
                   3240:        struct nfsv3_fsinfo *sip;
                   3241:        int32_t t1;
1.23      fvdl     3242:        caddr_t bpos;
1.69      yamt     3243:        int error = 0, rdonly, cache, getret = 1;
                   3244:        uint32_t maxdata;
1.23      fvdl     3245:        char *cp2;
1.67      matt     3246:        struct mbuf *mb, *mreq;
1.23      fvdl     3247:        struct vnode *vp;
                   3248:        struct vattr at;
                   3249:        nfsfh_t nfh;
                   3250:        fhandle_t *fhp;
1.37      fvdl     3251:        u_quad_t frev, maxfsize;
                   3252:        struct statfs sb;
1.23      fvdl     3253:
                   3254: #ifndef nolint
                   3255:        cache = 0;
                   3256: #endif
                   3257:        fhp = &nfh.fh_generic;
                   3258:        nfsm_srvmtofh(fhp);
                   3259:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  3260:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3261:        if (error) {
                   3262:                nfsm_reply(NFSX_UNSIGNED);
                   3263:                nfsm_srvpostop_attr(getret, &at);
                   3264:                return (0);
1.15      mycroft  3265:        }
1.37      fvdl     3266:
                   3267:        /* XXX Try to make a guess on the max file size. */
1.79      fvdl     3268:        VFS_STATFS(vp->v_mount, &sb, (struct proc *)0);
1.37      fvdl     3269:        maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
                   3270:
1.79      fvdl     3271:        getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     3272:        vput(vp);
                   3273:        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
                   3274:        nfsm_srvpostop_attr(getret, &at);
                   3275:        nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
                   3276:
                   3277:        /*
                   3278:         * XXX
                   3279:         * There should be file system VFS OP(s) to get this information.
                   3280:         * For now, assume ufs.
                   3281:         */
                   3282:        if (slp->ns_so->so_type == SOCK_DGRAM)
1.69      yamt     3283:                maxdata = NFS_MAXDGRAMDATA;
1.23      fvdl     3284:        else
1.69      yamt     3285:                maxdata = NFS_MAXDATA;
                   3286:        sip->fs_rtmax = txdr_unsigned(maxdata);
                   3287:        sip->fs_rtpref = txdr_unsigned(maxdata);
1.23      fvdl     3288:        sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
1.69      yamt     3289:        sip->fs_wtmax = txdr_unsigned(maxdata);
                   3290:        sip->fs_wtpref = txdr_unsigned(maxdata);
1.23      fvdl     3291:        sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
1.69      yamt     3292:        sip->fs_dtpref = txdr_unsigned(maxdata);
1.48      fair     3293:        txdr_hyper(maxfsize, &sip->fs_maxfilesize);
1.23      fvdl     3294:        sip->fs_timedelta.nfsv3_sec = 0;
                   3295:        sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
                   3296:        sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
                   3297:                NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
                   3298:                NFSV3FSINFO_CANSETTIME);
                   3299:        nfsm_srvdone;
                   3300: }
                   3301:
                   3302: /*
                   3303:  * nfs pathconf service
                   3304:  */
                   3305: int
1.79      fvdl     3306: nfsrv_pathconf(nfsd, slp, procp, mrq)
1.23      fvdl     3307:        struct nfsrv_descript *nfsd;
                   3308:        struct nfssvc_sock *slp;
1.79      fvdl     3309:        struct proc *procp;
1.23      fvdl     3310:        struct mbuf **mrq;
                   3311: {
                   3312:        struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
                   3313:        struct mbuf *nam = nfsd->nd_nam;
                   3314:        caddr_t dpos = nfsd->nd_dpos;
                   3315:        struct ucred *cred = &nfsd->nd_cr;
1.54      augustss 3316:        u_int32_t *tl;
                   3317:        struct nfsv3_pathconf *pc;
                   3318:        int32_t t1;
1.23      fvdl     3319:        caddr_t bpos;
1.24      cgd      3320:        int error = 0, rdonly, cache, getret = 1;
                   3321:        register_t linkmax, namemax, chownres, notrunc;
1.23      fvdl     3322:        char *cp2;
1.67      matt     3323:        struct mbuf *mb, *mreq;
1.23      fvdl     3324:        struct vnode *vp;
                   3325:        struct vattr at;
                   3326:        nfsfh_t nfh;
                   3327:        fhandle_t *fhp;
                   3328:        u_quad_t frev;
                   3329:
                   3330: #ifndef nolint
                   3331:        cache = 0;
                   3332: #endif
                   3333:        fhp = &nfh.fh_generic;
                   3334:        nfsm_srvmtofh(fhp);
                   3335:        error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
1.78      thorpej  3336:                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1.23      fvdl     3337:        if (error) {
                   3338:                nfsm_reply(NFSX_UNSIGNED);
                   3339:                nfsm_srvpostop_attr(getret, &at);
                   3340:                return (0);
                   3341:        }
                   3342:        error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
                   3343:        if (!error)
                   3344:                error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
                   3345:        if (!error)
                   3346:                error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
                   3347:        if (!error)
                   3348:                error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
1.79      fvdl     3349:        getret = VOP_GETATTR(vp, &at, cred, procp);
1.23      fvdl     3350:        vput(vp);
                   3351:        nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
                   3352:        nfsm_srvpostop_attr(getret, &at);
                   3353:        if (error)
                   3354:                return (0);
                   3355:        nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
                   3356:
                   3357:        pc->pc_linkmax = txdr_unsigned(linkmax);
                   3358:        pc->pc_namemax = txdr_unsigned(namemax);
                   3359:        pc->pc_notrunc = txdr_unsigned(notrunc);
                   3360:        pc->pc_chownrestricted = txdr_unsigned(chownres);
                   3361:
                   3362:        /*
                   3363:         * These should probably be supported by VOP_PATHCONF(), but
                   3364:         * until msdosfs is exportable (why would you want to?), the
                   3365:         * Unix defaults should be ok.
                   3366:         */
                   3367:        pc->pc_caseinsensitive = nfs_false;
                   3368:        pc->pc_casepreserving = nfs_true;
1.1       cgd      3369:        nfsm_srvdone;
                   3370: }
                   3371:
                   3372: /*
                   3373:  * Null operation, used by clients to ping server
                   3374:  */
                   3375: /* ARGSUSED */
1.22      christos 3376: int
1.79      fvdl     3377: nfsrv_null(nfsd, slp, procp, mrq)
1.23      fvdl     3378:        struct nfsrv_descript *nfsd;
                   3379:        struct nfssvc_sock *slp;
1.79      fvdl     3380:        struct proc *procp;
1.23      fvdl     3381:        struct mbuf **mrq;
1.1       cgd      3382: {
1.23      fvdl     3383:        struct mbuf *mrep = nfsd->nd_mrep;
1.1       cgd      3384:        caddr_t bpos;
1.23      fvdl     3385:        int error = NFSERR_RETVOID, cache = 0;
1.1       cgd      3386:        struct mbuf *mb, *mreq;
1.15      mycroft  3387:        u_quad_t frev;
1.1       cgd      3388:
                   3389:        nfsm_reply(0);
1.23      fvdl     3390:        return (0);
1.1       cgd      3391: }
                   3392:
                   3393: /*
                   3394:  * No operation, used for obsolete procedures
                   3395:  */
                   3396: /* ARGSUSED */
1.22      christos 3397: int
1.79      fvdl     3398: nfsrv_noop(nfsd, slp, procp, mrq)
1.23      fvdl     3399:        struct nfsrv_descript *nfsd;
                   3400:        struct nfssvc_sock *slp;
1.79      fvdl     3401:        struct proc *procp;
1.23      fvdl     3402:        struct mbuf **mrq;
1.1       cgd      3403: {
1.23      fvdl     3404:        struct mbuf *mrep = nfsd->nd_mrep;
1.1       cgd      3405:        caddr_t bpos;
1.22      christos 3406:        int error, cache = 0;
1.1       cgd      3407:        struct mbuf *mb, *mreq;
1.15      mycroft  3408:        u_quad_t frev;
1.1       cgd      3409:
1.15      mycroft  3410:        if (nfsd->nd_repstat)
                   3411:                error = nfsd->nd_repstat;
1.2       cgd      3412:        else
                   3413:                error = EPROCUNAVAIL;
1.1       cgd      3414:        nfsm_reply(0);
1.23      fvdl     3415:        return (0);
1.1       cgd      3416: }
                   3417:
                   3418: /*
                   3419:  * Perform access checking for vnodes obtained from file handles that would
                   3420:  * refer to files already opened by a Unix client. You cannot just use
                   3421:  * vn_writechk() and VOP_ACCESS() for two reasons.
1.15      mycroft  3422:  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
1.27      fvdl     3423:  * 2 - The owner is to be given access irrespective of mode bits for some
                   3424:  *     operations, so that processes that chmod after opening a file don't
                   3425:  *     break. I don't like this because it opens a security hole, but since
                   3426:  *     the nfs server opens a security hole the size of a barn door anyhow,
                   3427:  *     what the heck.
1.31      fvdl     3428:  *
                   3429:  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
                   3430:  * will return EPERM instead of EACCESS. EPERM is always an error.
1.1       cgd      3431:  */
1.22      christos 3432: int
1.79      fvdl     3433: nfsrv_access(vp, flags, cred, rdonly, p, override)
1.54      augustss 3434:        struct vnode *vp;
1.1       cgd      3435:        int flags;
1.54      augustss 3436:        struct ucred *cred;
1.15      mycroft  3437:        int rdonly;
1.79      fvdl     3438:        struct proc *p;
1.1       cgd      3439: {
                   3440:        struct vattr vattr;
                   3441:        int error;
                   3442:        if (flags & VWRITE) {
1.15      mycroft  3443:                /* Just vn_writechk() changed to check rdonly */
1.1       cgd      3444:                /*
                   3445:                 * Disallow write attempts on read-only file systems;
                   3446:                 * unless the file is a socket or a block or character
                   3447:                 * device resident on the file system.
                   3448:                 */
1.15      mycroft  3449:                if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
1.1       cgd      3450:                        switch (vp->v_type) {
1.23      fvdl     3451:                        case VREG:
                   3452:                        case VDIR:
                   3453:                        case VLNK:
1.1       cgd      3454:                                return (EROFS);
1.23      fvdl     3455:                        default:
1.22      christos 3456:                                break;
1.1       cgd      3457:                        }
                   3458:                }
1.59      chs      3459:
1.1       cgd      3460:                /*
1.59      chs      3461:                 * If the vnode is in use as a process's text,
                   3462:                 * we can't allow writing.
1.1       cgd      3463:                 */
1.59      chs      3464:                if (vp->v_flag & VTEXT)
1.40      mrg      3465:                        return (ETXTBSY);
1.1       cgd      3466:        }
1.79      fvdl     3467:        error = VOP_GETATTR(vp, &vattr, cred, p);
1.23      fvdl     3468:        if (error)
1.1       cgd      3469:                return (error);
1.79      fvdl     3470:        error = VOP_ACCESS(vp, flags, cred, p);
1.27      fvdl     3471:        /*
                   3472:         * Allow certain operations for the owner (reads and writes
                   3473:         * on files that are already open).
                   3474:         */
1.31      fvdl     3475:        if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
1.27      fvdl     3476:                error = 0;
                   3477:        return error;
1.1       cgd      3478: }

CVSweb <webmaster@jp.NetBSD.org>