Annotation of 43BSDReno/sys/hpdev/fd.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 is only permitted until one year after the first shipment
        !            11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            12:  * binary forms are permitted provided that: (1) source distributions retain
        !            13:  * this entire copyright notice and comment, and (2) distributions including
        !            14:  * binaries display the following acknowledgement:  This product includes
        !            15:  * software developed by the University of California, Berkeley and its
        !            16:  * contributors'' in the documentation or other materials provided with the
        !            17:  * distribution and in all advertising materials mentioning features or use
        !            18:  * of this software.  Neither the name of the University nor the names of
        !            19:  * its contributors may be used to endorse or promote products derived from
        !            20:  * this software without specific prior written permission.
        !            21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            24:  *
        !            25:  * from: Utah $Hdr: fd.c 1.3 89/12/03$
        !            26:  *
        !            27:  *     @(#)fd.c        7.1 (Berkeley) 5/8/90
        !            28:  */
        !            29: 
        !            30: /*
        !            31:  * File (vnode) disk driver.
        !            32:  *
        !            33:  * Block/character interface to a vnode.  Note that this uses the
        !            34:  * VOP_BMAP/VOP_STRATEGY interface to the vnode instead of a simple
        !            35:  * VOP_RDWR.  We do this to avoid distorting the local buffer cache.
        !            36:  *
        !            37:  * NOTE: There is a security issue involved with this driver.
        !            38:  * Once mounted all access to the contents of the "mapped" file via
        !            39:  * the special file is controlled by the permissions on the special
        !            40:  * file, the protection of the mapped file is ignored (effectively,
        !            41:  * by using root credentials in all transactions).
        !            42:  */
        !            43: #include "fd.h"
        !            44: #if NFD > 0
        !            45: 
        !            46: #include "param.h"
        !            47: #include "systm.h"
        !            48: #include "buf.h"
        !            49: #include "errno.h"
        !            50: #include "dkstat.h"
        !            51: #include "ioctl.h"
        !            52: #include "user.h"
        !            53: #include "vfs.h"
        !            54: #include "vnode.h"
        !            55: #include "file.h"
        !            56: #include "uio.h"
        !            57: #include "malloc.h"
        !            58: 
        !            59: #include "fdioctl.h"
        !            60: 
        !            61: #ifdef DEBUG
        !            62: int fddebug = 0x00;
        !            63: #define FDB_FOLLOW     0x01
        !            64: #define FDB_INIT       0x02
        !            65: #define FDB_IO         0x04
        !            66: #endif
        !            67: 
        !            68: struct buf fdbuf[NFD];
        !            69: struct buf fdtab[NFD];
        !            70: 
        !            71: #define b_cylin        b_resid
        !            72: 
        !            73: #define        fdunit(x)       ((minor(x) >> 3) & 0x7) /* for consistency */
        !            74: 
        !            75: #define        getfdbuf()      \
        !            76:        ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
        !            77: #define putfdbuf(bp)   \
        !            78:        free((caddr_t)(bp), M_DEVBUF)
        !            79: 
        !            80: struct fd_softc {
        !            81:        int              sc_flags;      /* flags */
        !            82:        size_t           sc_size;       /* size of fd */
        !            83:        struct vnode    *sc_vp;         /* vnode */
        !            84:        struct ucred    *sc_cred;       /* credentials */
        !            85:        int              sc_maxactive;  /* max # of active requests */
        !            86: } fd_softc[NFD];
        !            87: 
        !            88: /* sc_flags */
        !            89: #define        FDF_ALIVE       0x01
        !            90: #define FDF_INITED     0x02
        !            91: 
        !            92: fdopen(dev, flags)
        !            93:        dev_t dev;
        !            94: {
        !            95:        int unit = fdunit(dev);
        !            96: 
        !            97: #ifdef DEBUG
        !            98:        if (fddebug & FDB_FOLLOW)
        !            99:                printf("fdopen(%x, %x)\n", dev, flags);
        !           100: #endif
        !           101:        if (unit >= NFD)
        !           102:                return(ENXIO);
        !           103:        return(0);
        !           104: }
        !           105: 
        !           106: /*
        !           107:  * Break the request into bsize pieces and submit using VOP_BMAP/VOP_STRATEGY.
        !           108:  * Note that this driver can only be used for swapping over NFS on the hp
        !           109:  * since nfs_strategy on the vax cannot handle u-areas and page tables.
        !           110:  */
        !           111: fdstrategy(bp)
        !           112:        register struct buf *bp;
        !           113: {
        !           114:        int unit = fdunit(bp->b_dev);
        !           115:        register struct fd_softc *fs = &fd_softc[unit];
        !           116:        register struct buf *nbp;
        !           117:        register int bn, bsize, resid;
        !           118:        register caddr_t addr;
        !           119:        int sz, flags;
        !           120:        extern int fdiodone();
        !           121: 
        !           122: #ifdef DEBUG
        !           123:        if (fddebug & FDB_FOLLOW)
        !           124:                printf("fdstrategy(%x): unit %d\n", bp, unit);
        !           125: #endif
        !           126:        if ((fs->sc_flags & FDF_INITED) == 0) {
        !           127:                bp->b_error = ENXIO;
        !           128:                bp->b_flags |= B_ERROR;
        !           129:                iodone(bp);
        !           130:                return;
        !           131:        }
        !           132:        bn = bp->b_blkno;
        !           133:        sz = howmany(bp->b_bcount, DEV_BSIZE);
        !           134:        bp->b_resid = bp->b_bcount;
        !           135:        if (bn < 0 || bn + sz > fs->sc_size) {
        !           136:                if (bn != fs->sc_size) {
        !           137:                        bp->b_error = EINVAL;
        !           138:                        bp->b_flags |= B_ERROR;
        !           139:                }
        !           140:                iodone(bp);
        !           141:                return;
        !           142:        }
        !           143:        bn = dbtob(bn);
        !           144:        bsize = fs->sc_vp->v_vfsp->vfs_bsize;
        !           145:        addr = bp->b_un.b_addr;
        !           146:        flags = bp->b_flags | B_CALL;
        !           147:        for (resid = bp->b_resid; resid; resid -= sz) {
        !           148:                struct vnode *vp;
        !           149:                daddr_t nbn;
        !           150:                int off, s;
        !           151: 
        !           152:                nbp = getfdbuf();
        !           153:                off = bn % bsize;
        !           154:                sz = MIN(bsize - off, resid);
        !           155:                (void) VOP_BMAP(fs->sc_vp, bn / bsize, &vp, &nbn);
        !           156: #ifdef DEBUG
        !           157:                if (fddebug & FDB_IO)
        !           158:                        printf("fdstrategy: vp %x/%x bn %x/%x dev %x\n",
        !           159:                               fs->sc_vp, vp, bn, nbn, vp->v_rdev);
        !           160: #endif
        !           161:                nbp->b_flags = flags;
        !           162:                nbp->b_bcount = sz;
        !           163:                nbp->b_bufsize = bp->b_bufsize;
        !           164:                nbp->b_error = 0;
        !           165:                nbp->b_dev = vp->v_rdev;
        !           166:                nbp->b_un.b_addr = addr;
        !           167:                nbp->b_blkno = nbn + btodb(off);
        !           168:                nbp->b_proc = bp->b_proc;
        !           169:                nbp->b_iodone = fdiodone;
        !           170:                nbp->b_vp = vp;
        !           171:                nbp->b_pfcent = (int) bp;       /* XXX */
        !           172:                /*
        !           173:                 * Just sort by block number
        !           174:                 */
        !           175:                nbp->b_cylin = nbp->b_blkno;
        !           176:                s = splbio();
        !           177:                disksort(&fdtab[unit], nbp);
        !           178:                if (fdtab[unit].b_active < fs->sc_maxactive) {
        !           179:                        fdtab[unit].b_active++;
        !           180:                        fdstart(unit);
        !           181:                }
        !           182:                splx(s);
        !           183:                bn += sz;
        !           184:                addr += sz;
        !           185:        }
        !           186: }
        !           187: 
        !           188: /*
        !           189:  * Feed requests sequentially.
        !           190:  * We do it this way to keep from flooding NFS servers if we are connected
        !           191:  * to an NFS file.  This places the burden on the client rather than the
        !           192:  * server.
        !           193:  */
        !           194: fdstart(unit)
        !           195: {
        !           196:        register struct fd_softc *fs = &fd_softc[unit];
        !           197:        register struct buf *bp;
        !           198: 
        !           199:        /*
        !           200:         * Dequeue now since lower level strategy routine might
        !           201:         * queue using same links
        !           202:         */
        !           203:        bp = fdtab[unit].b_actf;
        !           204:        fdtab[unit].b_actf = bp->b_actf;
        !           205: #ifdef DEBUG
        !           206:        if (fddebug & FDB_IO)
        !           207:                printf("fdstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
        !           208:                       unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr,
        !           209:                       bp->b_bcount);
        !           210: #endif
        !           211:        VOP_STRATEGY(bp);
        !           212: }
        !           213: 
        !           214: fdiodone(bp)
        !           215:        register struct buf *bp;
        !           216: {
        !           217:        register struct buf *pbp = (struct buf *)bp->b_pfcent;  /* XXX */
        !           218:        register int unit = fdunit(pbp->b_dev);
        !           219:        int s;
        !           220: 
        !           221:        s = splbio();
        !           222: #ifdef DEBUG
        !           223:        if (fddebug & FDB_IO)
        !           224:                printf("fdiodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
        !           225:                       unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr,
        !           226:                       bp->b_bcount);
        !           227: #endif
        !           228:        if (bp->b_error) {
        !           229: #ifdef DEBUG
        !           230:                if (fddebug & FDB_IO)
        !           231:                        printf("fdiodone: bp %x error %d\n", bp, bp->b_error);
        !           232: #endif
        !           233:                pbp->b_flags |= B_ERROR;
        !           234:                pbp->b_error = geterror(bp);
        !           235:        }
        !           236:        pbp->b_resid -= bp->b_bcount;
        !           237:        putfdbuf(bp);
        !           238:        if (pbp->b_resid == 0) {
        !           239: #ifdef DEBUG
        !           240:                if (fddebug & FDB_IO)
        !           241:                        printf("fdiodone: pbp %x iodone\n", pbp);
        !           242: #endif
        !           243:                iodone(pbp);
        !           244:        }
        !           245:        if (fdtab[unit].b_actf)
        !           246:                fdstart(unit);
        !           247:        else
        !           248:                fdtab[unit].b_active--;
        !           249:        splx(s);
        !           250: }
        !           251: 
        !           252: fdread(dev, uio)
        !           253:        dev_t dev;
        !           254:        struct uio *uio;
        !           255: {
        !           256:        register int unit = fdunit(dev);
        !           257: 
        !           258: #ifdef DEBUG
        !           259:        if (fddebug & FDB_FOLLOW)
        !           260:                printf("fdread(%x, %x)\n", dev, uio);
        !           261: #endif
        !           262:        return(physio(fdstrategy, &fdbuf[unit], dev, B_READ, minphys, uio));
        !           263: }
        !           264: 
        !           265: fdwrite(dev, uio)
        !           266:        dev_t dev;
        !           267:        struct uio *uio;
        !           268: {
        !           269:        register int unit = fdunit(dev);
        !           270: 
        !           271: #ifdef DEBUG
        !           272:        if (fddebug & FDB_FOLLOW)
        !           273:                printf("fdwrite(%x, %x)\n", dev, uio);
        !           274: #endif
        !           275:        return(physio(fdstrategy, &fdbuf[unit], dev, B_WRITE, minphys, uio));
        !           276: }
        !           277: 
        !           278: /* ARGSUSED */
        !           279: fdioctl(dev, cmd, data, flag)
        !           280:        dev_t dev;
        !           281:        u_long cmd;
        !           282:        caddr_t data;
        !           283:        int flag;
        !           284: {
        !           285:        int unit = fdunit(dev);
        !           286:        register struct fd_softc *fs;
        !           287:        struct fd_ioctl *fio;
        !           288:        struct vattr vattr;
        !           289:        struct vnode *vp;
        !           290:        int error;
        !           291: 
        !           292: #ifdef DEBUG
        !           293:        if (fddebug & FDB_FOLLOW)
        !           294:                printf("fdioctl(%x, %x, %x, %x): unit %d\n",
        !           295:                       dev, cmd, data, flag, unit);
        !           296: #endif
        !           297:        error = suser(u.u_cred, &u.u_acflag);
        !           298:        if (error)
        !           299:                return (error);
        !           300:        if (unit >= NFD)
        !           301:                return (ENXIO);
        !           302: 
        !           303:        fs = &fd_softc[unit];
        !           304:        fio = (struct fd_ioctl *)data;
        !           305:        switch (cmd) {
        !           306: 
        !           307:        case FDIOCSET:
        !           308:                if (fs->sc_flags & FDF_INITED)
        !           309:                        return(EBUSY);
        !           310:                /*
        !           311:                 * Always open for read and write.
        !           312:                 * This is probably bogus, but it lets vn_open()
        !           313:                 * weed out directories, sockets, etc. so we don't
        !           314:                 * have to worry about them.
        !           315:                 */
        !           316:                error = vn_open(fio->fd_file, UIO_USERSPACE,
        !           317:                                FREAD|FWRITE, 0, &vp);
        !           318:                if (error)
        !           319:                        return(error);
        !           320:                error = VOP_GETATTR(vp, &vattr, u.u_cred);
        !           321:                if (error) {
        !           322:                        vn_close(vp, FREAD|FWRITE);
        !           323:                        VN_RELE(vp);
        !           324:                        return(error);
        !           325:                }
        !           326:                fs->sc_vp = vp;
        !           327:                fs->sc_size = btodb(vattr.va_size);     /* note truncation */
        !           328:                error = fdsetcred(fs);
        !           329:                if (error) {
        !           330:                        vn_close(vp, FREAD|FWRITE);
        !           331:                        VN_RELE(vp);
        !           332:                        return(error);
        !           333:                }
        !           334:                fdthrottle(fs, vp);
        !           335:                fio->fd_size = dbtob(fs->sc_size);
        !           336:                fs->sc_flags |= FDF_INITED;
        !           337: #ifdef DEBUG
        !           338:                if (fddebug & FDB_INIT)
        !           339:                        printf("fdioctl: SET vp %x size %x\n",
        !           340:                               fs->sc_vp, fs->sc_size);
        !           341: #endif
        !           342:                break;
        !           343: 
        !           344:        case FDIOCCLR:
        !           345:                if ((fs->sc_flags & FDF_INITED) == 0)
        !           346:                        return(ENXIO);
        !           347:                fdclear(fs);
        !           348: #ifdef DEBUG
        !           349:                if (fddebug & FDB_INIT)
        !           350:                        printf("fdioctl: CLRed\n");
        !           351: #endif
        !           352:                break;
        !           353: 
        !           354:        default:
        !           355:                return(ENXIO);
        !           356:        }
        !           357:        return(0);
        !           358: }
        !           359: 
        !           360: /*
        !           361:  * Duplicate the current processes' credentials.  Since we are called only
        !           362:  * as the result of a SET ioctl and only root can do that, any future access
        !           363:  * to this "disk" is essentially as root.  Note that credentials may change
        !           364:  * if some other uid can write directly to the mapped file (NFS).
        !           365:  */
        !           366: fdsetcred(fs)
        !           367:        register struct fd_softc *fs;
        !           368: {
        !           369:        struct uio auio;
        !           370:        struct iovec aiov;
        !           371:        char tmpbuf[DEV_BSIZE];
        !           372: 
        !           373:        fs->sc_cred = crdup(u.u_cred);
        !           374:        /* XXX: Horrible kludge to establish credentials for NFS */
        !           375:        aiov.iov_base = tmpbuf;
        !           376:        aiov.iov_len = MIN(DEV_BSIZE, dbtob(fs->sc_size));
        !           377:        auio.uio_iov = &aiov;
        !           378:        auio.uio_iovcnt = 1;
        !           379:        auio.uio_offset = 0;
        !           380:        auio.uio_rw = UIO_READ;
        !           381:        auio.uio_segflg = UIO_SYSSPACE;
        !           382:        auio.uio_resid = aiov.iov_len;
        !           383:        return(VOP_READ(fs->sc_vp, &auio, 0, fs->sc_cred));
        !           384: }
        !           385: 
        !           386: /*
        !           387:  * Set maxactive based on FS type
        !           388:  */
        !           389: fdthrottle(fs, vp)
        !           390:        register struct fd_softc *fs;
        !           391:        struct vnode *vp;
        !           392: {
        !           393:        extern struct vnodeops ufs_vnodeops, nfs_vnodeops;
        !           394: 
        !           395:        if (vp->v_op == &nfs_vnodeops)
        !           396:                fs->sc_maxactive = 2;
        !           397:        else
        !           398:                fs->sc_maxactive = 8;
        !           399: 
        !           400:        if (fs->sc_maxactive < 1)
        !           401:                fs->sc_maxactive = 1;
        !           402: }
        !           403: 
        !           404: fdshutdown()
        !           405: {
        !           406:        register struct fd_softc *fs;
        !           407: 
        !           408:        for (fs = &fd_softc[0]; fs < &fd_softc[NFD]; fs++)
        !           409:                if (fs->sc_flags & FDF_INITED)
        !           410:                        fdclear(fs);
        !           411: }
        !           412: 
        !           413: fdclear(fs)
        !           414:        register struct fd_softc *fs;
        !           415: {
        !           416:        register struct vnode *vp = fs->sc_vp;
        !           417: 
        !           418: #ifdef DEBUG
        !           419:        if (fddebug & FDB_FOLLOW)
        !           420:                printf("fdclear(%x): vp %x\n", vp);
        !           421: #endif
        !           422:        fs->sc_flags &= ~FDF_INITED;
        !           423:        if (vp == (struct vnode *)0)
        !           424:                panic("fdioctl: null vp");
        !           425: #if 0
        !           426:        /* XXX - this doesn't work right now */
        !           427:        (void) VOP_FSYNC(vp, fs->sc_cred);
        !           428: #endif
        !           429:        vn_close(vp, FREAD|FWRITE);
        !           430:        VN_RELE(vp);
        !           431:        crfree(fs->sc_cred);
        !           432:        fs->sc_vp = (struct vnode *)0;
        !           433:        fs->sc_cred = (struct ucred *)0;
        !           434:        fs->sc_size = 0;
        !           435: }
        !           436: 
        !           437: fdsize(dev)
        !           438:        dev_t dev;
        !           439: {
        !           440:        int unit = fdunit(dev);
        !           441:        register struct fd_softc *fs = &fd_softc[unit];
        !           442: 
        !           443:        if (unit >= NFD || (fs->sc_flags & FDF_INITED) == 0)
        !           444:                return(-1);
        !           445:        return(fs->sc_size);
        !           446: }
        !           447: 
        !           448: fddump(dev)
        !           449: {
        !           450:        return(ENXIO);
        !           451: }
        !           452: #endif

unix.superglobalmegacorp.com

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