Annotation of Net2/arch/hp300/dev/vn.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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