Annotation of Net2/arch/amiga/dev/vn.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             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.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  * from: Utah $Hdr: vn.c 1.1 91/04/30$
        !            39:  *
        !            40:  *     @(#)vn.c        7.6 (Berkeley) 6/21/91
        !            41:  */
        !            42: 
        !            43: /*
        !            44:  * Vnode disk driver.
        !            45:  *
        !            46:  * Block/character interface to a vnode.  Allows one to treat a file
        !            47:  * as a disk (e.g. build a filesystem in it, mount it, etc.).
        !            48:  *
        !            49:  * NOTE 1: This uses the VOP_BMAP/VOP_STRATEGY interface to the vnode
        !            50:  * instead of a simple VOP_RDWR.  We do this to avoid distorting the
        !            51:  * local buffer cache.
        !            52:  *
        !            53:  * NOTE 2: There is a security issue involved with this driver.
        !            54:  * Once mounted all access to the contents of the "mapped" file via
        !            55:  * the special file is controlled by the permissions on the special
        !            56:  * file, the protection of the mapped file is ignored (effectively,
        !            57:  * by using root credentials in all transactions).
        !            58:  */
        !            59: #include "vn.h"
        !            60: #if NVN > 0
        !            61: 
        !            62: #include "sys/param.h"
        !            63: #include "sys/systm.h"
        !            64: #include "sys/namei.h"
        !            65: #include "sys/proc.h"
        !            66: #include "sys/errno.h"
        !            67: #include "sys/dkstat.h"
        !            68: #include "sys/buf.h"
        !            69: #include "sys/malloc.h"
        !            70: #include "sys/ioctl.h"
        !            71: #include "sys/mount.h"
        !            72: #include "sys/vnode.h"
        !            73: #include "sys/specdev.h"
        !            74: #include "sys/file.h"
        !            75: #include "sys/uio.h"
        !            76: 
        !            77: #include "vnioctl.h"
        !            78: 
        !            79: #ifdef DEBUG
        !            80: int vndebug = 0x00;
        !            81: #define VDB_FOLLOW     0x01
        !            82: #define VDB_INIT       0x02
        !            83: #define VDB_IO         0x04
        !            84: #endif
        !            85: 
        !            86: struct buf vnbuf[NVN];
        !            87: struct buf vntab[NVN];
        !            88: 
        !            89: #define b_cylin        b_resid
        !            90: 
        !            91: #define        vnunit(x)       ((minor(x) >> 3) & 0x7) /* for consistency */
        !            92: 
        !            93: #define        getvnbuf()      \
        !            94:        ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
        !            95: #define putvnbuf(bp)   \
        !            96:        free((caddr_t)(bp), M_DEVBUF)
        !            97: 
        !            98: struct vn_softc {
        !            99:        int              sc_flags;      /* flags */
        !           100:        size_t           sc_size;       /* size of vn */
        !           101:        struct vnode    *sc_vp;         /* vnode */
        !           102:        struct ucred    *sc_cred;       /* credentials */
        !           103:        int              sc_maxactive;  /* max # of active requests */
        !           104: } vn_softc[NVN];
        !           105: 
        !           106: /* sc_flags */
        !           107: #define        VNF_ALIVE       0x01
        !           108: #define VNF_INITED     0x02
        !           109: 
        !           110: int
        !           111: vnopen(dev, flags, mode, p)
        !           112:        dev_t dev;
        !           113:        int flags, mode;
        !           114:        struct proc *p;
        !           115: {
        !           116:        int unit = vnunit(dev);
        !           117: 
        !           118: #ifdef DEBUG
        !           119:        if (vndebug & VDB_FOLLOW)
        !           120:                printf("vnopen(%x, %x, %x, %x)\n", dev, flags, mode, p);
        !           121: #endif
        !           122:        if (unit >= NVN)
        !           123:                return(ENXIO);
        !           124:        return(0);
        !           125: }
        !           126: 
        !           127: /*
        !           128:  * Break the request into bsize pieces and submit using VOP_BMAP/VOP_STRATEGY.
        !           129:  * Note that this driver can only be used for swapping over NFS on the hp
        !           130:  * since nfs_strategy on the vax cannot handle u-areas and page tables.
        !           131:  */
        !           132: vnstrategy(bp)
        !           133:        register struct buf *bp;
        !           134: {
        !           135:        int unit = vnunit(bp->b_dev);
        !           136:        register struct vn_softc *vn = &vn_softc[unit];
        !           137:        register struct buf *nbp;
        !           138:        register int bn, bsize, resid;
        !           139:        register caddr_t addr;
        !           140:        int sz, flags;
        !           141:        extern int vniodone();
        !           142: 
        !           143: #ifdef DEBUG
        !           144:        if (vndebug & VDB_FOLLOW)
        !           145:                printf("vnstrategy(%x): unit %d\n", bp, unit);
        !           146: #endif
        !           147:        if ((vn->sc_flags & VNF_INITED) == 0) {
        !           148:                bp->b_error = ENXIO;
        !           149:                bp->b_flags |= B_ERROR;
        !           150:                biodone(bp);
        !           151:                return;
        !           152:        }
        !           153:        bn = bp->b_blkno;
        !           154:        sz = howmany(bp->b_bcount, DEV_BSIZE);
        !           155:        bp->b_resid = bp->b_bcount;
        !           156:        if (bn < 0 || bn + sz > vn->sc_size) {
        !           157:                if (bn != vn->sc_size) {
        !           158:                        bp->b_error = EINVAL;
        !           159:                        bp->b_flags |= B_ERROR;
        !           160:                }
        !           161:                biodone(bp);
        !           162:                return;
        !           163:        }
        !           164:        bn = dbtob(bn);
        !           165:        bsize = vn->sc_vp->v_mount->mnt_stat.f_bsize;
        !           166:        addr = bp->b_un.b_addr;
        !           167:        flags = bp->b_flags | B_CALL;
        !           168:        for (resid = bp->b_resid; resid; resid -= sz) {
        !           169:                struct vnode *vp;
        !           170:                daddr_t nbn;
        !           171:                int off, s;
        !           172: 
        !           173:                nbp = getvnbuf();
        !           174:                off = bn % bsize;
        !           175:                sz = MIN(bsize - off, resid);
        !           176:                (void) VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn);
        !           177: #ifdef DEBUG
        !           178:                if (vndebug & VDB_IO)
        !           179:                        printf("vnstrategy: vp %x/%x bn %x/%x\n",
        !           180:                               vn->sc_vp, vp, bn, nbn);
        !           181: #endif
        !           182:                nbp->b_flags = flags;
        !           183:                nbp->b_bcount = sz;
        !           184:                nbp->b_bufsize = bp->b_bufsize;
        !           185:                nbp->b_error = 0;
        !           186:                if (vp->v_type == VBLK || vp->v_type == VCHR)
        !           187:                        nbp->b_dev = vp->v_rdev;
        !           188:                else
        !           189:                        nbp->b_dev = NODEV;
        !           190:                nbp->b_un.b_addr = addr;
        !           191:                nbp->b_blkno = nbn + btodb(off);
        !           192:                nbp->b_proc = bp->b_proc;
        !           193:                nbp->b_iodone = vniodone;
        !           194:                nbp->b_vp = vp;
        !           195:                nbp->b_pfcent = (int) bp;       /* XXX */
        !           196:                /*
        !           197:                 * Just sort by block number
        !           198:                 */
        !           199:                nbp->b_cylin = nbp->b_blkno;
        !           200:                s = splbio();
        !           201:                disksort(&vntab[unit], nbp);
        !           202:                if (vntab[unit].b_active < vn->sc_maxactive) {
        !           203:                        vntab[unit].b_active++;
        !           204:                        vnstart(unit);
        !           205:                }
        !           206:                splx(s);
        !           207:                bn += sz;
        !           208:                addr += sz;
        !           209:        }
        !           210: }
        !           211: 
        !           212: /*
        !           213:  * Feed requests sequentially.
        !           214:  * We do it this way to keep from flooding NFS servers if we are connected
        !           215:  * to an NFS file.  This places the burden on the client rather than the
        !           216:  * server.
        !           217:  */
        !           218: vnstart(unit)
        !           219: {
        !           220:        register struct vn_softc *vn = &vn_softc[unit];
        !           221:        register struct buf *bp;
        !           222: 
        !           223:        /*
        !           224:         * Dequeue now since lower level strategy routine might
        !           225:         * queue using same links
        !           226:         */
        !           227:        bp = vntab[unit].b_actf;
        !           228:        vntab[unit].b_actf = bp->b_actf;
        !           229: #ifdef DEBUG
        !           230:        if (vndebug & VDB_IO)
        !           231:                printf("vnstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
        !           232:                       unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr,
        !           233:                       bp->b_bcount);
        !           234: #endif
        !           235:        VOP_STRATEGY(bp);
        !           236: }
        !           237: 
        !           238: vniodone(bp)
        !           239:        register struct buf *bp;
        !           240: {
        !           241:        register struct buf *pbp = (struct buf *)bp->b_pfcent;  /* XXX */
        !           242:        register int unit = vnunit(pbp->b_dev);
        !           243:        int s;
        !           244: 
        !           245:        s = splbio();
        !           246: #ifdef DEBUG
        !           247:        if (vndebug & VDB_IO)
        !           248:                printf("vniodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
        !           249:                       unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr,
        !           250:                       bp->b_bcount);
        !           251: #endif
        !           252:        if (bp->b_error) {
        !           253: #ifdef DEBUG
        !           254:                if (vndebug & VDB_IO)
        !           255:                        printf("vniodone: bp %x error %d\n", bp, bp->b_error);
        !           256: #endif
        !           257:                pbp->b_flags |= B_ERROR;
        !           258:                pbp->b_error = biowait(bp);
        !           259:        }
        !           260:        pbp->b_resid -= bp->b_bcount;
        !           261:        putvnbuf(bp);
        !           262:        if (pbp->b_resid == 0) {
        !           263: #ifdef DEBUG
        !           264:                if (vndebug & VDB_IO)
        !           265:                        printf("vniodone: pbp %x iodone\n", pbp);
        !           266: #endif
        !           267:                biodone(pbp);
        !           268:        }
        !           269:        if (vntab[unit].b_actf)
        !           270:                vnstart(unit);
        !           271:        else
        !           272:                vntab[unit].b_active--;
        !           273:        splx(s);
        !           274: }
        !           275: 
        !           276: vnread(dev, uio, flags, p)
        !           277:        dev_t dev;
        !           278:        struct uio *uio;
        !           279:        int flags;
        !           280:        struct proc *p;
        !           281: {
        !           282:        register int unit = vnunit(dev);
        !           283: 
        !           284: #ifdef DEBUG
        !           285:        if (vndebug & VDB_FOLLOW)
        !           286:                printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p);
        !           287: #endif
        !           288: #if 0
        !           289:        return(physio(vnstrategy, &vnbuf[unit], dev, B_READ, minphys, uio));
        !           290: #else
        !           291:        return rawread (dev, uio);
        !           292: #endif
        !           293: }
        !           294: 
        !           295: vnwrite(dev, uio, flags, p)
        !           296:        dev_t dev;
        !           297:        struct uio *uio;
        !           298:        int flags;
        !           299:        struct proc *p;
        !           300: {
        !           301:        register int unit = vnunit(dev);
        !           302: 
        !           303: #ifdef DEBUG
        !           304:        if (vndebug & VDB_FOLLOW)
        !           305:                printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p);
        !           306: #endif
        !           307: #if 0
        !           308:        return(physio(vnstrategy, &vnbuf[unit], dev, B_WRITE, minphys, uio));
        !           309: #else
        !           310:        return rawwrite (dev, uio);
        !           311: #endif
        !           312: }
        !           313: 
        !           314: /* ARGSUSED */
        !           315: vnioctl(dev, cmd, data, flag, p)
        !           316:        dev_t dev;
        !           317:        u_long cmd;
        !           318:        caddr_t data;
        !           319:        int flag;
        !           320:        struct proc *p;
        !           321: {
        !           322:        int unit = vnunit(dev);
        !           323:        register struct vn_softc *vn;
        !           324:        struct vn_ioctl *vio;
        !           325:        struct vattr vattr;
        !           326:        struct nameidata nd;
        !           327:        int error;
        !           328: 
        !           329: #ifdef DEBUG
        !           330:        if (vndebug & VDB_FOLLOW)
        !           331:                printf("vnioctl(%x, %x, %x, %x, %x): unit %d\n",
        !           332:                       dev, cmd, data, flag, p, unit);
        !           333: #endif
        !           334:        error = suser(p->p_ucred, &p->p_acflag);
        !           335:        if (error)
        !           336:                return (error);
        !           337:        if (unit >= NVN)
        !           338:                return (ENXIO);
        !           339: 
        !           340:        vn = &vn_softc[unit];
        !           341:        vio = (struct vn_ioctl *)data;
        !           342:        switch (cmd) {
        !           343: 
        !           344:        case VNIOCSET:
        !           345:                if (vn->sc_flags & VNF_INITED)
        !           346:                        return(EBUSY);
        !           347:                /*
        !           348:                 * Always open for read and write.
        !           349:                 * This is probably bogus, but it lets vn_open()
        !           350:                 * weed out directories, sockets, etc. so we don't
        !           351:                 * have to worry about them.
        !           352:                 */
        !           353:                nd.ni_segflg = UIO_USERSPACE;
        !           354:                nd.ni_dirp = vio->vn_file;
        !           355:                if (error = vn_open(&nd, p, FREAD|FWRITE, 0))
        !           356:                        return(error);
        !           357:                if (error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p)) {
        !           358:                        VOP_UNLOCK(nd.ni_vp);
        !           359:                        (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
        !           360:                        return(error);
        !           361:                }
        !           362:                VOP_UNLOCK(nd.ni_vp);
        !           363:                vn->sc_vp = nd.ni_vp;
        !           364:                vn->sc_size = btodb(vattr.va_size);     /* note truncation */
        !           365:                if (error = vnsetcred(vn, p->p_ucred)) {
        !           366:                        (void) vn_close(vn->sc_vp, FREAD|FWRITE, p->p_ucred, p);
        !           367:                        return(error);
        !           368:                }
        !           369:                vnthrottle(vn, vn->sc_vp);
        !           370:                vio->vn_size = dbtob(vn->sc_size);
        !           371:                vn->sc_flags |= VNF_INITED;
        !           372: #ifdef DEBUG
        !           373:                if (vndebug & VDB_INIT)
        !           374:                        printf("vnioctl: SET vp %x size %x\n",
        !           375:                               vn->sc_vp, vn->sc_size);
        !           376: #endif
        !           377:                break;
        !           378: 
        !           379:        case VNIOCCLR:
        !           380:                if ((vn->sc_flags & VNF_INITED) == 0)
        !           381:                        return(ENXIO);
        !           382:                vnclear(vn);
        !           383: #ifdef DEBUG
        !           384:                if (vndebug & VDB_INIT)
        !           385:                        printf("vnioctl: CLRed\n");
        !           386: #endif
        !           387:                break;
        !           388: 
        !           389:        default:
        !           390:                return(ENXIO);
        !           391:        }
        !           392:        return(0);
        !           393: }
        !           394: 
        !           395: /*
        !           396:  * Duplicate the current processes' credentials.  Since we are called only
        !           397:  * as the result of a SET ioctl and only root can do that, any future access
        !           398:  * to this "disk" is essentially as root.  Note that credentials may change
        !           399:  * if some other uid can write directly to the mapped file (NFS).
        !           400:  */
        !           401: vnsetcred(vn, cred)
        !           402:        register struct vn_softc *vn;
        !           403:        struct ucred *cred;
        !           404: {
        !           405:        struct uio auio;
        !           406:        struct iovec aiov;
        !           407:        char tmpbuf[DEV_BSIZE];
        !           408: 
        !           409:        vn->sc_cred = crdup(cred);
        !           410:        /* XXX: Horrible kludge to establish credentials for NFS */
        !           411:        aiov.iov_base = tmpbuf;
        !           412:        aiov.iov_len = MIN(DEV_BSIZE, dbtob(vn->sc_size));
        !           413:        auio.uio_iov = &aiov;
        !           414:        auio.uio_iovcnt = 1;
        !           415:        auio.uio_offset = 0;
        !           416:        auio.uio_rw = UIO_READ;
        !           417:        auio.uio_segflg = UIO_SYSSPACE;
        !           418:        auio.uio_resid = aiov.iov_len;
        !           419:        return(VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred));
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * Set maxactive based on FS type
        !           424:  */
        !           425: vnthrottle(vn, vp)
        !           426:        register struct vn_softc *vn;
        !           427:        struct vnode *vp;
        !           428: {
        !           429:        extern struct vnodeops ufs_vnodeops, nfsv2_vnodeops;
        !           430: 
        !           431:        if (vp->v_op == &nfsv2_vnodeops)
        !           432:                vn->sc_maxactive = 2;
        !           433:        else
        !           434:                vn->sc_maxactive = 8;
        !           435: 
        !           436:        if (vn->sc_maxactive < 1)
        !           437:                vn->sc_maxactive = 1;
        !           438: }
        !           439: 
        !           440: vnshutdown()
        !           441: {
        !           442:        register struct vn_softc *vn;
        !           443: 
        !           444:        for (vn = &vn_softc[0]; vn < &vn_softc[NVN]; vn++)
        !           445:                if (vn->sc_flags & VNF_INITED)
        !           446:                        vnclear(vn);
        !           447: }
        !           448: 
        !           449: vnclear(vn)
        !           450:        register struct vn_softc *vn;
        !           451: {
        !           452:        register struct vnode *vp = vn->sc_vp;
        !           453:        struct proc *p = curproc;               /* XXX */
        !           454: 
        !           455: #ifdef DEBUG
        !           456:        if (vndebug & VDB_FOLLOW)
        !           457:                printf("vnclear(%x): vp %x\n", vp);
        !           458: #endif
        !           459:        vn->sc_flags &= ~VNF_INITED;
        !           460:        if (vp == (struct vnode *)0)
        !           461:                panic("vnioctl: null vp");
        !           462: #if 0
        !           463:        /* XXX - this doesn't work right now */
        !           464:        (void) VOP_FSYNC(vp, 0, vn->sc_cred, MNT_WAIT, p);
        !           465: #endif
        !           466:        (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
        !           467:        crfree(vn->sc_cred);
        !           468:        vn->sc_vp = (struct vnode *)0;
        !           469:        vn->sc_cred = (struct ucred *)0;
        !           470:        vn->sc_size = 0;
        !           471: }
        !           472: 
        !           473: vnsize(dev)
        !           474:        dev_t dev;
        !           475: {
        !           476:        int unit = vnunit(dev);
        !           477:        register struct vn_softc *vn = &vn_softc[unit];
        !           478: 
        !           479:        if (unit >= NVN || (vn->sc_flags & VNF_INITED) == 0)
        !           480:                return(-1);
        !           481:        return(vn->sc_size);
        !           482: }
        !           483: 
        !           484: vndump(dev)
        !           485: {
        !           486:        return(ENXIO);
        !           487: }
        !           488: #endif

unix.superglobalmegacorp.com

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