summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs/devfs_vnops.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-10-22 09:59:37 +0000
committerphk <phk@FreeBSD.org>2004-10-22 09:59:37 +0000
commit2c3e47b66843948385e7152055338c67f3c6a0a0 (patch)
tree0207c677739b9bf7fbf4c4f4bbb9f5a1d7e7bfb5 /sys/fs/devfs/devfs_vnops.c
parenteaf4c4162d48f9aad7b949a5f5e8da4bb026c18f (diff)
downloadFreeBSD-src-2c3e47b66843948385e7152055338c67f3c6a0a0.zip
FreeBSD-src-2c3e47b66843948385e7152055338c67f3c6a0a0.tar.gz
Alas, poor SPECFS! -- I knew him, Horatio; A filesystem of infinite
jest, of most excellent fancy: he hath taught me lessons a thousand times; and now, how abhorred in my imagination it is! my gorge rises at it. Here were those hacks that I have curs'd I know not how oft. Where be your kludges now? your workarounds? your layering violations, that were wont to set the table on a roar? Move the skeleton of specfs into devfs where it now belongs and bury the rest.
Diffstat (limited to 'sys/fs/devfs/devfs_vnops.c')
-rw-r--r--sys/fs/devfs/devfs_vnops.c577
1 files changed, 551 insertions, 26 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 08a7abe..ded05a9 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 2000
+ * Copyright (c) 2000-2004
* Poul-Henning Kamp. All rights reserved.
+ * Copyright (c) 1989, 1992-1993, 1995
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
@@ -46,8 +46,11 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/dirent.h>
+#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mac.h>
@@ -55,6 +58,9 @@
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
@@ -62,25 +68,36 @@
#include <fs/devfs/devfs.h>
static int devfs_access(struct vop_access_args *ap);
+static int devfs_advlock(struct vop_advlock_args *ap);
+static int devfs_close(struct vop_close_args *ap);
+static int devfs_fsync(struct vop_fsync_args *ap);
static int devfs_getattr(struct vop_getattr_args *ap);
static int devfs_ioctl(struct vop_ioctl_args *ap);
+static int devfs_kqfilter(struct vop_kqfilter_args *ap);
static int devfs_lookupx(struct vop_lookup_args *ap);
static int devfs_mknod(struct vop_mknod_args *ap);
+static int devfs_open(struct vop_open_args *ap);
static int devfs_pathconf(struct vop_pathconf_args *ap);
+static int devfs_poll(struct vop_poll_args *ap);
+static int devfs_print(struct vop_print_args *ap);
static int devfs_read(struct vop_read_args *ap);
static int devfs_readdir(struct vop_readdir_args *ap);
static int devfs_readlink(struct vop_readlink_args *ap);
static int devfs_reclaim(struct vop_reclaim_args *ap);
static int devfs_remove(struct vop_remove_args *ap);
static int devfs_revoke(struct vop_revoke_args *ap);
+static int devfs_rioctl(struct vop_ioctl_args *ap);
+static int devfs_rread(struct vop_read_args *ap);
static int devfs_setattr(struct vop_setattr_args *ap);
#ifdef MAC
static int devfs_setlabel(struct vop_setlabel_args *ap);
#endif
+static int devfs_specstrategy(struct vop_specstrategy_args *);
static int devfs_symlink(struct vop_symlink_args *ap);
+static int devfs_write(struct vop_write_args *ap);
static vop_t **devfs_vnodeop_p;
-static vop_t **devfs_specop_p;
+vop_t **devfs_specop_p;
/*
* Construct the fully qualified path name relative to the mountpoint
@@ -199,6 +216,127 @@ devfs_access(ap)
return (error);
}
+/*
+ * Special device advisory byte-level locks.
+ */
+/* ARGSUSED */
+static int
+devfs_advlock(ap)
+ struct vop_advlock_args /* {
+ struct vnode *a_vp;
+ caddr_t a_id;
+ int a_op;
+ struct flock *a_fl;
+ int a_flags;
+ } */ *ap;
+{
+
+ return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
+}
+
+/*
+ * Device close routine
+ */
+/* ARGSUSED */
+static int
+devfs_close(ap)
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp, *oldvp;
+ struct thread *td = ap->a_td;
+ struct cdev *dev = vp->v_rdev;
+ struct cdevsw *dsw;
+ int error;
+
+ /*
+ * Hack: a tty device that is a controlling terminal
+ * has a reference from the session structure.
+ * We cannot easily tell that a character device is
+ * a controlling terminal, unless it is the closing
+ * process' controlling terminal. In that case,
+ * if the reference count is 2 (this last descriptor
+ * plus the session), release the reference from the session.
+ */
+
+ /*
+ * This needs to be rewritten to take the vp interlock into
+ * consideration.
+ */
+
+ oldvp = NULL;
+ sx_xlock(&proctree_lock);
+ if (td && vp == td->td_proc->p_session->s_ttyvp) {
+ SESS_LOCK(td->td_proc->p_session);
+ VI_LOCK(vp);
+ if (count_dev(dev) == 2 && (vp->v_iflag & VI_XLOCK) == 0) {
+ td->td_proc->p_session->s_ttyvp = NULL;
+ oldvp = vp;
+ }
+ VI_UNLOCK(vp);
+ SESS_UNLOCK(td->td_proc->p_session);
+ }
+ sx_xunlock(&proctree_lock);
+ if (oldvp != NULL)
+ vrele(oldvp);
+ /*
+ * We do not want to really close the device if it
+ * is still in use unless we are trying to close it
+ * forcibly. Since every use (buffer, vnode, swap, cmap)
+ * holds a reference to the vnode, and because we mark
+ * any other vnodes that alias this device, when the
+ * sum of the reference counts on all the aliased
+ * vnodes descends to one, we are on last close.
+ */
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return (ENXIO);
+ VI_LOCK(vp);
+ if (vp->v_iflag & VI_XLOCK) {
+ /* Forced close. */
+ } else if (dsw->d_flags & D_TRACKCLOSE) {
+ /* Keep device updated on status. */
+ } else if (count_dev(dev) > 1) {
+ VI_UNLOCK(vp);
+ dev_relthread(dev);
+ return (0);
+ }
+ VI_UNLOCK(vp);
+ KASSERT(dev->si_refcount > 0,
+ ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev)));
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
+ PICKUP_GIANT();
+ } else
+ error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
+ dev_relthread(dev);
+ return (error);
+}
+
+/*
+ * Synch buffers associated with a block device
+ */
+/* ARGSUSED */
+static int
+devfs_fsync(ap)
+ struct vop_fsync_args /* {
+ struct vnode *a_vp;
+ struct ucred *a_cred;
+ int a_waitfor;
+ struct thread *a_td;
+ } */ *ap;
+{
+ if (!vn_isdisk(ap->a_vp, NULL))
+ return (0);
+
+ return (vop_stdfsync(ap));
+}
+
static int
devfs_getattr(ap)
struct vop_getattr_args /* {
@@ -266,6 +404,10 @@ devfs_getattr(ap)
return (error);
}
+/*
+ * Device ioctl operation.
+ */
+/* ARGSUSED */
static int
devfs_ioctl(ap)
struct vop_ioctl_args /* {
@@ -277,15 +419,55 @@ devfs_ioctl(ap)
struct thread *a_td;
} */ *ap;
{
+ struct cdev *dev;
int error;
- struct devfs_mount *dmp;
+ struct cdevsw *dsw;
+
+ dev = ap->a_vp->v_rdev;
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return (ENXIO);
+ KASSERT(dev->si_refcount > 0,
+ ("devfs_ioctl() on un-referenced struct cdev *(%s)", devtoname(dev)));
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ error = dsw->d_ioctl(dev, ap->a_command,
+ ap->a_data, ap->a_fflag, ap->a_td);
+ PICKUP_GIANT();
+ } else
+ error = dsw->d_ioctl(dev, ap->a_command,
+ ap->a_data, ap->a_fflag, ap->a_td);
+ dev_relthread(dev);
+ if (error == ENOIOCTL)
+ error = ENOTTY;
+ return (error);
+}
- dmp = VFSTODEVFS(ap->a_vp->v_mount);
- lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
- devfs_populate(dmp);
- lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
- error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data,
- ap->a_td);
+/* ARGSUSED */
+static int
+devfs_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
+{
+ struct cdev *dev;
+ struct cdevsw *dsw;
+ int error;
+
+ dev = ap->a_vp->v_rdev;
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return(0);
+ KASSERT(dev->si_refcount > 0,
+ ("devfs_kqfilter() on un-referenced struct cdev *(%s)", devtoname(dev)));
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ error = dsw->d_kqfilter(dev, ap->a_kn);
+ PICKUP_GIANT();
+ } else
+ error = dsw->d_kqfilter(dev, ap->a_kn);
+ dev_relthread(dev);
return (error);
}
@@ -458,15 +640,14 @@ devfs_lookup(struct vop_lookup_args *ap)
static int
devfs_mknod(struct vop_mknod_args *ap)
-/*
-struct vop_mknod_args {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-*/
+ /*
+ struct vop_mknod_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+ struct vattr *a_vap;
+ }; */
{
struct componentname *cnp;
struct vnode *dvp, **vpp;
@@ -504,6 +685,107 @@ notfound:
return (error);
}
+/*
+ * Open a special file.
+ */
+/* ARGSUSED */
+static int
+devfs_open(ap)
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct thread *td = ap->a_td;
+ struct vnode *vp = ap->a_vp;
+ struct cdev *dev = vp->v_rdev;
+ int error;
+ struct cdevsw *dsw;
+
+ if (vp->v_type == VBLK)
+ return (ENXIO);
+
+ /* Don't allow open if fs is mounted -nodev. */
+ if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
+ return (ENXIO);
+
+ if (dev == NULL)
+ return (ENXIO);
+
+ /* Make this field valid before any I/O in d_open. */
+ if (dev->si_iosize_max == 0)
+ dev->si_iosize_max = DFLTPHYS;
+
+ /*
+ * XXX: Disks get special billing here, but it is mostly wrong.
+ * XXX: Disk partitions can overlap and the real checks should
+ * XXX: take this into account, and consequently they need to
+ * XXX: live in the disk slice code. Some checks do.
+ */
+ if (vn_isdisk(vp, NULL) && ap->a_cred != FSCRED &&
+ (ap->a_mode & FWRITE)) {
+ /*
+ * Never allow opens for write if the disk is mounted R/W.
+ */
+ if (vp->v_rdev->si_mountpoint != NULL &&
+ !(vp->v_rdev->si_mountpoint->mnt_flag & MNT_RDONLY))
+ return (EBUSY);
+
+ /*
+ * When running in secure mode, do not allow opens
+ * for writing if the disk is mounted.
+ */
+ error = securelevel_ge(td->td_ucred, 1);
+ if (error && vfs_mountedon(vp))
+ return (error);
+
+ /*
+ * When running in very secure mode, do not allow
+ * opens for writing of any disks.
+ */
+ error = securelevel_ge(td->td_ucred, 2);
+ if (error)
+ return (error);
+ }
+
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return (ENXIO);
+
+ /* XXX: Special casing of ttys for deadfs. Probably redundant. */
+ if (dsw->d_flags & D_TTY)
+ vp->v_vflag |= VV_ISTTY;
+
+ VOP_UNLOCK(vp, 0, td);
+
+ if(!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ if (dsw->d_fdopen != NULL)
+ error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
+ else
+ error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
+ PICKUP_GIANT();
+ } else if (dsw->d_fdopen != NULL)
+ error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx);
+ else
+ error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+
+ dev_relthread(dev);
+
+ if (error)
+ return (error);
+
+ if (vn_isdisk(vp, NULL)) {
+ if (!dev->si_bsize_phys)
+ dev->si_bsize_phys = DEV_BSIZE;
+ }
+ return (error);
+}
+
static int
devfs_pathconf(ap)
@@ -538,6 +820,54 @@ devfs_pathconf(ap)
/* NOTREACHED */
}
+/* ARGSUSED */
+static int
+devfs_poll(ap)
+ struct vop_poll_args /* {
+ struct vnode *a_vp;
+ int a_events;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct cdev *dev;
+ struct cdevsw *dsw;
+ int error;
+
+ dev = ap->a_vp->v_rdev;
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return(0);
+ KASSERT(dev->si_refcount > 0,
+ ("devfs_poll() on un-referenced struct cdev *(%s)", devtoname(dev)));
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ /* XXX: not yet DROP_GIANT(); */
+ error = dsw->d_poll(dev, ap->a_events, ap->a_td);
+ /* XXX: not yet PICKUP_GIANT(); */
+ } else
+ error = dsw->d_poll(dev, ap->a_events, ap->a_td);
+ dev_relthread(dev);
+ return(error);
+}
+
+/*
+ * Print out the contents of a special device vnode.
+ */
+static int
+devfs_print(ap)
+ struct vop_print_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+
+ printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev));
+ return (0);
+}
+
+/*
+ * Vnode op for read
+ */
+/* ARGSUSED */
static int
devfs_read(ap)
struct vop_read_args /* {
@@ -547,10 +877,39 @@ devfs_read(ap)
struct ucred *a_cred;
} */ *ap;
{
+ struct vnode *vp;
+ struct thread *td;
+ struct uio *uio;
+ struct cdev *dev;
+ int error, resid;
+ struct cdevsw *dsw;
- if (ap->a_vp->v_type != VDIR)
- return (EINVAL);
- return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
+ vp = ap->a_vp;
+ dev = vp->v_rdev;
+ uio = ap->a_uio;
+ td = uio->uio_td;
+ resid = uio->uio_resid;
+
+ if (resid == 0)
+ return (0);
+
+ KASSERT(dev->si_refcount > 0,
+ ("specread() on un-referenced struct cdev *(%s)", devtoname(dev)));
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return (ENXIO);
+ VOP_UNLOCK(vp, 0, td);
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ error = dsw->d_read(dev, uio, ap->a_ioflag);
+ PICKUP_GIANT();
+ } else
+ error = dsw->d_read(dev, uio, ap->a_ioflag);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ dev_relthread(dev);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0))
+ vfs_timestamp(&dev->si_atime);
+ return (error);
}
static int
@@ -721,6 +1080,44 @@ devfs_revoke(ap)
}
static int
+devfs_rioctl(ap)
+ struct vop_ioctl_args /* {
+ struct vnode *a_vp;
+ u_long a_command;
+ caddr_t a_data;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ int error;
+ struct devfs_mount *dmp;
+
+ dmp = VFSTODEVFS(ap->a_vp->v_mount);
+ lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread);
+ devfs_populate(dmp);
+ lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread);
+ error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data,
+ ap->a_td);
+ return (error);
+}
+
+static int
+devfs_rread(ap)
+ struct vop_read_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+
+ if (ap->a_vp->v_type != VDIR)
+ return (EINVAL);
+ return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
+}
+
+static int
devfs_setattr(ap)
struct vop_setattr_args /* {
struct vnode *a_vp;
@@ -834,6 +1231,58 @@ devfs_setlabel(ap)
}
#endif
+static int doslowdown = 0;
+SYSCTL_INT(_debug, OID_AUTO, doslowdown, CTLFLAG_RW, &doslowdown, 0, "");
+
+static int
+devfs_specstrategy(ap)
+ struct vop_specstrategy_args /* {
+ struct vnode *a_vp;
+ struct buf *a_bp;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct buf *bp = ap->a_bp;
+ struct mount *mp;
+ struct thread *td = curthread;
+
+ KASSERT(ap->a_vp->v_rdev == ap->a_bp->b_dev,
+ ("%s, dev %s != %s", __func__,
+ devtoname(ap->a_vp->v_rdev),
+ devtoname(ap->a_bp->b_dev)));
+ KASSERT(bp->b_iocmd == BIO_READ || bp->b_iocmd == BIO_WRITE,
+ ("Wrong b_iocmd buf=%p cmd=%d", bp, bp->b_iocmd));
+
+ /*
+ * Slow down disk requests for niced processes.
+ */
+ if (doslowdown && td && td->td_proc->p_nice > 0) {
+ msleep(td, NULL, PPAUSE | PCATCH, "ioslow",
+ td->td_proc->p_nice);
+ }
+ /*
+ * Collect statistics on synchronous and asynchronous read
+ * and write counts for disks that have associated filesystems.
+ */
+ if (vn_isdisk(vp, NULL) && (mp = vp->v_rdev->si_mountpoint) != NULL) {
+ if (bp->b_iocmd == BIO_WRITE) {
+ if (bp->b_lock.lk_lockholder == LK_KERNPROC)
+ mp->mnt_stat.f_asyncwrites++;
+ else
+ mp->mnt_stat.f_syncwrites++;
+ } else {
+ if (bp->b_lock.lk_lockholder == LK_KERNPROC)
+ mp->mnt_stat.f_asyncreads++;
+ else
+ mp->mnt_stat.f_syncreads++;
+ }
+ }
+
+ dev_strategy(bp);
+
+ return (0);
+}
+
static int
devfs_symlink(ap)
struct vop_symlink_args /* {
@@ -876,15 +1325,64 @@ devfs_symlink(ap)
return (0);
}
+/*
+ * Vnode op for write
+ */
+/* ARGSUSED */
+static int
+devfs_write(ap)
+ struct vop_write_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ struct vnode *vp;
+ struct thread *td;
+ struct uio *uio;
+ struct cdev *dev;
+ int error, resid;
+ struct cdevsw *dsw;
+
+ vp = ap->a_vp;
+ dev = vp->v_rdev;
+ uio = ap->a_uio;
+ td = uio->uio_td;
+ resid = uio->uio_resid;
+
+ dsw = dev_refthread(dev);
+ if (dsw == NULL)
+ return (ENXIO);
+ VOP_UNLOCK(vp, 0, td);
+ KASSERT(dev->si_refcount > 0,
+ ("devfs_write() on un-referenced struct cdev *(%s)",
+ devtoname(dev)));
+ if (!(dsw->d_flags & D_NEEDGIANT)) {
+ DROP_GIANT();
+ error = dsw->d_write(dev, uio, ap->a_ioflag);
+ PICKUP_GIANT();
+ } else
+ error = dsw->d_write(dev, uio, ap->a_ioflag);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ dev_relthread(dev);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
+ vfs_timestamp(&dev->si_ctime);
+ dev->si_mtime = dev->si_ctime;
+ }
+ return (error);
+}
+
+
static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) vop_defaultop },
{ &vop_access_desc, (vop_t *) devfs_access },
{ &vop_getattr_desc, (vop_t *) devfs_getattr },
- { &vop_ioctl_desc, (vop_t *) devfs_ioctl },
+ { &vop_ioctl_desc, (vop_t *) devfs_rioctl },
{ &vop_lookup_desc, (vop_t *) devfs_lookup },
{ &vop_mknod_desc, (vop_t *) devfs_mknod },
{ &vop_pathconf_desc, (vop_t *) devfs_pathconf },
- { &vop_read_desc, (vop_t *) devfs_read },
+ { &vop_read_desc, (vop_t *) devfs_rread },
{ &vop_readdir_desc, (vop_t *) devfs_readdir },
{ &vop_readlink_desc, (vop_t *) devfs_readlink },
{ &vop_reclaim_desc, (vop_t *) devfs_reclaim },
@@ -897,25 +1395,52 @@ static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = {
{ &vop_symlink_desc, (vop_t *) devfs_symlink },
{ NULL, NULL }
};
+
static struct vnodeopv_desc devfs_vnodeop_opv_desc =
{ &devfs_vnodeop_p, devfs_vnodeop_entries };
VNODEOP_SET(devfs_vnodeop_opv_desc);
static struct vnodeopv_entry_desc devfs_specop_entries[] = {
- { &vop_default_desc, (vop_t *) spec_vnoperate },
+ { &vop_default_desc, (vop_t *) vop_defaultop },
{ &vop_access_desc, (vop_t *) devfs_access },
+ { &vop_advlock_desc, (vop_t *) devfs_advlock },
+ { &vop_bmap_desc, (vop_t *) vop_panic },
+ { &vop_close_desc, (vop_t *) devfs_close },
+ { &vop_create_desc, (vop_t *) vop_panic },
+ { &vop_fsync_desc, (vop_t *) devfs_fsync },
{ &vop_getattr_desc, (vop_t *) devfs_getattr },
+ { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
+ { &vop_ioctl_desc, (vop_t *) devfs_ioctl },
+ { &vop_kqfilter_desc, (vop_t *) devfs_kqfilter },
+ { &vop_lease_desc, (vop_t *) vop_null },
+ { &vop_link_desc, (vop_t *) vop_panic },
+ { &vop_mkdir_desc, (vop_t *) vop_panic },
+ { &vop_mknod_desc, (vop_t *) vop_panic },
+ { &vop_open_desc, (vop_t *) devfs_open },
{ &vop_pathconf_desc, (vop_t *) devfs_pathconf },
+ { &vop_poll_desc, (vop_t *) devfs_poll },
+ { &vop_print_desc, (vop_t *) devfs_print },
+ { &vop_read_desc, (vop_t *) devfs_read },
+ { &vop_readdir_desc, (vop_t *) vop_panic },
+ { &vop_readlink_desc, (vop_t *) vop_panic },
+ { &vop_reallocblks_desc, (vop_t *) vop_panic },
{ &vop_reclaim_desc, (vop_t *) devfs_reclaim },
{ &vop_remove_desc, (vop_t *) devfs_remove },
+ { &vop_rename_desc, (vop_t *) vop_panic },
{ &vop_revoke_desc, (vop_t *) devfs_revoke },
+ { &vop_rmdir_desc, (vop_t *) vop_panic },
{ &vop_setattr_desc, (vop_t *) devfs_setattr },
#ifdef MAC
{ &vop_setlabel_desc, (vop_t *) devfs_setlabel },
#endif
+ { &vop_specstrategy_desc, (vop_t *) devfs_specstrategy },
+ { &vop_strategy_desc, (vop_t *) vop_panic },
+ { &vop_symlink_desc, (vop_t *) vop_panic },
+ { &vop_write_desc, (vop_t *) devfs_write },
{ NULL, NULL }
};
+
static struct vnodeopv_desc devfs_specop_opv_desc =
{ &devfs_specop_p, devfs_specop_entries };
OpenPOWER on IntegriCloud