Annotation of Net2/arch/amiga/dev/vn.c, revision 1.1.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.