BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / spec_vnops.c
index b397f19..ba7dee7 100644 (file)
@@ -2,31 +2,45 @@
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1989 The Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement:  This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software.  Neither the name of the University nor the names of
- * its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)spec_vnops.c        7.28 (Berkeley) 6/28/90
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)spec_vnops.c        7.37 (Berkeley) 5/30/91
  */
 
 #include "param.h"
  */
 
 #include "param.h"
+#include "proc.h"
 #include "systm.h"
 #include "systm.h"
-#include "user.h"
 #include "kernel.h"
 #include "conf.h"
 #include "buf.h"
 #include "mount.h"
 #include "kernel.h"
 #include "conf.h"
 #include "buf.h"
 #include "mount.h"
+#include "namei.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "stat.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "stat.h"
@@ -44,63 +58,49 @@ char        devout[] = "devout";
 char   devioc[] = "devioc";
 char   devcls[] = "devcls";
 
 char   devioc[] = "devioc";
 char   devcls[] = "devcls";
 
-int    spec_lookup(),
-       spec_open(),
-       spec_read(),
-       spec_write(),
-       spec_strategy(),
-       spec_bmap(),
-       spec_ioctl(),
-       spec_select(),
-       spec_lock(),
-       spec_unlock(),
-       spec_close(),
-       spec_print(),
-       spec_ebadf(),
-       spec_badop(),
-       spec_nullop();
-
 struct vnodeops spec_vnodeops = {
        spec_lookup,            /* lookup */
 struct vnodeops spec_vnodeops = {
        spec_lookup,            /* lookup */
-       spec_badop,             /* create */
-       spec_badop,             /* mknod */
+       spec_create,            /* create */
+       spec_mknod,             /* mknod */
        spec_open,              /* open */
        spec_close,             /* close */
        spec_open,              /* open */
        spec_close,             /* close */
-       spec_ebadf,             /* access */
-       spec_ebadf,             /* getattr */
-       spec_ebadf,             /* setattr */
+       spec_access,            /* access */
+       spec_getattr,           /* getattr */
+       spec_setattr,           /* setattr */
        spec_read,              /* read */
        spec_write,             /* write */
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
        spec_read,              /* read */
        spec_write,             /* write */
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
-       spec_badop,             /* mmap */
-       spec_nullop,            /* fsync */
-       spec_badop,             /* seek */
-       spec_badop,             /* remove */
-       spec_badop,             /* link */
-       spec_badop,             /* rename */
-       spec_badop,             /* mkdir */
-       spec_badop,             /* rmdir */
-       spec_badop,             /* symlink */
-       spec_badop,             /* readdir */
-       spec_badop,             /* readlink */
-       spec_badop,             /* abortop */
-       spec_nullop,            /* inactive */
-       spec_nullop,            /* reclaim */
+       spec_mmap,              /* mmap */
+       spec_fsync,             /* fsync */
+       spec_seek,              /* seek */
+       spec_remove,            /* remove */
+       spec_link,              /* link */
+       spec_rename,            /* rename */
+       spec_mkdir,             /* mkdir */
+       spec_rmdir,             /* rmdir */
+       spec_symlink,           /* symlink */
+       spec_readdir,           /* readdir */
+       spec_readlink,          /* readlink */
+       spec_abortop,           /* abortop */
+       spec_inactive,          /* inactive */
+       spec_reclaim,           /* reclaim */
        spec_lock,              /* lock */
        spec_unlock,            /* unlock */
        spec_bmap,              /* bmap */
        spec_strategy,          /* strategy */
        spec_print,             /* print */
        spec_lock,              /* lock */
        spec_unlock,            /* unlock */
        spec_bmap,              /* bmap */
        spec_strategy,          /* strategy */
        spec_print,             /* print */
-       spec_nullop,            /* islocked */
+       spec_islocked,          /* islocked */
+       spec_advlock,           /* advlock */
 };
 
 /*
  * Trivial lookup routine that always fails.
  */
 };
 
 /*
  * Trivial lookup routine that always fails.
  */
-spec_lookup(vp, ndp)
+spec_lookup(vp, ndp, p)
        struct vnode *vp;
        struct nameidata *ndp;
        struct vnode *vp;
        struct nameidata *ndp;
+       struct proc *p;
 {
 
        ndp->ni_dvp = vp;
 {
 
        ndp->ni_dvp = vp;
@@ -109,15 +109,16 @@ spec_lookup(vp, ndp)
 }
 
 /*
 }
 
 /*
- * Open called to allow handler
- * of special files to initialize and
- * validate before actual IO.
+ * Open a special file: Don't allow open if fs is mounted -nodev,
+ * and don't allow opens of block devices that are currently mounted.
+ * Otherwise, call device driver open function.
  */
 /* ARGSUSED */
  */
 /* ARGSUSED */
-spec_open(vp, mode, cred)
+spec_open(vp, mode, cred, p)
        register struct vnode *vp;
        int mode;
        struct ucred *cred;
        register struct vnode *vp;
        int mode;
        struct ucred *cred;
+       struct proc *p;
 {
        dev_t dev = (dev_t)vp->v_rdev;
        register int maj = major(dev);
 {
        dev_t dev = (dev_t)vp->v_rdev;
        register int maj = major(dev);
@@ -131,14 +132,17 @@ spec_open(vp, mode, cred)
        case VCHR:
                if ((u_int)maj >= nchrdev)
                        return (ENXIO);
        case VCHR:
                if ((u_int)maj >= nchrdev)
                        return (ENXIO);
-               return ((*cdevsw[maj].d_open)(dev, mode, S_IFCHR));
+               VOP_UNLOCK(vp);
+               error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p);
+               VOP_LOCK(vp);
+               return (error);
 
        case VBLK:
                if ((u_int)maj >= nblkdev)
                        return (ENXIO);
                if (error = mountedon(vp))
                        return (error);
 
        case VBLK:
                if ((u_int)maj >= nblkdev)
                        return (ENXIO);
                if (error = mountedon(vp))
                        return (error);
-               return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK));
+               return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK, p));
        }
        return (0);
 }
        }
        return (0);
 }
@@ -153,6 +157,7 @@ spec_read(vp, uio, ioflag, cred)
        int ioflag;
        struct ucred *cred;
 {
        int ioflag;
        struct ucred *cred;
 {
+       struct proc *p = uio->uio_procp;
        struct buf *bp;
        daddr_t bn;
        long bsize, bscale;
        struct buf *bp;
        daddr_t bn;
        long bsize, bscale;
@@ -161,8 +166,12 @@ spec_read(vp, uio, ioflag, cred)
        int error = 0;
        extern int mem_no;
 
        int error = 0;
        extern int mem_no;
 
+#ifdef DIAGNOSTIC
        if (uio->uio_rw != UIO_READ)
                panic("spec_read mode");
        if (uio->uio_rw != UIO_READ)
                panic("spec_read mode");
+       if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
+               panic("spec_read proc");
+#endif
        if (uio->uio_resid == 0)
                return (0);
 
        if (uio->uio_resid == 0)
                return (0);
 
@@ -185,7 +194,7 @@ spec_read(vp, uio, ioflag, cred)
                        return (EINVAL);
                bsize = BLKDEV_IOSIZE;
                if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
                        return (EINVAL);
                bsize = BLKDEV_IOSIZE;
                if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
-                   (caddr_t)&dpart, FREAD) == 0) {
+                   (caddr_t)&dpart, FREAD, p) == 0) {
                        if (dpart.part->p_fstype == FS_BSDFFS &&
                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                                bsize = dpart.part->p_frag *
                        if (dpart.part->p_fstype == FS_BSDFFS &&
                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                                bsize = dpart.part->p_frag *
@@ -230,16 +239,21 @@ spec_write(vp, uio, ioflag, cred)
        int ioflag;
        struct ucred *cred;
 {
        int ioflag;
        struct ucred *cred;
 {
+       struct proc *p = uio->uio_procp;
        struct buf *bp;
        daddr_t bn;
        int bsize, blkmask;
        struct partinfo dpart;
        struct buf *bp;
        daddr_t bn;
        int bsize, blkmask;
        struct partinfo dpart;
-       register int n, on, i;
-       int count, error = 0;
+       register int n, on;
+       int error = 0;
        extern int mem_no;
 
        extern int mem_no;
 
+#ifdef DIAGNOSTIC
        if (uio->uio_rw != UIO_WRITE)
                panic("spec_write mode");
        if (uio->uio_rw != UIO_WRITE)
                panic("spec_write mode");
+       if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
+               panic("spec_write proc");
+#endif
 
        switch (vp->v_type) {
 
 
        switch (vp->v_type) {
 
@@ -262,7 +276,7 @@ spec_write(vp, uio, ioflag, cred)
                        return (EINVAL);
                bsize = BLKDEV_IOSIZE;
                if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
                        return (EINVAL);
                bsize = BLKDEV_IOSIZE;
                if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART,
-                   (caddr_t)&dpart, FREAD) == 0) {
+                   (caddr_t)&dpart, FREAD, p) == 0) {
                        if (dpart.part->p_fstype == FS_BSDFFS &&
                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                                bsize = dpart.part->p_frag *
                        if (dpart.part->p_fstype == FS_BSDFFS &&
                            dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
                                bsize = dpart.part->p_frag *
@@ -273,9 +287,6 @@ spec_write(vp, uio, ioflag, cred)
                        bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask;
                        on = uio->uio_offset % bsize;
                        n = MIN((unsigned)(bsize - on), uio->uio_resid);
                        bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask;
                        on = uio->uio_offset % bsize;
                        n = MIN((unsigned)(bsize - on), uio->uio_resid);
-                       count = howmany(bsize, CLBYTES);
-                       for (i = 0; i < count; i++)
-                               munhash(vp, bn + i * (CLBYTES / DEV_BSIZE));
                        if (n == bsize)
                                bp = getblk(vp, bn, bsize);
                        else
                        if (n == bsize)
                                bp = getblk(vp, bn, bsize);
                        else
@@ -304,19 +315,21 @@ spec_write(vp, uio, ioflag, cred)
  * Device ioctl operation.
  */
 /* ARGSUSED */
  * Device ioctl operation.
  */
 /* ARGSUSED */
-spec_ioctl(vp, com, data, fflag, cred)
+spec_ioctl(vp, com, data, fflag, cred, p)
        struct vnode *vp;
        int com;
        caddr_t data;
        int fflag;
        struct ucred *cred;
        struct vnode *vp;
        int com;
        caddr_t data;
        int fflag;
        struct ucred *cred;
+       struct proc *p;
 {
        dev_t dev = vp->v_rdev;
 
        switch (vp->v_type) {
 
        case VCHR:
 {
        dev_t dev = vp->v_rdev;
 
        switch (vp->v_type) {
 
        case VCHR:
-               return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data, fflag));
+               return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data,
+                   fflag, p));
 
        case VBLK:
                if (com == 0 && (int)data == B_TAPE)
 
        case VBLK:
                if (com == 0 && (int)data == B_TAPE)
@@ -324,7 +337,8 @@ spec_ioctl(vp, com, data, fflag, cred)
                                return (0);
                        else
                                return (1);
                                return (0);
                        else
                                return (1);
-               return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data, fflag));
+               return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data,
+                  fflag, p));
 
        default:
                panic("spec_ioctl");
 
        default:
                panic("spec_ioctl");
@@ -333,10 +347,11 @@ spec_ioctl(vp, com, data, fflag, cred)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
-spec_select(vp, which, fflags, cred)
+spec_select(vp, which, fflags, cred, p)
        struct vnode *vp;
        int which, fflags;
        struct ucred *cred;
        struct vnode *vp;
        int which, fflags;
        struct ucred *cred;
+       struct proc *p;
 {
        register dev_t dev;
 
 {
        register dev_t dev;
 
@@ -347,7 +362,7 @@ spec_select(vp, which, fflags, cred)
 
        case VCHR:
                dev = vp->v_rdev;
 
        case VCHR:
                dev = vp->v_rdev;
-               return (*cdevsw[major(dev)].d_select)(dev, which);
+               return (*cdevsw[major(dev)].d_select)(dev, which, p);
        }
 }
 
        }
 }
 
@@ -402,13 +417,14 @@ spec_unlock(vp)
  * Device close routine
  */
 /* ARGSUSED */
  * Device close routine
  */
 /* ARGSUSED */
-spec_close(vp, flag, cred)
+spec_close(vp, flag, cred, p)
        register struct vnode *vp;
        int flag;
        struct ucred *cred;
        register struct vnode *vp;
        int flag;
        struct ucred *cred;
+       struct proc *p;
 {
        dev_t dev = vp->v_rdev;
 {
        dev_t dev = vp->v_rdev;
-       int (*cfunc)();
+       int (*devclose) __P((dev_t, int, int, struct proc *));
        int mode;
 
        switch (vp->v_type) {
        int mode;
 
        switch (vp->v_type) {
@@ -421,7 +437,7 @@ spec_close(vp, flag, cred)
                 */
                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
                        return (0);
                 */
                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
                        return (0);
-               cfunc = cdevsw[major(dev)].d_close;
+               devclose = cdevsw[major(dev)].d_close;
                mode = S_IFCHR;
                break;
 
                mode = S_IFCHR;
                break;
 
@@ -445,7 +461,7 @@ spec_close(vp, flag, cred)
                 */
                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
                        return (0);
                 */
                if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
                        return (0);
-               cfunc = bdevsw[major(dev)].d_close;
+               devclose = bdevsw[major(dev)].d_close;
                mode = S_IFBLK;
                break;
 
                mode = S_IFBLK;
                break;
 
@@ -453,7 +469,7 @@ spec_close(vp, flag, cred)
                panic("spec_close: not special");
        }
 
                panic("spec_close: not special");
        }
 
-       return ((*cfunc)(dev, flag, mode));
+       return ((*devclose)(dev, flag, mode, p));
 }
 
 /*
 }
 
 /*
@@ -467,6 +483,21 @@ spec_print(vp)
                minor(vp->v_rdev));
 }
 
                minor(vp->v_rdev));
 }
 
+/*
+ * Special device advisory byte-level locks.
+ */
+/* ARGSUSED */
+spec_advlock(vp, id, op, fl, flags)
+       struct vnode *vp;
+       caddr_t id;
+       int op;
+       struct flock *fl;
+       int flags;
+{
+
+       return (EOPNOTSUPP);
+}
+
 /*
  * Special device failed operation
  */
 /*
  * Special device failed operation
  */
@@ -485,12 +516,3 @@ spec_badop()
        panic("spec_badop called");
        /* NOTREACHED */
 }
        panic("spec_badop called");
        /* NOTREACHED */
 }
-
-/*
- * Special device null operation
- */
-spec_nullop()
-{
-
-       return (0);
-}