Annotation of Net2/nfs/nfs_vfsops.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Rick Macklem at The University of Guelph.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)nfs_vfsops.c        7.31 (Berkeley) 5/6/91
        !            37:  */
        !            38: 
        !            39: #include "param.h"
        !            40: #include "conf.h"
        !            41: #include "ioctl.h"
        !            42: #include "signal.h"
        !            43: #include "proc.h"
        !            44: #include "namei.h"
        !            45: #include "vnode.h"
        !            46: #include "mount.h"
        !            47: #include "buf.h"
        !            48: #include "mbuf.h"
        !            49: #include "socket.h"
        !            50: #include "systm.h"
        !            51: 
        !            52: #include "../net/if.h"
        !            53: #include "../net/route.h"
        !            54: #include "../netinet/in.h"
        !            55: 
        !            56: #include "nfsv2.h"
        !            57: #include "nfsnode.h"
        !            58: #include "nfsmount.h"
        !            59: #include "nfs.h"
        !            60: #include "xdr_subs.h"
        !            61: #include "nfsm_subs.h"
        !            62: #include "nfsdiskless.h"
        !            63: 
        !            64: /*
        !            65:  * nfs vfs operations.
        !            66:  */
        !            67: struct vfsops nfs_vfsops = {
        !            68:        nfs_mount,
        !            69:        nfs_start,
        !            70:        nfs_unmount,
        !            71:        nfs_root,
        !            72:        nfs_quotactl,
        !            73:        nfs_statfs,
        !            74:        nfs_sync,
        !            75:        nfs_fhtovp,
        !            76:        nfs_vptofh,
        !            77:        nfs_init,
        !            78: };
        !            79: 
        !            80: static u_char nfs_mntid;
        !            81: extern u_long nfs_procids[NFS_NPROCS];
        !            82: extern u_long nfs_prog, nfs_vers;
        !            83: struct nfs_diskless nfs_diskless;
        !            84: void nfs_disconnect();
        !            85: 
        !            86: #define TRUE   1
        !            87: #define        FALSE   0
        !            88: 
        !            89: /*
        !            90:  * nfs statfs call
        !            91:  */
        !            92: nfs_statfs(mp, sbp, p)
        !            93:        struct mount *mp;
        !            94:        register struct statfs *sbp;
        !            95:        struct proc *p;
        !            96: {
        !            97:        register struct vnode *vp;
        !            98:        register struct nfsv2_statfs *sfp;
        !            99:        register caddr_t cp;
        !           100:        register long t1;
        !           101:        caddr_t bpos, dpos, cp2;
        !           102:        u_long xid;
        !           103:        int error = 0;
        !           104:        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        !           105:        struct nfsmount *nmp;
        !           106:        struct ucred *cred;
        !           107:        struct nfsnode *np;
        !           108: 
        !           109:        nmp = VFSTONFS(mp);
        !           110:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           111:                return (error);
        !           112:        vp = NFSTOV(np);
        !           113:        nfsstats.rpccnt[NFSPROC_STATFS]++;
        !           114:        cred = crget();
        !           115:        cred->cr_ngroups = 1;
        !           116:        nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
        !           117:        nfsm_fhtom(vp);
        !           118:        nfsm_request(vp, NFSPROC_STATFS, p, 0);
        !           119:        nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
        !           120:        sbp->f_type = MOUNT_NFS;
        !           121:        sbp->f_flags = nmp->nm_flag;
        !           122:        sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize);
        !           123:        sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize);
        !           124:        sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
        !           125:        sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
        !           126:        sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
        !           127:        sbp->f_files = 0;
        !           128:        sbp->f_ffree = 0;
        !           129:        if (sbp != &mp->mnt_stat) {
        !           130:                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
        !           131:                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
        !           132:        }
        !           133:        nfsm_reqdone;
        !           134:        nfs_nput(vp);
        !           135:        crfree(cred);
        !           136:        return (error);
        !           137: }
        !           138: 
        !           139: /*
        !           140:  * Mount a remote root fs via. nfs. This depends on the info in the
        !           141:  * nfs_diskless structure that has been filled in properly by some primary
        !           142:  * bootstrap.
        !           143:  * It goes something like this:
        !           144:  * - do enough of "ifconfig" by calling ifioctl() so that the system
        !           145:  *   can talk to the server
        !           146:  * - If nfs_diskless.mygateway is filled in, use that address as
        !           147:  *   a default gateway.
        !           148:  *   (This is done the 4.3 way with rtioctl() and should be changed)
        !           149:  * - hand craft the swap nfs vnode hanging off a fake mount point
        !           150:  * - build the rootfs mount point and call mountnfs() to do the rest.
        !           151:  */
        !           152: nfs_mountroot()
        !           153: {
        !           154:        register struct mount *mp;
        !           155:        register struct mbuf *m;
        !           156:        struct socket *so;
        !           157:        struct vnode *vp;
        !           158:        int error;
        !           159: 
        !           160:        /*
        !           161:         * Do enough of ifconfig(8) so that critical net interface can
        !           162:         * talk to the server.
        !           163:         */
        !           164:        if (socreate(nfs_diskless.myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0))
        !           165:                panic("nfs ifconf");
        !           166:        if (ifioctl(so, SIOCAIFADDR, &nfs_diskless.myif))
        !           167:                panic("nfs ifconf2");
        !           168:        soclose(so);
        !           169: 
        !           170:        /*
        !           171:         * If the gateway field is filled in, set it as the default route.
        !           172:         */
        !           173: #ifdef COMPAT_43
        !           174:        if (nfs_diskless.mygateway.sa_family == AF_INET) {
        !           175:                struct ortentry rt;
        !           176:                struct sockaddr_in *sin;
        !           177: 
        !           178:                sin = (struct sockaddr_in *) &rt.rt_dst;
        !           179:                sin->sin_len = sizeof (struct sockaddr_in);
        !           180:                sin->sin_family = AF_INET;
        !           181:                sin->sin_addr.s_addr = 0;       /* default */
        !           182:                bcopy((caddr_t)&nfs_diskless.mygateway, (caddr_t)&rt.rt_gateway,
        !           183:                        sizeof (struct sockaddr_in));
        !           184:                rt.rt_flags = (RTF_UP | RTF_GATEWAY);
        !           185:                if (rtioctl(SIOCADDRT, (caddr_t)&rt))
        !           186:                        panic("nfs root route");
        !           187:        }
        !           188: #endif /* COMPAT_43 */
        !           189: 
        !           190:        /*
        !           191:         * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV):
        !           192:         * Create a fake mount point just for the swap vnode so that the
        !           193:         * swap file can be on a different server from the rootfs.
        !           194:         */
        !           195:        if (swdevt[0].sw_dev == NODEV) {
        !           196:                mp = (struct mount *)malloc((u_long)sizeof(struct mount),
        !           197:                        M_MOUNT, M_NOWAIT);
        !           198:                if (mp == NULL)
        !           199:                        panic("nfs root mount");
        !           200:                mp->mnt_op = &nfs_vfsops;
        !           201:                mp->mnt_flag = 0;
        !           202:                mp->mnt_exroot = 0;
        !           203:                mp->mnt_mounth = NULLVP;
        !           204:        
        !           205:                /*
        !           206:                 * Set up the diskless nfs_args for the swap mount point
        !           207:                 * and then call mountnfs() to mount it.
        !           208:                 * Since the swap file is not the root dir of a file system,
        !           209:                 * hack it to a regular file.
        !           210:                 */
        !           211:                nfs_diskless.swap_args.fh = (nfsv2fh_t *)nfs_diskless.swap_fh;
        !           212:                MGET(m, MT_SONAME, M_DONTWAIT);
        !           213:                if (m == NULL)
        !           214:                        panic("nfs root mbuf");
        !           215:                bcopy((caddr_t)&nfs_diskless.swap_saddr, mtod(m, caddr_t),
        !           216:                        nfs_diskless.swap_saddr.sa_len);
        !           217:                m->m_len = nfs_diskless.swap_saddr.sa_len;
        !           218:                if (mountnfs(&nfs_diskless.swap_args, mp, m, "/swap",
        !           219:                        nfs_diskless.swap_hostnam, &vp))
        !           220:                        panic("nfs swap");
        !           221:                vp->v_type = VREG;
        !           222:                vp->v_flag = 0;
        !           223:                swapdev_vp = vp;
        !           224:                VREF(vp);
        !           225:                swdevt[0].sw_vp = vp;
        !           226:        }
        !           227: 
        !           228:        /*
        !           229:         * Create the rootfs mount point.
        !           230:         */
        !           231:        mp = (struct mount *)malloc((u_long)sizeof(struct mount),
        !           232:                M_MOUNT, M_NOWAIT);
        !           233:        if (mp == NULL)
        !           234:                panic("nfs root mount2");
        !           235:        mp->mnt_op = &nfs_vfsops;
        !           236:        mp->mnt_flag = MNT_RDONLY;
        !           237:        mp->mnt_exroot = 0;
        !           238:        mp->mnt_mounth = NULLVP;
        !           239: 
        !           240:        /*
        !           241:         * Set up the root fs args and call mountnfs() to do the rest.
        !           242:         */
        !           243:        nfs_diskless.root_args.fh = (nfsv2fh_t *)nfs_diskless.root_fh;
        !           244:        MGET(m, MT_SONAME, M_DONTWAIT);
        !           245:        if (m == NULL)
        !           246:                panic("nfs root mbuf2");
        !           247:        bcopy((caddr_t)&nfs_diskless.root_saddr, mtod(m, caddr_t),
        !           248:                nfs_diskless.root_saddr.sa_len);
        !           249:        m->m_len = nfs_diskless.root_saddr.sa_len;
        !           250:        if (mountnfs(&nfs_diskless.root_args, mp, m, "/",
        !           251:                nfs_diskless.root_hostnam, &vp))
        !           252:                panic("nfs root");
        !           253:        if (vfs_lock(mp))
        !           254:                panic("nfs root2");
        !           255:        rootfs = mp;
        !           256:        mp->mnt_next = mp;
        !           257:        mp->mnt_prev = mp;
        !           258:        mp->mnt_vnodecovered = NULLVP;
        !           259:        vfs_unlock(mp);
        !           260:        rootvp = vp;
        !           261:        inittodr((time_t)0);    /* There is no time in the nfs fsstat so ?? */
        !           262:        return (0);
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * VFS Operations.
        !           267:  *
        !           268:  * mount system call
        !           269:  * It seems a bit dumb to copyinstr() the host and path here and then
        !           270:  * bcopy() them in mountnfs(), but I wanted to detect errors before
        !           271:  * doing the sockargs() call because sockargs() allocates an mbuf and
        !           272:  * an error after that means that I have to release the mbuf.
        !           273:  */
        !           274: /* ARGSUSED */
        !           275: nfs_mount(mp, path, data, ndp, p)
        !           276:        struct mount *mp;
        !           277:        char *path;
        !           278:        caddr_t data;
        !           279:        struct nameidata *ndp;
        !           280:        struct proc *p;
        !           281: {
        !           282:        int error;
        !           283:        struct nfs_args args;
        !           284:        struct mbuf *nam;
        !           285:        struct vnode *vp;
        !           286:        char pth[MNAMELEN], hst[MNAMELEN];
        !           287:        u_int len;
        !           288:        nfsv2fh_t nfh;
        !           289: 
        !           290:        if (mp->mnt_flag & MNT_UPDATE)
        !           291:                return (0);
        !           292:        if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
        !           293:                return (error);
        !           294:        if (error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
        !           295:                return (error);
        !           296:        if (error = copyinstr(path, pth, MNAMELEN-1, &len))
        !           297:                return (error);
        !           298:        bzero(&pth[len], MNAMELEN - len);
        !           299:        if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
        !           300:                return (error);
        !           301:        bzero(&hst[len], MNAMELEN - len);
        !           302:        /* sockargs() call must be after above copyin() calls */
        !           303:        if (error = sockargs(&nam, (caddr_t)args.addr,
        !           304:                sizeof (struct sockaddr), MT_SONAME))
        !           305:                return (error);
        !           306:        args.fh = &nfh;
        !           307:        error = mountnfs(&args, mp, nam, pth, hst, &vp);
        !           308:        return (error);
        !           309: }
        !           310: 
        !           311: /*
        !           312:  * Common code for mount and mountroot
        !           313:  */
        !           314: mountnfs(argp, mp, nam, pth, hst, vpp)
        !           315:        register struct nfs_args *argp;
        !           316:        register struct mount *mp;
        !           317:        struct mbuf *nam;
        !           318:        char *pth, *hst;
        !           319:        struct vnode **vpp;
        !           320: {
        !           321:        register struct nfsmount *nmp;
        !           322:        struct proc *p = curproc;               /* XXX */
        !           323:        struct nfsnode *np;
        !           324:        int error;
        !           325:        fsid_t tfsid;
        !           326: 
        !           327:        MALLOC(nmp, struct nfsmount *, sizeof *nmp, M_NFSMNT, M_WAITOK);
        !           328:        bzero((caddr_t)nmp, sizeof *nmp);
        !           329:        mp->mnt_data = (qaddr_t)nmp;
        !           330:        /*
        !           331:         * Generate a unique nfs mount id. The problem is that a dev number
        !           332:         * is not unique across multiple systems. The techique is as follows:
        !           333:         * 1) Set to nblkdev,0 which will never be used otherwise
        !           334:         * 2) Generate a first guess as nblkdev,nfs_mntid where nfs_mntid is
        !           335:         *      NOT 0
        !           336:         * 3) Loop searching the mount list for another one with same id
        !           337:         *      If a match, increment val[0] and try again
        !           338:         * NB: I increment val[0] { a long } instead of nfs_mntid { a u_char }
        !           339:         *      so that nfs is not limited to 255 mount points
        !           340:         *     Incrementing the high order bits does no real harm, since it
        !           341:         *     simply makes the major dev number tick up. The upper bound is
        !           342:         *     set to major dev 127 to avoid any sign extention problems
        !           343:         */
        !           344:        mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev, 0);
        !           345:        mp->mnt_stat.f_fsid.val[1] = MOUNT_NFS;
        !           346:        if (++nfs_mntid == 0)
        !           347:                ++nfs_mntid;
        !           348:        tfsid.val[0] = makedev(nblkdev, nfs_mntid);
        !           349:        tfsid.val[1] = MOUNT_NFS;
        !           350:        while (rootfs && getvfs(&tfsid)) {
        !           351:                tfsid.val[0]++;
        !           352:                nfs_mntid++;
        !           353:        }
        !           354:        if (major(tfsid.val[0]) > 127) {
        !           355:                error = ENOENT;
        !           356:                goto bad;
        !           357:        }
        !           358:        mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
        !           359:        nmp->nm_mountp = mp;
        !           360:        nmp->nm_flag = argp->flags;
        !           361:        nmp->nm_rto = NFS_TIMEO;
        !           362:        nmp->nm_rtt = -1;
        !           363:        nmp->nm_rttvar = nmp->nm_rto << 1;
        !           364:        nmp->nm_retry = NFS_RETRANS;
        !           365:        nmp->nm_wsize = NFS_WSIZE;
        !           366:        nmp->nm_rsize = NFS_RSIZE;
        !           367:        bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
        !           368:        bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
        !           369:        bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
        !           370:        nmp->nm_nam = nam;
        !           371: 
        !           372:        if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
        !           373:                nmp->nm_rto = argp->timeo;
        !           374:                /* NFS timeouts are specified in 1/10 sec. */
        !           375:                nmp->nm_rto = (nmp->nm_rto * 10) / NFS_HZ;
        !           376:                if (nmp->nm_rto < NFS_MINTIMEO)
        !           377:                        nmp->nm_rto = NFS_MINTIMEO;
        !           378:                else if (nmp->nm_rto > NFS_MAXTIMEO)
        !           379:                        nmp->nm_rto = NFS_MAXTIMEO;
        !           380:                nmp->nm_rttvar = nmp->nm_rto << 1;
        !           381:        }
        !           382: 
        !           383:        if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
        !           384:                nmp->nm_retry = argp->retrans;
        !           385:                if (nmp->nm_retry > NFS_MAXREXMIT)
        !           386:                        nmp->nm_retry = NFS_MAXREXMIT;
        !           387:        }
        !           388: 
        !           389:        if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
        !           390:                nmp->nm_wsize = argp->wsize;
        !           391:                /* Round down to multiple of blocksize */
        !           392:                nmp->nm_wsize &= ~0x1ff;
        !           393:                if (nmp->nm_wsize <= 0)
        !           394:                        nmp->nm_wsize = 512;
        !           395:                else if (nmp->nm_wsize > NFS_MAXDATA)
        !           396:                        nmp->nm_wsize = NFS_MAXDATA;
        !           397:        }
        !           398:        if (nmp->nm_wsize > MAXBSIZE)
        !           399:                nmp->nm_wsize = MAXBSIZE;
        !           400: 
        !           401:        if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
        !           402:                nmp->nm_rsize = argp->rsize;
        !           403:                /* Round down to multiple of blocksize */
        !           404:                nmp->nm_rsize &= ~0x1ff;
        !           405:                if (nmp->nm_rsize <= 0)
        !           406:                        nmp->nm_rsize = 512;
        !           407:                else if (nmp->nm_rsize > NFS_MAXDATA)
        !           408:                        nmp->nm_rsize = NFS_MAXDATA;
        !           409:        }
        !           410:        if (nmp->nm_rsize > MAXBSIZE)
        !           411:                nmp->nm_rsize = MAXBSIZE;
        !           412:        /* Set up the sockets and per-host congestion */
        !           413:        nmp->nm_sotype = argp->sotype;
        !           414:        nmp->nm_soproto = argp->proto;
        !           415:        if (error = nfs_connect(nmp))
        !           416:                goto bad;
        !           417: 
        !           418:        if (error = nfs_statfs(mp, &mp->mnt_stat, p))
        !           419:                goto bad;
        !           420:        /*
        !           421:         * A reference count is needed on the nfsnode representing the
        !           422:         * remote root.  If this object is not persistent, then backward
        !           423:         * traversals of the mount point (i.e. "..") will not work if
        !           424:         * the nfsnode gets flushed out of the cache. Ufs does not have
        !           425:         * this problem, because one can identify root inodes by their
        !           426:         * number == ROOTINO (2).
        !           427:         */
        !           428:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           429:                goto bad;
        !           430:        /*
        !           431:         * Unlock it, but keep the reference count.
        !           432:         */
        !           433:        nfs_unlock(NFSTOV(np));
        !           434:        *vpp = NFSTOV(np);
        !           435: 
        !           436:        return (0);
        !           437: bad:
        !           438:        nfs_disconnect(nmp);
        !           439:        FREE(nmp, M_NFSMNT);
        !           440:        m_freem(nam);
        !           441:        return (error);
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * unmount system call
        !           446:  */
        !           447: nfs_unmount(mp, mntflags, p)
        !           448:        struct mount *mp;
        !           449:        int mntflags;
        !           450:        struct proc *p;
        !           451: {
        !           452:        register struct nfsmount *nmp;
        !           453:        struct nfsnode *np;
        !           454:        struct vnode *vp;
        !           455:        int error, flags = 0;
        !           456:        extern int doforce;
        !           457: 
        !           458:        if (mntflags & MNT_FORCE) {
        !           459:                if (!doforce || mp == rootfs)
        !           460:                        return (EINVAL);
        !           461:                flags |= FORCECLOSE;
        !           462:        }
        !           463:        nmp = VFSTONFS(mp);
        !           464:        /*
        !           465:         * Clear out the buffer cache
        !           466:         */
        !           467:        mntflushbuf(mp, 0);
        !           468:        if (mntinvalbuf(mp))
        !           469:                return (EBUSY);
        !           470:        /*
        !           471:         * Goes something like this..
        !           472:         * - Check for activity on the root vnode (other than ourselves).
        !           473:         * - Call vflush() to clear out vnodes for this file system,
        !           474:         *   except for the root vnode.
        !           475:         * - Decrement reference on the vnode representing remote root.
        !           476:         * - Close the socket
        !           477:         * - Free up the data structures
        !           478:         */
        !           479:        /*
        !           480:         * We need to decrement the ref. count on the nfsnode representing
        !           481:         * the remote root.  See comment in mountnfs().  The VFS unmount()
        !           482:         * has done vput on this vnode, otherwise we would get deadlock!
        !           483:         */
        !           484:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           485:                return(error);
        !           486:        vp = NFSTOV(np);
        !           487:        if (vp->v_usecount > 2) {
        !           488:                vput(vp);
        !           489:                return (EBUSY);
        !           490:        }
        !           491:        if (error = vflush(mp, vp, flags)) {
        !           492:                vput(vp);
        !           493:                return (error);
        !           494:        }
        !           495:        /*
        !           496:         * Get rid of two reference counts, and unlock it on the second.
        !           497:         */
        !           498:        vrele(vp);
        !           499:        vput(vp);
        !           500:        nfs_disconnect(nmp);
        !           501:        m_freem(nmp->nm_nam);
        !           502:        free((caddr_t)nmp, M_NFSMNT);
        !           503:        return (0);
        !           504: }
        !           505: 
        !           506: /*
        !           507:  * Return root of a filesystem
        !           508:  */
        !           509: nfs_root(mp, vpp)
        !           510:        struct mount *mp;
        !           511:        struct vnode **vpp;
        !           512: {
        !           513:        register struct vnode *vp;
        !           514:        struct nfsmount *nmp;
        !           515:        struct nfsnode *np;
        !           516:        int error;
        !           517: 
        !           518:        nmp = VFSTONFS(mp);
        !           519:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           520:                return (error);
        !           521:        vp = NFSTOV(np);
        !           522:        vp->v_type = VDIR;
        !           523:        vp->v_flag = VROOT;
        !           524:        *vpp = vp;
        !           525:        return (0);
        !           526: }
        !           527: 
        !           528: extern int syncprt;
        !           529: 
        !           530: /*
        !           531:  * Flush out the buffer cache
        !           532:  */
        !           533: /* ARGSUSED */
        !           534: nfs_sync(mp, waitfor)
        !           535:        struct mount *mp;
        !           536:        int waitfor;
        !           537: {
        !           538:        if (syncprt)
        !           539:                bufstats();
        !           540:        /*
        !           541:         * Force stale buffer cache information to be flushed.
        !           542:         */
        !           543:        mntflushbuf(mp, waitfor == MNT_WAIT ? B_SYNC : 0);
        !           544:        return (0);
        !           545: }
        !           546: 
        !           547: /*
        !           548:  * At this point, this should never happen
        !           549:  */
        !           550: /* ARGSUSED */
        !           551: nfs_fhtovp(mp, fhp, vpp)
        !           552:        struct mount *mp;
        !           553:        struct fid *fhp;
        !           554:        struct vnode **vpp;
        !           555: {
        !           556: 
        !           557:        return (EINVAL);
        !           558: }
        !           559: 
        !           560: /*
        !           561:  * Vnode pointer to File handle, should never happen either
        !           562:  */
        !           563: /* ARGSUSED */
        !           564: nfs_vptofh(vp, fhp)
        !           565:        struct vnode *vp;
        !           566:        struct fid *fhp;
        !           567: {
        !           568: 
        !           569:        return (EINVAL);
        !           570: }
        !           571: 
        !           572: /*
        !           573:  * Vfs start routine, a no-op.
        !           574:  */
        !           575: /* ARGSUSED */
        !           576: nfs_start(mp, flags, p)
        !           577:        struct mount *mp;
        !           578:        int flags;
        !           579:        struct proc *p;
        !           580: {
        !           581: 
        !           582:        return (0);
        !           583: }
        !           584: 
        !           585: /*
        !           586:  * Do operations associated with quotas, not supported
        !           587:  */
        !           588: nfs_quotactl(mp, cmd, uid, arg, p)
        !           589:        struct mount *mp;
        !           590:        int cmd;
        !           591:        uid_t uid;
        !           592:        caddr_t arg;
        !           593:        struct proc *p;
        !           594: {
        !           595: #ifdef lint
        !           596:        mp = mp; cmd = cmd; uid = uid; arg = arg;
        !           597: #endif /* lint */
        !           598:        return (EOPNOTSUPP);
        !           599: }

unix.superglobalmegacorp.com

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