X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/0893c3537a2bf76d972ca8dc62a96d7689e6c927..38a01dbeac9414d4cc0fa1a01ae498024a183078:/usr/src/sys/dev/vn.c diff --git a/usr/src/sys/dev/vn.c b/usr/src/sys/dev/vn.c index d388b1e96f..b1f1655a84 100644 --- a/usr/src/sys/dev/vn.c +++ b/usr/src/sys/dev/vn.c @@ -9,87 +9,92 @@ * * %sccs.include.redist.c% * - * from: Utah $Hdr: fd.c 1.1 90/07/09$ + * from: Utah $Hdr: fd.c 1.3 89/12/03$ * - * @(#)vn.c 7.4 (Berkeley) %G% + * @(#)vn.c 7.14 (Berkeley) %G% */ /* - * CURRENTLY BROKEN; the name "fd" collides with /dev/fd/xxx. - * This would need to be converted to the new proc/user layout as well. - */ -/* - * File (vnode) disk driver. + * Vnode disk driver. * - * Block/character interface to a vnode. Note that this uses the - * VOP_BMAP/VOP_STRATEGY interface to the vnode instead of a simple - * VOP_RDWR. We do this to avoid distorting the local buffer cache. + * Block/character interface to a vnode. Allows one to treat a file + * as a disk (e.g. build a filesystem in it, mount it, etc.). * - * NOTE: There is a security issue involved with this driver. + * NOTE 1: This uses the VOP_BMAP/VOP_STRATEGY interface to the vnode + * instead of a simple VOP_RDWR. We do this to avoid distorting the + * local buffer cache. + * + * NOTE 2: There is a security issue involved with this driver. * Once mounted all access to the contents of the "mapped" file via * the special file is controlled by the permissions on the special * file, the protection of the mapped file is ignored (effectively, * by using root credentials in all transactions). */ -#include "fd.h" -#if NFD > 0 - -#include "sys/param.h" -#include "sys/systm.h" -#include "sys/buf.h" -#include "sys/errno.h" -#include "sys/dkstat.h" -#include "sys/ioctl.h" -#include "sys/user.h" -#include "sys/vfs.h" -#include "sys/vnode.h" -#include "sys/file.h" -#include "sys/uio.h" -#include "sys/malloc.h" - -#include "fdioctl.h" +#include "vn.h" +#if NVN > 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #ifdef DEBUG -int fddebug = 0x00; -#define FDB_FOLLOW 0x01 -#define FDB_INIT 0x02 -#define FDB_IO 0x04 +int vndebug = 0x00; +#define VDB_FOLLOW 0x01 +#define VDB_INIT 0x02 +#define VDB_IO 0x04 #endif -struct buf fdbuf[NFD]; -struct buf fdtab[NFD]; +struct buf vnbuf[NVN]; +struct buf vntab[NVN]; #define b_cylin b_resid -#define fdunit(x) ((minor(x) >> 3) & 0x7) /* for consistency */ +#define vnunit(x) ((minor(x) >> 3) & 0x7) /* for consistency */ -#define getfdbuf() \ +#define getvnbuf() \ ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK)) -#define putfdbuf(bp) \ +#define putvnbuf(bp) \ free((caddr_t)(bp), M_DEVBUF) -struct fd_softc { +struct vn_softc { int sc_flags; /* flags */ - size_t sc_size; /* size of fd */ + size_t sc_size; /* size of vn */ struct vnode *sc_vp; /* vnode */ struct ucred *sc_cred; /* credentials */ int sc_maxactive; /* max # of active requests */ -} fd_softc[NFD]; +} vn_softc[NVN]; /* sc_flags */ -#define FDF_ALIVE 0x01 -#define FDF_INITED 0x02 +#define VNF_ALIVE 0x01 +#define VNF_INITED 0x02 -fdopen(dev, flags) +int +vnopen(dev, flags, mode, p) dev_t dev; + int flags, mode; + struct proc *p; { - int unit = fdunit(dev); + int unit = vnunit(dev); #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdopen(%x, %x)\n", dev, flags); + if (vndebug & VDB_FOLLOW) + printf("vnopen(%x, %x, %x, %x)\n", dev, flags, mode, p); #endif - if (unit >= NFD) + if (unit >= NVN) return(ENXIO); return(0); } @@ -99,40 +104,40 @@ fdopen(dev, flags) * Note that this driver can only be used for swapping over NFS on the hp * since nfs_strategy on the vax cannot handle u-areas and page tables. */ -fdstrategy(bp) +vnstrategy(bp) register struct buf *bp; { - int unit = fdunit(bp->b_dev); - register struct fd_softc *fs = &fd_softc[unit]; + int unit = vnunit(bp->b_dev); + register struct vn_softc *vn = &vn_softc[unit]; register struct buf *nbp; register int bn, bsize, resid; register caddr_t addr; int sz, flags; - extern int fdiodone(); + extern void vniodone(); #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdstrategy(%x): unit %d\n", bp, unit); + if (vndebug & VDB_FOLLOW) + printf("vnstrategy(%x): unit %d\n", bp, unit); #endif - if ((fs->sc_flags & FDF_INITED) == 0) { + if ((vn->sc_flags & VNF_INITED) == 0) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; - iodone(bp); + biodone(bp); return; } bn = bp->b_blkno; sz = howmany(bp->b_bcount, DEV_BSIZE); bp->b_resid = bp->b_bcount; - if (bn < 0 || bn + sz > fs->sc_size) { - if (bn != fs->sc_size) { + if (bn < 0 || bn + sz > vn->sc_size) { + if (bn != vn->sc_size) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; } - iodone(bp); + biodone(bp); return; } bn = dbtob(bn); - bsize = fs->sc_vp->v_vfsp->vfs_bsize; + bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize; addr = bp->b_un.b_addr; flags = bp->b_flags | B_CALL; for (resid = bp->b_resid; resid; resid -= sz) { @@ -140,24 +145,27 @@ fdstrategy(bp) daddr_t nbn; int off, s; - nbp = getfdbuf(); + nbp = getvnbuf(); off = bn % bsize; - sz = MIN(bsize - off, resid); - (void) VOP_BMAP(fs->sc_vp, bn / bsize, &vp, &nbn); + sz = min(bsize - off, resid); + (void) VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn, NULL); #ifdef DEBUG - if (fddebug & FDB_IO) - printf("fdstrategy: vp %x/%x bn %x/%x dev %x\n", - fs->sc_vp, vp, bn, nbn, vp->v_rdev); + if (vndebug & VDB_IO) + printf("vnstrategy: vp %x/%x bn %x/%x\n", + vn->sc_vp, vp, bn, nbn); #endif nbp->b_flags = flags; nbp->b_bcount = sz; nbp->b_bufsize = bp->b_bufsize; nbp->b_error = 0; - nbp->b_dev = vp->v_rdev; + if (vp->v_type == VBLK || vp->v_type == VCHR) + nbp->b_dev = vp->v_rdev; + else + nbp->b_dev = NODEV; nbp->b_un.b_addr = addr; nbp->b_blkno = nbn + btodb(off); nbp->b_proc = bp->b_proc; - nbp->b_iodone = fdiodone; + nbp->b_iodone = vniodone; nbp->b_vp = vp; nbp->b_pfcent = (int) bp; /* XXX */ /* @@ -165,10 +173,10 @@ fdstrategy(bp) */ nbp->b_cylin = nbp->b_blkno; s = splbio(); - disksort(&fdtab[unit], nbp); - if (fdtab[unit].b_active < fs->sc_maxactive) { - fdtab[unit].b_active++; - fdstart(unit); + disksort(&vntab[unit], nbp); + if (vntab[unit].b_active < vn->sc_maxactive) { + vntab[unit].b_active++; + vnstart(unit); } splx(s); bn += sz; @@ -182,121 +190,127 @@ fdstrategy(bp) * to an NFS file. This places the burden on the client rather than the * server. */ -fdstart(unit) +vnstart(unit) { - register struct fd_softc *fs = &fd_softc[unit]; + register struct vn_softc *vn = &vn_softc[unit]; register struct buf *bp; /* * Dequeue now since lower level strategy routine might * queue using same links */ - bp = fdtab[unit].b_actf; - fdtab[unit].b_actf = bp->b_actf; + bp = vntab[unit].b_actf; + vntab[unit].b_actf = bp->b_actf; #ifdef DEBUG - if (fddebug & FDB_IO) - printf("fdstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n", + if (vndebug & VDB_IO) + printf("vnstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n", unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr, bp->b_bcount); #endif VOP_STRATEGY(bp); } -fdiodone(bp) +void +vniodone(bp) register struct buf *bp; { register struct buf *pbp = (struct buf *)bp->b_pfcent; /* XXX */ - register int unit = fdunit(pbp->b_dev); + register int unit = vnunit(pbp->b_dev); int s; s = splbio(); #ifdef DEBUG - if (fddebug & FDB_IO) - printf("fdiodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n", + if (vndebug & VDB_IO) + printf("vniodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n", unit, bp, bp->b_vp, bp->b_blkno, bp->b_un.b_addr, bp->b_bcount); #endif if (bp->b_error) { #ifdef DEBUG - if (fddebug & FDB_IO) - printf("fdiodone: bp %x error %d\n", bp, bp->b_error); + if (vndebug & VDB_IO) + printf("vniodone: bp %x error %d\n", bp, bp->b_error); #endif pbp->b_flags |= B_ERROR; - pbp->b_error = geterror(bp); + pbp->b_error = biowait(bp); } pbp->b_resid -= bp->b_bcount; - putfdbuf(bp); + putvnbuf(bp); if (pbp->b_resid == 0) { #ifdef DEBUG - if (fddebug & FDB_IO) - printf("fdiodone: pbp %x iodone\n", pbp); + if (vndebug & VDB_IO) + printf("vniodone: pbp %x iodone\n", pbp); #endif - iodone(pbp); + biodone(pbp); } - if (fdtab[unit].b_actf) - fdstart(unit); + if (vntab[unit].b_actf) + vnstart(unit); else - fdtab[unit].b_active--; + vntab[unit].b_active--; splx(s); } -fdread(dev, uio) +vnread(dev, uio, flags, p) dev_t dev; struct uio *uio; + int flags; + struct proc *p; { - register int unit = fdunit(dev); + register int unit = vnunit(dev); #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdread(%x, %x)\n", dev, uio); + if (vndebug & VDB_FOLLOW) + printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p); #endif - return(physio(fdstrategy, &fdbuf[unit], dev, B_READ, minphys, uio)); + return(physio(vnstrategy, &vnbuf[unit], dev, B_READ, minphys, uio)); } -fdwrite(dev, uio) +vnwrite(dev, uio, flags, p) dev_t dev; struct uio *uio; + int flags; + struct proc *p; { - register int unit = fdunit(dev); + register int unit = vnunit(dev); #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdwrite(%x, %x)\n", dev, uio); + if (vndebug & VDB_FOLLOW) + printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p); #endif - return(physio(fdstrategy, &fdbuf[unit], dev, B_WRITE, minphys, uio)); + return(physio(vnstrategy, &vnbuf[unit], dev, B_WRITE, minphys, uio)); } /* ARGSUSED */ -fdioctl(dev, cmd, data, flag) +vnioctl(dev, cmd, data, flag, p) dev_t dev; u_long cmd; caddr_t data; int flag; + struct proc *p; { - int unit = fdunit(dev); - register struct fd_softc *fs; - struct fd_ioctl *fio; + int unit = vnunit(dev); + register struct vn_softc *vn; + struct vn_ioctl *vio; struct vattr vattr; - struct vnode *vp; + struct nameidata nd; int error; #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdioctl(%x, %x, %x, %x): unit %d\n", - dev, cmd, data, flag, unit); + if (vndebug & VDB_FOLLOW) + printf("vnioctl(%x, %x, %x, %x, %x): unit %d\n", + dev, cmd, data, flag, p, unit); #endif - error = suser(u.u_cred, &u.u_acflag); + error = suser(p->p_ucred, &p->p_acflag); if (error) return (error); - if (unit >= NFD) + if (unit >= NVN) return (ENXIO); - fs = &fd_softc[unit]; - fio = (struct fd_ioctl *)data; + vn = &vn_softc[unit]; + vio = (struct vn_ioctl *)data; switch (cmd) { - case FDIOCSET: - if (fs->sc_flags & FDF_INITED) + case VNIOCSET: + if (vn->sc_flags & VNF_INITED) return(EBUSY); /* * Always open for read and write. @@ -304,41 +318,38 @@ fdioctl(dev, cmd, data, flag) * weed out directories, sockets, etc. so we don't * have to worry about them. */ - error = vn_open(fio->fd_file, UIO_USERSPACE, - FREAD|FWRITE, 0, &vp); - if (error) + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vn_file, p); + if (error = vn_open(&nd, FREAD|FWRITE, 0)) return(error); - error = VOP_GETATTR(vp, &vattr, u.u_cred); - if (error) { - vn_close(vp, FREAD|FWRITE); - VN_RELE(vp); + if (error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p)) { + VOP_UNLOCK(nd.ni_vp); + (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p); return(error); } - fs->sc_vp = vp; - fs->sc_size = btodb(vattr.va_size); /* note truncation */ - error = fdsetcred(fs); - if (error) { - vn_close(vp, FREAD|FWRITE); - VN_RELE(vp); + VOP_UNLOCK(nd.ni_vp); + vn->sc_vp = nd.ni_vp; + vn->sc_size = btodb(vattr.va_size); /* note truncation */ + if (error = vnsetcred(vn, p->p_ucred)) { + (void) vn_close(vn->sc_vp, FREAD|FWRITE, p->p_ucred, p); return(error); } - fdthrottle(fs, vp); - fio->fd_size = dbtob(fs->sc_size); - fs->sc_flags |= FDF_INITED; + vnthrottle(vn, vn->sc_vp); + vio->vn_size = dbtob(vn->sc_size); + vn->sc_flags |= VNF_INITED; #ifdef DEBUG - if (fddebug & FDB_INIT) - printf("fdioctl: SET vp %x size %x\n", - fs->sc_vp, fs->sc_size); + if (vndebug & VDB_INIT) + printf("vnioctl: SET vp %x size %x\n", + vn->sc_vp, vn->sc_size); #endif break; - case FDIOCCLR: - if ((fs->sc_flags & FDF_INITED) == 0) + case VNIOCCLR: + if ((vn->sc_flags & VNF_INITED) == 0) return(ENXIO); - fdclear(fs); + vnclear(vn); #ifdef DEBUG - if (fddebug & FDB_INIT) - printf("fdioctl: CLRed\n"); + if (vndebug & VDB_INIT) + printf("vnioctl: CLRed\n"); #endif break; @@ -354,89 +365,91 @@ fdioctl(dev, cmd, data, flag) * to this "disk" is essentially as root. Note that credentials may change * if some other uid can write directly to the mapped file (NFS). */ -fdsetcred(fs) - register struct fd_softc *fs; +vnsetcred(vn, cred) + register struct vn_softc *vn; + struct ucred cred; { struct uio auio; struct iovec aiov; char tmpbuf[DEV_BSIZE]; - fs->sc_cred = crdup(u.u_cred); + vn->sc_cred = crdup(cred); /* XXX: Horrible kludge to establish credentials for NFS */ aiov.iov_base = tmpbuf; - aiov.iov_len = MIN(DEV_BSIZE, dbtob(fs->sc_size)); + aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size)); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_resid = aiov.iov_len; - return(VOP_READ(fs->sc_vp, &auio, 0, fs->sc_cred)); + return(VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred)); } /* * Set maxactive based on FS type */ -fdthrottle(fs, vp) - register struct fd_softc *fs; +vnthrottle(vn, vp) + register struct vn_softc *vn; struct vnode *vp; { - extern struct vnodeops ufs_vnodeops, nfs_vnodeops; + extern int (**ufs_vnodeop_p)(); + extern int (**nfsv2_vnodeop_p)(); - if (vp->v_op == &nfs_vnodeops) - fs->sc_maxactive = 2; + if (vp->v_op == nfsv2_vnodeop_p) + vn->sc_maxactive = 2; else - fs->sc_maxactive = 8; + vn->sc_maxactive = 8; - if (fs->sc_maxactive < 1) - fs->sc_maxactive = 1; + if (vn->sc_maxactive < 1) + vn->sc_maxactive = 1; } -fdshutdown() +vnshutdown() { - register struct fd_softc *fs; + register struct vn_softc *vn; - for (fs = &fd_softc[0]; fs < &fd_softc[NFD]; fs++) - if (fs->sc_flags & FDF_INITED) - fdclear(fs); + for (vn = &vn_softc[0]; vn < &vn_softc[NVN]; vn++) + if (vn->sc_flags & VNF_INITED) + vnclear(vn); } -fdclear(fs) - register struct fd_softc *fs; +vnclear(vn) + register struct vn_softc *vn; { - register struct vnode *vp = fs->sc_vp; + register struct vnode *vp = vn->sc_vp; + struct proc *p = curproc; /* XXX */ #ifdef DEBUG - if (fddebug & FDB_FOLLOW) - printf("fdclear(%x): vp %x\n", vp); + if (vndebug & VDB_FOLLOW) + printf("vnclear(%x): vp %x\n", vp); #endif - fs->sc_flags &= ~FDF_INITED; + vn->sc_flags &= ~VNF_INITED; if (vp == (struct vnode *)0) - panic("fdioctl: null vp"); + panic("vnioctl: null vp"); #if 0 /* XXX - this doesn't work right now */ - (void) VOP_FSYNC(vp, fs->sc_cred); + (void) VOP_FSYNC(vp, 0, vn->sc_cred, MNT_WAIT, p); #endif - vn_close(vp, FREAD|FWRITE); - VN_RELE(vp); - crfree(fs->sc_cred); - fs->sc_vp = (struct vnode *)0; - fs->sc_cred = (struct ucred *)0; - fs->sc_size = 0; + (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p); + crfree(vn->sc_cred); + vn->sc_vp = (struct vnode *)0; + vn->sc_cred = (struct ucred *)0; + vn->sc_size = 0; } -fdsize(dev) +vnsize(dev) dev_t dev; { - int unit = fdunit(dev); - register struct fd_softc *fs = &fd_softc[unit]; + int unit = vnunit(dev); + register struct vn_softc *vn = &vn_softc[unit]; - if (unit >= NFD || (fs->sc_flags & FDF_INITED) == 0) + if (unit >= NVN || (vn->sc_flags & VNF_INITED) == 0) return(-1); - return(fs->sc_size); + return(vn->sc_size); } -fddump(dev) +vndump(dev) { return(ENXIO); }