strategy returns void, ioctl cmd is u_long
[unix-history] / usr / src / sys / dev / vn.c
index b1f1655..6e1e073 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: fd.c 1.3 89/12/03$
+ * from: Utah $Hdr: vn.c 1.13 94/04/02$
  *
  *
- *     @(#)vn.c        7.14 (Berkeley) %G%
+ *     @(#)vn.c        8.8 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -29,6 +29,8 @@
  * 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 <dev/vnioctl.h>
 
 #ifdef DEBUG
 #include <dev/vnioctl.h>
 
 #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 */
@@ -76,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;
@@ -94,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);
 }
@@ -104,6 +133,7 @@ vnopen(dev, flags, mode, p)
  * 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.
  */
  * 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.
  */
+void
 vnstrategy(bp)
        register struct buf *bp;
 {
 vnstrategy(bp)
        register struct buf *bp;
 {
@@ -112,7 +142,7 @@ 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;
+       int sz, flags, error;
        extern void vniodone();
 
 #ifdef DEBUG
        extern void vniodone();
 
 #ifdef DEBUG
@@ -138,22 +168,35 @@ vnstrategy(bp)
        }
        bn = dbtob(bn);
        bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
        }
        bn = dbtob(bn);
        bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
-       addr = bp->b_un.b_addr;
+       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, NULL);
+               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;
@@ -162,21 +205,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;
@@ -190,23 +255,25 @@ 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);
 }
 
@@ -215,14 +282,14 @@ vniodone(bp)
        register struct buf *bp;
 {
        register struct buf *pbp = (struct buf *)bp->b_pfcent;  /* XXX */
        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) {
@@ -242,10 +309,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);
 }
 
@@ -255,13 +322,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)
@@ -270,13 +336,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 */
@@ -302,7 +367,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];
@@ -330,7 +395,7 @@ vnioctl(dev, cmd, data, flag, p)
                vn->sc_vp = nd.ni_vp;
                vn->sc_size = btodb(vattr.va_size);     /* note truncation */
                if (error = vnsetcred(vn, p->p_ucred)) {
                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);
+                       (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);
@@ -354,7 +419,7 @@ vnioctl(dev, cmd, data, flag, p)
                break;
 
        default:
                break;
 
        default:
-               return(ENXIO);
+               return(ENOTTY);
        }
        return(0);
 }
        }
        return(0);
 }
@@ -367,13 +432,16 @@ 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;
        aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size));
        /* XXX: Horrible kludge to establish credentials for NFS */
        aiov.iov_base = tmpbuf;
        aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size));
@@ -383,7 +451,10 @@ vnsetcred(vn, cred)
        auio.uio_rw = UIO_READ;
        auio.uio_segflg = UIO_SYSSPACE;
        auio.uio_resid = aiov.iov_len;
        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,7 +464,6 @@ vnthrottle(vn, vp)
        register struct vn_softc *vn;
        struct vnode *vp;
 {
        register struct vn_softc *vn;
        struct vnode *vp;
 {
-       extern int (**ufs_vnodeop_p)();
        extern int (**nfsv2_vnodeop_p)();
 
        if (vp->v_op == nfsv2_vnodeop_p)
        extern int (**nfsv2_vnodeop_p)();
 
        if (vp->v_op == nfsv2_vnodeop_p)
@@ -409,7 +479,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);
 }
@@ -427,10 +497,6 @@ 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
        (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
        crfree(vn->sc_cred);
        vn->sc_vp = (struct vnode *)0;
        (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
        crfree(vn->sc_cred);
        vn->sc_vp = (struct vnode *)0;
@@ -444,7 +510,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);
 }