Annotation of 43BSDReno/sys/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 is only permitted until one year after the first shipment
        !             9:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            10:  * binary forms are permitted provided that: (1) source distributions retain
        !            11:  * this entire copyright notice and comment, and (2) distributions including
        !            12:  * binaries display the following acknowledgement:  This product includes
        !            13:  * software developed by the University of California, Berkeley and its
        !            14:  * contributors'' in the documentation or other materials provided with the
        !            15:  * distribution and in all advertising materials mentioning features or use
        !            16:  * of this software.  Neither the name of the University nor the names of
        !            17:  * its contributors may be used to endorse or promote products derived from
        !            18:  * this software without specific prior written permission.
        !            19:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            20:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            22:  *
        !            23:  *     @(#)nfs_vfsops.c        7.24 (Berkeley) 6/28/90
        !            24:  */
        !            25: 
        !            26: #include "param.h"
        !            27: #include "signal.h"
        !            28: #include "user.h"
        !            29: #include "proc.h"
        !            30: #include "vnode.h"
        !            31: #include "mount.h"
        !            32: #include "errno.h"
        !            33: #include "buf.h"
        !            34: #include "mbuf.h"
        !            35: #include "socket.h"
        !            36: #include "systm.h"
        !            37: #include "nfsv2.h"
        !            38: #include "nfsnode.h"
        !            39: #include "nfsmount.h"
        !            40: #include "nfs.h"
        !            41: #include "xdr_subs.h"
        !            42: #include "nfsm_subs.h"
        !            43: 
        !            44: /*
        !            45:  * nfs vfs operations.
        !            46:  */
        !            47: int nfs_mount();
        !            48: int nfs_start();
        !            49: int nfs_unmount();
        !            50: int nfs_root();
        !            51: int nfs_quotactl();
        !            52: int nfs_statfs();
        !            53: int nfs_sync();
        !            54: int nfs_fhtovp();
        !            55: int nfs_vptofh();
        !            56: int nfs_init();
        !            57: 
        !            58: struct vfsops nfs_vfsops = {
        !            59:        nfs_mount,
        !            60:        nfs_start,
        !            61:        nfs_unmount,
        !            62:        nfs_root,
        !            63:        nfs_quotactl,
        !            64:        nfs_statfs,
        !            65:        nfs_sync,
        !            66:        nfs_fhtovp,
        !            67:        nfs_vptofh,
        !            68:        nfs_init,
        !            69: };
        !            70: 
        !            71: static u_char nfs_mntid;
        !            72: extern u_long nfs_procids[NFS_NPROCS];
        !            73: extern u_long nfs_prog, nfs_vers;
        !            74: void nfs_disconnect();
        !            75: 
        !            76: #define TRUE   1
        !            77: #define        FALSE   0
        !            78: 
        !            79: /*
        !            80:  * nfs statfs call
        !            81:  */
        !            82: nfs_statfs(mp, sbp)
        !            83:        struct mount *mp;
        !            84:        register struct statfs *sbp;
        !            85: {
        !            86:        register struct vnode *vp;
        !            87:        register struct nfsv2_statfs *sfp;
        !            88:        register caddr_t cp;
        !            89:        register long t1;
        !            90:        caddr_t bpos, dpos, cp2;
        !            91:        u_long xid;
        !            92:        int error = 0;
        !            93:        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        !            94:        struct nfsmount *nmp;
        !            95:        struct ucred *cred;
        !            96:        struct nfsnode *np;
        !            97: 
        !            98:        nmp = VFSTONFS(mp);
        !            99:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           100:                return (error);
        !           101:        vp = NFSTOV(np);
        !           102:        nfsstats.rpccnt[NFSPROC_STATFS]++;
        !           103:        cred = crget();
        !           104:        cred->cr_ngroups = 1;
        !           105:        nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
        !           106:        nfsm_fhtom(vp);
        !           107:        nfsm_request(vp, NFSPROC_STATFS, u.u_procp, 0);
        !           108:        nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
        !           109:        sbp->f_type = MOUNT_NFS;
        !           110:        sbp->f_flags = nmp->nm_flag;
        !           111:        sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize);
        !           112:        sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize);
        !           113:        sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
        !           114:        sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
        !           115:        sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
        !           116:        sbp->f_files = 0;
        !           117:        sbp->f_ffree = 0;
        !           118:        if (sbp != &mp->mnt_stat) {
        !           119:                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
        !           120:                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
        !           121:        }
        !           122:        nfsm_reqdone;
        !           123:        nfs_nput(vp);
        !           124:        crfree(cred);
        !           125:        return (error);
        !           126: }
        !           127: 
        !           128: /*
        !           129:  * Called by vfs_mountroot when nfs is going to be mounted as root
        !           130:  * Not Yet (By a LONG shot)
        !           131:  */
        !           132: nfs_mountroot()
        !           133: {
        !           134:        return (ENODEV);
        !           135: }
        !           136: 
        !           137: /*
        !           138:  * VFS Operations.
        !           139:  *
        !           140:  * mount system call
        !           141:  * It seems a bit dumb to copyinstr() the host and path here and then
        !           142:  * bcopy() them in mountnfs(), but I wanted to detect errors before
        !           143:  * doing the sockargs() call because sockargs() allocates an mbuf and
        !           144:  * an error after that means that I have to release the mbuf.
        !           145:  */
        !           146: /* ARGSUSED */
        !           147: nfs_mount(mp, path, data, ndp)
        !           148:        struct mount *mp;
        !           149:        char *path;
        !           150:        caddr_t data;
        !           151:        struct nameidata *ndp;
        !           152: {
        !           153:        int error;
        !           154:        struct nfs_args args;
        !           155:        struct mbuf *nam;
        !           156:        char pth[MNAMELEN], hst[MNAMELEN];
        !           157:        int len;
        !           158:        nfsv2fh_t nfh;
        !           159: 
        !           160:        if (mp->mnt_flag & MNT_UPDATE)
        !           161:                return (0);
        !           162:        if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
        !           163:                return (error);
        !           164:        if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
        !           165:                return (error);
        !           166:        if (error = copyinstr(path, pth, MNAMELEN-1, &len))
        !           167:                return (error);
        !           168:        bzero(&pth[len], MNAMELEN-len);
        !           169:        if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
        !           170:                return (error);
        !           171:        bzero(&hst[len], MNAMELEN-len);
        !           172:        /* sockargs() call must be after above copyin() calls */
        !           173:        if (error = sockargs(&nam, (caddr_t)args.addr,
        !           174:                sizeof (struct sockaddr), MT_SONAME))
        !           175:                return (error);
        !           176:        args.fh = &nfh;
        !           177:        error = mountnfs(&args, mp, nam, pth, hst);
        !           178:        return (error);
        !           179: }
        !           180: 
        !           181: /*
        !           182:  * Common code for mount and mountroot
        !           183:  */
        !           184: mountnfs(argp, mp, nam, pth, hst)
        !           185:        register struct nfs_args *argp;
        !           186:        register struct mount *mp;
        !           187:        struct mbuf *nam;
        !           188:        char *pth, *hst;
        !           189: {
        !           190:        register struct nfsmount *nmp;
        !           191:        struct nfsnode *np;
        !           192:        int error;
        !           193:        fsid_t tfsid;
        !           194: 
        !           195:        MALLOC(nmp, struct nfsmount *, sizeof *nmp, M_NFSMNT, M_WAITOK);
        !           196:        bzero((caddr_t)nmp, sizeof *nmp);
        !           197:        mp->mnt_data = (qaddr_t)nmp;
        !           198:        /*
        !           199:         * Generate a unique nfs mount id. The problem is that a dev number
        !           200:         * is not unique across multiple systems. The techique is as follows:
        !           201:         * 1) Set to nblkdev,0 which will never be used otherwise
        !           202:         * 2) Generate a first guess as nblkdev,nfs_mntid where nfs_mntid is
        !           203:         *      NOT 0
        !           204:         * 3) Loop searching the mount list for another one with same id
        !           205:         *      If a match, increment val[0] and try again
        !           206:         * NB: I increment val[0] { a long } instead of nfs_mntid { a u_char }
        !           207:         *      so that nfs is not limited to 255 mount points
        !           208:         *     Incrementing the high order bits does no real harm, since it
        !           209:         *     simply makes the major dev number tick up. The upper bound is
        !           210:         *     set to major dev 127 to avoid any sign extention problems
        !           211:         */
        !           212:        mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev, 0);
        !           213:        mp->mnt_stat.f_fsid.val[1] = MOUNT_NFS;
        !           214:        if (++nfs_mntid == 0)
        !           215:                ++nfs_mntid;
        !           216:        tfsid.val[0] = makedev(nblkdev, nfs_mntid);
        !           217:        tfsid.val[1] = MOUNT_NFS;
        !           218:        while (getvfs(&tfsid)) {
        !           219:                tfsid.val[0]++;
        !           220:                nfs_mntid++;
        !           221:        }
        !           222:        if (major(tfsid.val[0]) > 127) {
        !           223:                error = ENOENT;
        !           224:                goto bad;
        !           225:        }
        !           226:        mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
        !           227:        nmp->nm_mountp = mp;
        !           228:        nmp->nm_flag = argp->flags;
        !           229:        nmp->nm_rto = NFS_TIMEO;
        !           230:        nmp->nm_rtt = -1;
        !           231:        nmp->nm_rttvar = nmp->nm_rto << 1;
        !           232:        nmp->nm_retry = NFS_RETRANS;
        !           233:        nmp->nm_wsize = NFS_WSIZE;
        !           234:        nmp->nm_rsize = NFS_RSIZE;
        !           235:        bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
        !           236:        bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
        !           237:        bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
        !           238:        nmp->nm_nam = nam;
        !           239: 
        !           240:        if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
        !           241:                nmp->nm_rto = argp->timeo;
        !           242:                /* NFS timeouts are specified in 1/10 sec. */
        !           243:                nmp->nm_rto = (nmp->nm_rto * 10) / NFS_HZ;
        !           244:                if (nmp->nm_rto < NFS_MINTIMEO)
        !           245:                        nmp->nm_rto = NFS_MINTIMEO;
        !           246:                else if (nmp->nm_rto > NFS_MAXTIMEO)
        !           247:                        nmp->nm_rto = NFS_MAXTIMEO;
        !           248:                nmp->nm_rttvar = nmp->nm_rto << 1;
        !           249:        }
        !           250: 
        !           251:        if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
        !           252:                nmp->nm_retry = argp->retrans;
        !           253:                if (nmp->nm_retry > NFS_MAXREXMIT)
        !           254:                        nmp->nm_retry = NFS_MAXREXMIT;
        !           255:        }
        !           256: 
        !           257:        if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
        !           258:                nmp->nm_wsize = argp->wsize;
        !           259:                /* Round down to multiple of blocksize */
        !           260:                nmp->nm_wsize &= ~0x1ff;
        !           261:                if (nmp->nm_wsize <= 0)
        !           262:                        nmp->nm_wsize = 512;
        !           263:                else if (nmp->nm_wsize > NFS_MAXDATA)
        !           264:                        nmp->nm_wsize = NFS_MAXDATA;
        !           265:        }
        !           266:        if (nmp->nm_wsize > MAXBSIZE)
        !           267:                nmp->nm_wsize = MAXBSIZE;
        !           268: 
        !           269:        if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
        !           270:                nmp->nm_rsize = argp->rsize;
        !           271:                /* Round down to multiple of blocksize */
        !           272:                nmp->nm_rsize &= ~0x1ff;
        !           273:                if (nmp->nm_rsize <= 0)
        !           274:                        nmp->nm_rsize = 512;
        !           275:                else if (nmp->nm_rsize > NFS_MAXDATA)
        !           276:                        nmp->nm_rsize = NFS_MAXDATA;
        !           277:        }
        !           278:        if (nmp->nm_rsize > MAXBSIZE)
        !           279:                nmp->nm_rsize = MAXBSIZE;
        !           280:        /* Set up the sockets and per-host congestion */
        !           281:        nmp->nm_sotype = argp->sotype;
        !           282:        nmp->nm_soproto = argp->proto;
        !           283:        if (error = nfs_connect(nmp))
        !           284:                goto bad;
        !           285: 
        !           286:        if (error = nfs_statfs(mp, &mp->mnt_stat))
        !           287:                goto bad;
        !           288:        /*
        !           289:         * A reference count is needed on the nfsnode representing the
        !           290:         * remote root.  If this object is not persistent, then backward
        !           291:         * traversals of the mount point (i.e. "..") will not work if
        !           292:         * the nfsnode gets flushed out of the cache. Ufs does not have
        !           293:         * this problem, because one can identify root inodes by their
        !           294:         * number == ROOTINO (2).
        !           295:         */
        !           296:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           297:                goto bad;
        !           298:        /*
        !           299:         * Unlock it, but keep the reference count.
        !           300:         */
        !           301:        nfs_unlock(NFSTOV(np));
        !           302: 
        !           303:        return (0);
        !           304: bad:
        !           305:        nfs_disconnect(nmp);
        !           306:        FREE(nmp, M_NFSMNT);
        !           307:        m_freem(nam);
        !           308:        return (error);
        !           309: }
        !           310: 
        !           311: /*
        !           312:  * unmount system call
        !           313:  */
        !           314: nfs_unmount(mp, mntflags)
        !           315:        struct mount *mp;
        !           316:        int mntflags;
        !           317: {
        !           318:        register struct nfsmount *nmp;
        !           319:        struct nfsnode *np;
        !           320:        struct vnode *vp;
        !           321:        int flags = 0;
        !           322:        int error;
        !           323: 
        !           324:        if (mntflags & MNT_FORCE)
        !           325:                return (EINVAL);
        !           326:        if (mntflags & MNT_FORCE)
        !           327:                flags |= FORCECLOSE;
        !           328:        nmp = VFSTONFS(mp);
        !           329:        /*
        !           330:         * Clear out the buffer cache
        !           331:         */
        !           332:        mntflushbuf(mp, 0);
        !           333:        if (mntinvalbuf(mp))
        !           334:                return (EBUSY);
        !           335:        /*
        !           336:         * Goes something like this..
        !           337:         * - Check for activity on the root vnode (other than ourselves).
        !           338:         * - Call vflush() to clear out vnodes for this file system,
        !           339:         *   except for the root vnode.
        !           340:         * - Decrement reference on the vnode representing remote root.
        !           341:         * - Close the socket
        !           342:         * - Free up the data structures
        !           343:         */
        !           344:        /*
        !           345:         * We need to decrement the ref. count on the nfsnode representing
        !           346:         * the remote root.  See comment in mountnfs().  The VFS unmount()
        !           347:         * has done vput on this vnode, otherwise we would get deadlock!
        !           348:         */
        !           349:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           350:                return(error);
        !           351:        vp = NFSTOV(np);
        !           352:        if (vp->v_usecount > 2) {
        !           353:                vput(vp);
        !           354:                return (EBUSY);
        !           355:        }
        !           356:        if (error = vflush(mp, vp, flags)) {
        !           357:                vput(vp);
        !           358:                return (error);
        !           359:        }
        !           360:        /*
        !           361:         * Get rid of two reference counts, and unlock it on the second.
        !           362:         */
        !           363:        vrele(vp);
        !           364:        vput(vp);
        !           365:        nfs_disconnect(nmp);
        !           366:        m_freem(nmp->nm_nam);
        !           367:        free((caddr_t)nmp, M_NFSMNT);
        !           368:        return (0);
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Return root of a filesystem
        !           373:  */
        !           374: nfs_root(mp, vpp)
        !           375:        struct mount *mp;
        !           376:        struct vnode **vpp;
        !           377: {
        !           378:        register struct vnode *vp;
        !           379:        struct nfsmount *nmp;
        !           380:        struct nfsnode *np;
        !           381:        int error;
        !           382: 
        !           383:        nmp = VFSTONFS(mp);
        !           384:        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
        !           385:                return (error);
        !           386:        vp = NFSTOV(np);
        !           387:        vp->v_type = VDIR;
        !           388:        vp->v_flag = VROOT;
        !           389:        *vpp = vp;
        !           390:        return (0);
        !           391: }
        !           392: 
        !           393: extern int syncprt;
        !           394: 
        !           395: /*
        !           396:  * Flush out the buffer cache
        !           397:  */
        !           398: /* ARGSUSED */
        !           399: nfs_sync(mp, waitfor)
        !           400:        struct mount *mp;
        !           401:        int waitfor;
        !           402: {
        !           403:        if (syncprt)
        !           404:                bufstats();
        !           405:        /*
        !           406:         * Force stale buffer cache information to be flushed.
        !           407:         */
        !           408:        mntflushbuf(mp, waitfor == MNT_WAIT ? B_SYNC : 0);
        !           409:        return (0);
        !           410: }
        !           411: 
        !           412: /*
        !           413:  * At this point, this should never happen
        !           414:  */
        !           415: /* ARGSUSED */
        !           416: nfs_fhtovp(mp, fhp, vpp)
        !           417:        struct mount *mp;
        !           418:        struct fid *fhp;
        !           419:        struct vnode **vpp;
        !           420: {
        !           421: 
        !           422:        return (EINVAL);
        !           423: }
        !           424: 
        !           425: /*
        !           426:  * Vnode pointer to File handle, should never happen either
        !           427:  */
        !           428: /* ARGSUSED */
        !           429: nfs_vptofh(mp, fhp, vpp)
        !           430:        struct mount *mp;
        !           431:        struct fid *fhp;
        !           432:        struct vnode **vpp;
        !           433: {
        !           434: 
        !           435:        return (EINVAL);
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * Vfs start routine, a no-op.
        !           440:  */
        !           441: /* ARGSUSED */
        !           442: nfs_start(mp, flags)
        !           443:        struct mount *mp;
        !           444:        int flags;
        !           445: {
        !           446: 
        !           447:        return (0);
        !           448: }
        !           449: 
        !           450: /*
        !           451:  * Do operations associated with quotas, not supported
        !           452:  */
        !           453: nfs_quotactl(mp, cmd, uid, arg)
        !           454:        struct mount *mp;
        !           455:        int cmd;
        !           456:        uid_t uid;
        !           457:        caddr_t arg;
        !           458: {
        !           459: #ifdef lint
        !           460:        mp = mp; cmd = cmd; uid = uid; arg = arg;
        !           461: #endif /* lint */
        !           462:        return (EOPNOTSUPP);
        !           463: }

unix.superglobalmegacorp.com

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