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

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Rick Macklem at The University of Guelph.
                      7:  *
                      8:  * Redistribution is only permitted until one year after the first shipment
                      9:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                     10:  * binary forms are permitted provided that: (1) source distributions retain
                     11:  * this entire copyright notice and comment, and (2) distributions including
                     12:  * binaries display the following acknowledgement:  This product includes
                     13:  * software developed by the University of California, Berkeley and its
                     14:  * contributors'' in the documentation or other materials provided with the
                     15:  * distribution and in all advertising materials mentioning features or use
                     16:  * of this software.  Neither the name of the University nor the names of
                     17:  * its contributors may be used to endorse or promote products derived from
                     18:  * this software without specific prior written permission.
                     19:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     20:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     22:  *
                     23:  *     @(#)nfs_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.