oops, forgot to update the Utah id
[unix-history] / usr / src / sys / dev / vn.c
index 59fc0cd..860fbbd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1988 University of Utah.
 /*
  * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
@@ -9,9 +9,9 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- * from: Utah $Hdr: vn.c 1.1 91/04/30$
+ * from: Utah $Hdr: vn.c 1.13 94/04/02$
  *
  *
- *     @(#)vn.c        7.5 (Berkeley) %G%
+ *     @(#)vn.c        8.6 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  * 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).
  * 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).
+ *
+ * NOTE 3: Doesn't interact with leases, should it?
  */
 #include "vn.h"
 #if NVN > 0
 
  */
 #include "vn.h"
 #if NVN > 0
 
-#include "sys/param.h"
-#include "sys/systm.h"
-#include "sys/namei.h"
-#include "sys/proc.h"
-#include "sys/errno.h"
-#include "sys/dkstat.h"
-#include "sys/buf.h"
-#include "sys/malloc.h"
-#include "sys/ioctl.h"
-#include "sys/mount.h"
-#include "sys/vnode.h"
-#include "sys/specdev.h"
-#include "sys/file.h"
-#include "sys/uio.h"
-
-#include "vnioctl.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+
+#include <miscfs/specfs/specdev.h>
+
+#include <dev/vnioctl.h>
 
 #ifdef DEBUG
 
 #ifdef DEBUG
+int dovncluster = 1;
 int vndebug = 0x00;
 #define VDB_FOLLOW     0x01
 #define VDB_INIT       0x02
 #define VDB_IO         0x04
 #endif
 
 int vndebug = 0x00;
 #define VDB_FOLLOW     0x01
 #define VDB_INIT       0x02
 #define VDB_IO         0x04
 #endif
 
-struct buf vnbuf[NVN];
-struct buf vntab[NVN];
-
 #define b_cylin        b_resid
 
 #define        vnunit(x)       ((minor(x) >> 3) & 0x7) /* for consistency */
 #define b_cylin        b_resid
 
 #define        vnunit(x)       ((minor(x) >> 3) & 0x7) /* for consistency */
@@ -75,12 +76,41 @@ struct vn_softc {
        struct vnode    *sc_vp;         /* vnode */
        struct ucred    *sc_cred;       /* credentials */
        int              sc_maxactive;  /* max # of active requests */
        struct vnode    *sc_vp;         /* vnode */
        struct ucred    *sc_cred;       /* credentials */
        int              sc_maxactive;  /* max # of active requests */
-} vn_softc[NVN];
+       struct buf       sc_tab;        /* transfer queue */
+};
 
 /* sc_flags */
 #define        VNF_ALIVE       0x01
 #define VNF_INITED     0x02
 
 
 /* sc_flags */
 #define        VNF_ALIVE       0x01
 #define VNF_INITED     0x02
 
+#if 0  /* if you need static allocation */
+struct vn_softc vn_softc[NVN];
+int numvnd = NVN;
+#else
+struct vn_softc *vn_softc;
+int numvnd;
+#endif
+
+void
+vnattach(num)
+       int num;
+{
+       char *mem;
+       register u_long size;
+
+       if (num <= 0)
+               return;
+       size = num * sizeof(struct vn_softc);
+       mem = malloc(size, M_DEVBUF, M_NOWAIT);
+       if (mem == NULL) {
+               printf("WARNING: no memory for vnode disks\n");
+               return;
+       }
+       bzero(mem, size);
+       vn_softc = (struct vn_softc *)mem;
+       numvnd = num;
+}
+
 int
 vnopen(dev, flags, mode, p)
        dev_t dev;
 int
 vnopen(dev, flags, mode, p)
        dev_t dev;
@@ -93,7 +123,7 @@ vnopen(dev, flags, mode, p)
        if (vndebug & VDB_FOLLOW)
                printf("vnopen(%x, %x, %x, %x)\n", dev, flags, mode, p);
 #endif
        if (vndebug & VDB_FOLLOW)
                printf("vnopen(%x, %x, %x, %x)\n", dev, flags, mode, p);
 #endif
-       if (unit >= NVN)
+       if (unit >= numvnd)
                return(ENXIO);
        return(0);
 }
                return(ENXIO);
        return(0);
 }
@@ -111,8 +141,8 @@ vnstrategy(bp)
        register struct buf *nbp;
        register int bn, bsize, resid;
        register caddr_t addr;
        register struct buf *nbp;
        register int bn, bsize, resid;
        register caddr_t addr;
-       int sz, flags;
-       extern int vniodone();
+       int sz, flags, error;
+       extern void vniodone();
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
@@ -136,23 +166,36 @@ vnstrategy(bp)
                return;
        }
        bn = dbtob(bn);
                return;
        }
        bn = dbtob(bn);
-       bsize = vn->sc_vp->v_mount->mnt_stat.f_bsize;
-       addr = bp->b_un.b_addr;
+       bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
+       addr = bp->b_data;
        flags = bp->b_flags | B_CALL;
        for (resid = bp->b_resid; resid; resid -= sz) {
                struct vnode *vp;
                daddr_t nbn;
        flags = bp->b_flags | B_CALL;
        for (resid = bp->b_resid; resid; resid -= sz) {
                struct vnode *vp;
                daddr_t nbn;
-               int off, s;
+               int off, s, nra;
 
 
-               nbp = getvnbuf();
-               off = bn % bsize;
-               sz = MIN(bsize - off, resid);
-               (void) VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn);
+               nra = 0;
+               error = VOP_BMAP(vn->sc_vp, bn / bsize, &vp, &nbn, &nra);
+               if (error == 0 && (long)nbn == -1)
+                       error = EIO;
+#ifdef DEBUG
+               if (!dovncluster)
+                       nra = 0;
+#endif
+
+               if (off = bn % bsize)
+                       sz = bsize - off;
+               else
+                       sz = (1 + nra) * bsize;
+               if (resid < sz)
+                       sz = resid;
 #ifdef DEBUG
                if (vndebug & VDB_IO)
 #ifdef DEBUG
                if (vndebug & VDB_IO)
-                       printf("vnstrategy: vp %x/%x bn %x/%x\n",
-                              vn->sc_vp, vp, bn, nbn);
+                       printf("vnstrategy: vp %x/%x bn %x/%x sz %x\n",
+                              vn->sc_vp, vp, bn, nbn, sz);
 #endif
 #endif
+
+               nbp = getvnbuf();
                nbp->b_flags = flags;
                nbp->b_bcount = sz;
                nbp->b_bufsize = bp->b_bufsize;
                nbp->b_flags = flags;
                nbp->b_bcount = sz;
                nbp->b_bufsize = bp->b_bufsize;
@@ -161,21 +204,43 @@ vnstrategy(bp)
                        nbp->b_dev = vp->v_rdev;
                else
                        nbp->b_dev = NODEV;
                        nbp->b_dev = vp->v_rdev;
                else
                        nbp->b_dev = NODEV;
-               nbp->b_un.b_addr = addr;
+               nbp->b_data = addr;
                nbp->b_blkno = nbn + btodb(off);
                nbp->b_proc = bp->b_proc;
                nbp->b_iodone = vniodone;
                nbp->b_vp = vp;
                nbp->b_pfcent = (int) bp;       /* XXX */
                nbp->b_blkno = nbn + btodb(off);
                nbp->b_proc = bp->b_proc;
                nbp->b_iodone = vniodone;
                nbp->b_vp = vp;
                nbp->b_pfcent = (int) bp;       /* XXX */
+               nbp->b_rcred = vn->sc_cred;     /* XXX crdup? */
+               nbp->b_wcred = vn->sc_cred;     /* XXX crdup? */
+               nbp->b_dirtyoff = bp->b_dirtyoff;
+               nbp->b_dirtyend = bp->b_dirtyend;
+               nbp->b_validoff = bp->b_validoff;
+               nbp->b_validend = bp->b_validend;
+               /*
+                * If there was an error or a hole in the file...punt.
+                * Note that we deal with this after the nbp allocation.
+                * This ensures that we properly clean up any operations
+                * that we have already fired off.
+                *
+                * XXX we could deal with holes here but it would be
+                * a hassle (in the write case).
+                */
+               if (error) {
+                       nbp->b_error = error;
+                       nbp->b_flags |= B_ERROR;
+                       bp->b_resid -= (resid - sz);
+                       biodone(nbp);
+                       return;
+               }
                /*
                 * Just sort by block number
                 */
                nbp->b_cylin = nbp->b_blkno;
                s = splbio();
                /*
                 * Just sort by block number
                 */
                nbp->b_cylin = nbp->b_blkno;
                s = splbio();
-               disksort(&vntab[unit], nbp);
-               if (vntab[unit].b_active < vn->sc_maxactive) {
-                       vntab[unit].b_active++;
-                       vnstart(unit);
+               disksort(&vn->sc_tab, nbp);
+               if (vn->sc_tab.b_active < vn->sc_maxactive) {
+                       vn->sc_tab.b_active++;
+                       vnstart(vn);
                }
                splx(s);
                bn += sz;
                }
                splx(s);
                bn += sz;
@@ -189,38 +254,41 @@ vnstrategy(bp)
  * to an NFS file.  This places the burden on the client rather than the
  * server.
  */
  * to an NFS file.  This places the burden on the client rather than the
  * server.
  */
-vnstart(unit)
+vnstart(vn)
+       register struct vn_softc *vn;
 {
 {
-       register struct vn_softc *vn = &vn_softc[unit];
        register struct buf *bp;
 
        /*
         * Dequeue now since lower level strategy routine might
         * queue using same links
         */
        register struct buf *bp;
 
        /*
         * Dequeue now since lower level strategy routine might
         * queue using same links
         */
-       bp = vntab[unit].b_actf;
-       vntab[unit].b_actf = bp->b_actf;
+       bp = vn->sc_tab.b_actf;
+       vn->sc_tab.b_actf = bp->b_actf;
 #ifdef DEBUG
        if (vndebug & VDB_IO)
                printf("vnstart(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
 #ifdef DEBUG
        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,
+                      vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
                       bp->b_bcount);
 #endif
                       bp->b_bcount);
 #endif
+       if ((bp->b_flags & B_READ) == 0)
+               bp->b_vp->v_numoutput++;
        VOP_STRATEGY(bp);
 }
 
        VOP_STRATEGY(bp);
 }
 
+void
 vniodone(bp)
        register struct buf *bp;
 {
        register struct buf *pbp = (struct buf *)bp->b_pfcent;  /* XXX */
 vniodone(bp)
        register struct buf *bp;
 {
        register struct buf *pbp = (struct buf *)bp->b_pfcent;  /* XXX */
-       register int unit = vnunit(pbp->b_dev);
+       register struct vn_softc *vn = &vn_softc[vnunit(pbp->b_dev)];
        int s;
 
        s = splbio();
 #ifdef DEBUG
        if (vndebug & VDB_IO)
                printf("vniodone(%d): bp %x vp %x blkno %x addr %x cnt %x\n",
        int s;
 
        s = splbio();
 #ifdef DEBUG
        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,
+                      vn-vn_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
                       bp->b_bcount);
 #endif
        if (bp->b_error) {
                       bp->b_bcount);
 #endif
        if (bp->b_error) {
@@ -240,10 +308,10 @@ vniodone(bp)
 #endif
                biodone(pbp);
        }
 #endif
                biodone(pbp);
        }
-       if (vntab[unit].b_actf)
-               vnstart(unit);
+       if (vn->sc_tab.b_actf)
+               vnstart(vn);
        else
        else
-               vntab[unit].b_active--;
+               vn->sc_tab.b_active--;
        splx(s);
 }
 
        splx(s);
 }
 
@@ -253,13 +321,12 @@ vnread(dev, uio, flags, p)
        int flags;
        struct proc *p;
 {
        int flags;
        struct proc *p;
 {
-       register int unit = vnunit(dev);
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
                printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p);
 #endif
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
                printf("vnread(%x, %x, %x, %x)\n", dev, uio, flags, p);
 #endif
-       return(physio(vnstrategy, &vnbuf[unit], dev, B_READ, minphys, uio));
+       return(physio(vnstrategy, NULL, dev, B_READ, minphys, uio));
 }
 
 vnwrite(dev, uio, flags, p)
 }
 
 vnwrite(dev, uio, flags, p)
@@ -268,13 +335,12 @@ vnwrite(dev, uio, flags, p)
        int flags;
        struct proc *p;
 {
        int flags;
        struct proc *p;
 {
-       register int unit = vnunit(dev);
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
                printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p);
 #endif
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
                printf("vnwrite(%x, %x, %x, %x)\n", dev, uio, flags, p);
 #endif
-       return(physio(vnstrategy, &vnbuf[unit], dev, B_WRITE, minphys, uio));
+       return(physio(vnstrategy, NULL, dev, B_WRITE, minphys, uio));
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -300,7 +366,7 @@ vnioctl(dev, cmd, data, flag, p)
        error = suser(p->p_ucred, &p->p_acflag);
        if (error)
                return (error);
        error = suser(p->p_ucred, &p->p_acflag);
        if (error)
                return (error);
-       if (unit >= NVN)
+       if (unit >= numvnd)
                return (ENXIO);
 
        vn = &vn_softc[unit];
                return (ENXIO);
 
        vn = &vn_softc[unit];
@@ -316,21 +382,19 @@ vnioctl(dev, cmd, data, flag, p)
                 * weed out directories, sockets, etc. so we don't
                 * have to worry about them.
                 */
                 * weed out directories, sockets, etc. so we don't
                 * have to worry about them.
                 */
-               nd.ni_segflg = UIO_USERSPACE;
-               nd.ni_dirp = vio->vn_file;
-               error = vn_open(&nd, p, FREAD|FWRITE, 0);
-               if (error)
+               NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vn_file, p);
+               if (error = vn_open(&nd, FREAD|FWRITE, 0))
                        return(error);
                        return(error);
-               error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
-               if (error) {
-                       vrele(nd.ni_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);
                }
                        return(error);
                }
+               VOP_UNLOCK(nd.ni_vp);
                vn->sc_vp = nd.ni_vp;
                vn->sc_size = btodb(vattr.va_size);     /* note truncation */
                vn->sc_vp = nd.ni_vp;
                vn->sc_size = btodb(vattr.va_size);     /* note truncation */
-               error = vnsetcred(vn, p->p_ucred);
-               if (error) {
-                       vrele(vn->sc_vp);
+               if (error = vnsetcred(vn, p->p_ucred)) {
+                       (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
                        return(error);
                }
                vnthrottle(vn, vn->sc_vp);
                        return(error);
                }
                vnthrottle(vn, vn->sc_vp);
@@ -367,23 +431,29 @@ vnioctl(dev, cmd, data, flag, p)
  */
 vnsetcred(vn, cred)
        register struct vn_softc *vn;
  */
 vnsetcred(vn, cred)
        register struct vn_softc *vn;
-       struct ucred cred;
+       struct ucred *cred;
 {
        struct uio auio;
        struct iovec aiov;
 {
        struct uio auio;
        struct iovec aiov;
-       char tmpbuf[DEV_BSIZE];
+       char *tmpbuf;
+       int error;
 
        vn->sc_cred = crdup(cred);
 
        vn->sc_cred = crdup(cred);
+       tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
+
        /* XXX: Horrible kludge to establish credentials for NFS */
        aiov.iov_base = tmpbuf;
        /* XXX: Horrible kludge to establish credentials for NFS */
        aiov.iov_base = tmpbuf;
-       aiov.iov_len = MIN(DEV_BSIZE, dbtob(vn->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;
        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(vn->sc_vp, &auio, 0, vn->sc_cred));
+       error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
+
+       free(tmpbuf, M_TEMP);
+       return (error);
 }
 
 /*
 }
 
 /*
@@ -393,9 +463,9 @@ vnthrottle(vn, vp)
        register struct vn_softc *vn;
        struct vnode *vp;
 {
        register struct vn_softc *vn;
        struct vnode *vp;
 {
-       extern struct vnodeops ufs_vnodeops, nfsv2_vnodeops;
+       extern int (**nfsv2_vnodeop_p)();
 
 
-       if (vp->v_op == &nfsv2_vnodeops)
+       if (vp->v_op == nfsv2_vnodeop_p)
                vn->sc_maxactive = 2;
        else
                vn->sc_maxactive = 8;
                vn->sc_maxactive = 2;
        else
                vn->sc_maxactive = 8;
@@ -408,7 +478,7 @@ vnshutdown()
 {
        register struct vn_softc *vn;
 
 {
        register struct vn_softc *vn;
 
-       for (vn = &vn_softc[0]; vn < &vn_softc[NVN]; vn++)
+       for (vn = &vn_softc[0]; vn < &vn_softc[numvnd]; vn++)
                if (vn->sc_flags & VNF_INITED)
                        vnclear(vn);
 }
                if (vn->sc_flags & VNF_INITED)
                        vnclear(vn);
 }
@@ -417,6 +487,7 @@ vnclear(vn)
        register struct vn_softc *vn;
 {
        register struct vnode *vp = vn->sc_vp;
        register struct vn_softc *vn;
 {
        register struct vnode *vp = vn->sc_vp;
+       struct proc *p = curproc;               /* XXX */
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
 
 #ifdef DEBUG
        if (vndebug & VDB_FOLLOW)
@@ -425,11 +496,7 @@ vnclear(vn)
        vn->sc_flags &= ~VNF_INITED;
        if (vp == (struct vnode *)0)
                panic("vnioctl: null vp");
        vn->sc_flags &= ~VNF_INITED;
        if (vp == (struct vnode *)0)
                panic("vnioctl: null vp");
-#if 0
-       /* XXX - this doesn't work right now */
-       (void) VOP_FSYNC(vp, 0, vn->sc_cred, MNT_WAIT, p);
-#endif
-       vrele(vp);
+       (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;
        crfree(vn->sc_cred);
        vn->sc_vp = (struct vnode *)0;
        vn->sc_cred = (struct ucred *)0;
@@ -442,7 +509,7 @@ vnsize(dev)
        int unit = vnunit(dev);
        register struct vn_softc *vn = &vn_softc[unit];
 
        int unit = vnunit(dev);
        register struct vn_softc *vn = &vn_softc[unit];
 
-       if (unit >= NVN || (vn->sc_flags & VNF_INITED) == 0)
+       if (unit >= numvnd || (vn->sc_flags & VNF_INITED) == 0)
                return(-1);
        return(vn->sc_size);
 }
                return(-1);
        return(vn->sc_size);
 }