Annotation of 43BSDReno/sys/hpdev/fd.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 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.