Allow EVFILT_VNODE events to work on every filesystem type, not just
UFS by: - Making the pre and post hooks for the VOP functions work even when DEBUG_VFS_LOCKS is not defined. - Moving the KNOTE activations into the corresponding VOP hooks. - Creating a MNTK_NOKNOTE flag for the mnt_kern_flag field of struct mount that permits filesystems to disable the new behavior. - Creating a default VOP_KQFILTER function: vfs_kqfilter() My benchmarks have not revealed any performance degradation. Reviewed by: jeff, bde Approved by: rwatson, jmg (kqueue changes), grehan (mentor)
This commit is contained in:
parent
bf3a7d1c45
commit
0835f7b4a9
@ -502,7 +502,6 @@ ext2_setattr(ap)
|
||||
return (EROFS);
|
||||
error = ext2_chmod(vp, (int)vap->va_mode, cred, td);
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -502,7 +502,6 @@ ext2_setattr(ap)
|
||||
return (EROFS);
|
||||
error = ext2_chmod(vp, (int)vap->va_mode, cred, td);
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
@ -82,6 +83,7 @@ struct vop_vector default_vnodeops = {
|
||||
.vop_getwritemount = vop_stdgetwritemount,
|
||||
.vop_inactive = VOP_NULL,
|
||||
.vop_ioctl = VOP_ENOTTY,
|
||||
.vop_kqfilter = vop_stdkqfilter,
|
||||
.vop_islocked = vop_stdislocked,
|
||||
.vop_lease = VOP_NULL,
|
||||
.vop_lock = vop_stdlock,
|
||||
@ -464,6 +466,12 @@ vop_stdgetpages(ap)
|
||||
ap->a_count, ap->a_reqpage);
|
||||
}
|
||||
|
||||
int
|
||||
vop_stdkqfilter(struct vop_kqfilter_args *ap)
|
||||
{
|
||||
return vfs_kqfilter(ap);
|
||||
}
|
||||
|
||||
/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */
|
||||
int
|
||||
vop_stdputpages(ap)
|
||||
|
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/event.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/extattr.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -3304,12 +3305,14 @@ assert_vop_slocked(struct vnode *vp, const char *str)
|
||||
vfs_badlock("is not locked shared but should be", str, vp);
|
||||
}
|
||||
#endif /* 0 */
|
||||
#endif /* DEBUG_VFS_LOCKS */
|
||||
|
||||
void
|
||||
vop_rename_pre(void *ap)
|
||||
{
|
||||
struct vop_rename_args *a = ap;
|
||||
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
if (a->a_tvp)
|
||||
ASSERT_VI_UNLOCKED(a->a_tvp, "VOP_RENAME");
|
||||
ASSERT_VI_UNLOCKED(a->a_tdvp, "VOP_RENAME");
|
||||
@ -3326,11 +3329,20 @@ vop_rename_pre(void *ap)
|
||||
if (a->a_tvp)
|
||||
ASSERT_VOP_LOCKED(a->a_tvp, "vop_rename: tvp not locked");
|
||||
ASSERT_VOP_LOCKED(a->a_tdvp, "vop_rename: tdvp not locked");
|
||||
#endif
|
||||
if (a->a_tdvp != a->a_fdvp)
|
||||
vholdl(a->a_fdvp);
|
||||
if (a->a_tvp != a->a_fvp)
|
||||
vhold(a->a_fvp);
|
||||
vhold(a->a_tdvp);
|
||||
if (a->a_tvp)
|
||||
vhold(a->a_tvp);
|
||||
}
|
||||
|
||||
void
|
||||
vop_strategy_pre(void *ap)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_strategy_args *a;
|
||||
struct buf *bp;
|
||||
|
||||
@ -3350,11 +3362,13 @@ vop_strategy_pre(void *ap)
|
||||
if (vfs_badlock_ddb)
|
||||
kdb_enter("lock violation");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_lookup_pre(void *ap)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_lookup_args *a;
|
||||
struct vnode *dvp;
|
||||
|
||||
@ -3362,11 +3376,13 @@ vop_lookup_pre(void *ap)
|
||||
dvp = a->a_dvp;
|
||||
ASSERT_VI_UNLOCKED(dvp, "VOP_LOOKUP");
|
||||
ASSERT_VOP_LOCKED(dvp, "VOP_LOOKUP");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_lookup_post(void *ap, int rc)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_lookup_args *a;
|
||||
struct vnode *dvp;
|
||||
struct vnode *vp;
|
||||
@ -3380,48 +3396,155 @@ vop_lookup_post(void *ap, int rc)
|
||||
|
||||
if (!rc)
|
||||
ASSERT_VOP_LOCKED(vp, "VOP_LOOKUP (child)");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_lock_pre(void *ap)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_lock_args *a = ap;
|
||||
|
||||
if ((a->a_flags & LK_INTERLOCK) == 0)
|
||||
ASSERT_VI_UNLOCKED(a->a_vp, "VOP_LOCK");
|
||||
else
|
||||
ASSERT_VI_LOCKED(a->a_vp, "VOP_LOCK");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_lock_post(void *ap, int rc)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_lock_args *a = ap;
|
||||
|
||||
ASSERT_VI_UNLOCKED(a->a_vp, "VOP_LOCK");
|
||||
if (rc == 0)
|
||||
ASSERT_VOP_LOCKED(a->a_vp, "VOP_LOCK");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_unlock_pre(void *ap)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_unlock_args *a = ap;
|
||||
|
||||
if (a->a_flags & LK_INTERLOCK)
|
||||
ASSERT_VI_LOCKED(a->a_vp, "VOP_UNLOCK");
|
||||
ASSERT_VOP_LOCKED(a->a_vp, "VOP_UNLOCK");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_unlock_post(void *ap, int rc)
|
||||
{
|
||||
#ifdef DEBUG_VFS_LOCKS
|
||||
struct vop_unlock_args *a = ap;
|
||||
|
||||
if (a->a_flags & LK_INTERLOCK)
|
||||
ASSERT_VI_UNLOCKED(a->a_vp, "VOP_UNLOCK");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vop_create_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_create_args *a = ap;
|
||||
|
||||
if (!rc)
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE);
|
||||
}
|
||||
|
||||
void
|
||||
vop_link_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_link_args *a = ap;
|
||||
|
||||
if (!rc) {
|
||||
VFS_SEND_KNOTE(a->a_vp, NOTE_LINK);
|
||||
VFS_SEND_KNOTE(a->a_tdvp, NOTE_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vop_mkdir_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_mkdir_args *a = ap;
|
||||
|
||||
if (!rc)
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE | NOTE_LINK);
|
||||
}
|
||||
|
||||
void
|
||||
vop_mknod_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_mknod_args *a = ap;
|
||||
|
||||
if (!rc)
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE);
|
||||
}
|
||||
|
||||
void
|
||||
vop_remove_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_remove_args *a = ap;
|
||||
|
||||
if (!rc) {
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE);
|
||||
VFS_SEND_KNOTE(a->a_vp, NOTE_DELETE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vop_rename_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_rename_args *a = ap;
|
||||
|
||||
if (!rc) {
|
||||
VFS_SEND_KNOTE(a->a_fdvp, NOTE_WRITE);
|
||||
VFS_SEND_KNOTE(a->a_tdvp, NOTE_WRITE);
|
||||
VFS_SEND_KNOTE(a->a_fvp, NOTE_RENAME);
|
||||
if (a->a_tvp)
|
||||
VFS_SEND_KNOTE(a->a_tvp, NOTE_DELETE);
|
||||
}
|
||||
if (a->a_tdvp != a->a_fdvp)
|
||||
vdrop(a->a_fdvp);
|
||||
if (a->a_tvp != a->a_fvp)
|
||||
vdrop(a->a_fvp);
|
||||
vdrop(a->a_tdvp);
|
||||
if (a->a_tvp)
|
||||
vdrop(a->a_tvp);
|
||||
}
|
||||
|
||||
void
|
||||
vop_rmdir_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_rmdir_args *a = ap;
|
||||
|
||||
if (!rc) {
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE | NOTE_LINK);
|
||||
VFS_SEND_KNOTE(a->a_vp, NOTE_DELETE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vop_setattr_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_setattr_args *a = ap;
|
||||
|
||||
if (!rc)
|
||||
VFS_SEND_KNOTE(a->a_vp, NOTE_ATTRIB);
|
||||
}
|
||||
|
||||
void
|
||||
vop_symlink_post(void *ap, int rc)
|
||||
{
|
||||
struct vop_symlink_args *a = ap;
|
||||
|
||||
if (!rc)
|
||||
VFS_SEND_KNOTE(a->a_dvp, NOTE_WRITE);
|
||||
}
|
||||
#endif /* DEBUG_VFS_LOCKS */
|
||||
|
||||
static struct knlist fs_knlist;
|
||||
|
||||
@ -3510,3 +3633,111 @@ init_va_filerev(void)
|
||||
getbinuptime(&bt);
|
||||
return (((u_quad_t)bt.sec << 32LL) | (bt.frac >> 32LL));
|
||||
}
|
||||
|
||||
static int filt_vfsread(struct knote *kn, long hint);
|
||||
static int filt_vfswrite(struct knote *kn, long hint);
|
||||
static int filt_vfsvnode(struct knote *kn, long hint);
|
||||
static void filt_vfsdetach(struct knote *kn);
|
||||
|
||||
static struct filterops vfsread_filtops =
|
||||
{ 1, NULL, filt_vfsdetach, filt_vfsread };
|
||||
static struct filterops vfswrite_filtops =
|
||||
{ 1, NULL, filt_vfsdetach, filt_vfswrite };
|
||||
static struct filterops vfsvnode_filtops =
|
||||
{ 1, NULL, filt_vfsdetach, filt_vfsvnode };
|
||||
|
||||
int
|
||||
vfs_kqfilter(struct vop_kqfilter_args *ap)
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct knote *kn = ap->a_kn;
|
||||
|
||||
switch (kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
kn->kn_fop = &vfsread_filtops;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
kn->kn_fop = &vfswrite_filtops;
|
||||
break;
|
||||
case EVFILT_VNODE:
|
||||
kn->kn_fop = &vfsvnode_filtops;
|
||||
break;
|
||||
default:
|
||||
return (1);
|
||||
}
|
||||
|
||||
kn->kn_hook = (caddr_t)vp;
|
||||
|
||||
if (vp->v_pollinfo == NULL)
|
||||
v_addpollinfo(vp);
|
||||
if (vp->v_pollinfo == NULL)
|
||||
return (ENOMEM);
|
||||
knlist_add(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach knote from vnode
|
||||
*/
|
||||
static void
|
||||
filt_vfsdetach(struct knote *kn)
|
||||
{
|
||||
struct vnode *vp = (struct vnode *)kn->kn_hook;
|
||||
|
||||
KASSERT(vp->v_pollinfo != NULL, ("Missing v_pollinfo"));
|
||||
knlist_remove(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_vfsread(struct knote *kn, long hint)
|
||||
{
|
||||
struct vnode *vp = (struct vnode *)kn->kn_hook;
|
||||
struct vattr va;
|
||||
|
||||
/*
|
||||
* filesystem is gone, so set the EOF flag and schedule
|
||||
* the knote for deletion.
|
||||
*/
|
||||
if (hint == NOTE_REVOKE) {
|
||||
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
|
||||
return (1);
|
||||
}
|
||||
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY, curthread);
|
||||
if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread))
|
||||
return (0);
|
||||
if (VOP_UNLOCK(vp, 0, curthread))
|
||||
return (0);
|
||||
|
||||
kn->kn_data = va.va_size - kn->kn_fp->f_offset;
|
||||
return (kn->kn_data != 0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_vfswrite(struct knote *kn, long hint)
|
||||
{
|
||||
/*
|
||||
* filesystem is gone, so set the EOF flag and schedule
|
||||
* the knote for deletion.
|
||||
*/
|
||||
if (hint == NOTE_REVOKE)
|
||||
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
|
||||
|
||||
kn->kn_data = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
filt_vfsvnode(struct knote *kn, long hint)
|
||||
{
|
||||
if (kn->kn_sfflags & hint)
|
||||
kn->kn_fflags |= hint;
|
||||
if (hint == NOTE_REVOKE) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
return (1);
|
||||
}
|
||||
return (kn->kn_fflags != 0);
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ vop_cachedlookup {
|
||||
#
|
||||
#% create dvp E E E
|
||||
#% create vpp - L -
|
||||
#! create post vop_create_post
|
||||
#
|
||||
vop_create {
|
||||
IN struct vnode *dvp;
|
||||
@ -115,6 +116,7 @@ vop_whiteout {
|
||||
#
|
||||
#% mknod dvp E E E
|
||||
#% mknod vpp - L -
|
||||
#! mknod post vop_mknod_post
|
||||
#
|
||||
vop_mknod {
|
||||
IN struct vnode *dvp;
|
||||
@ -166,6 +168,7 @@ vop_getattr {
|
||||
|
||||
#
|
||||
#% setattr vp E E E
|
||||
#! setattr post vop_setattr_post
|
||||
#
|
||||
vop_setattr {
|
||||
IN struct vnode *vp;
|
||||
@ -186,6 +189,8 @@ vop_read {
|
||||
|
||||
#
|
||||
#% write vp E E E
|
||||
#! write pre VOP_WRITE_PRE
|
||||
#! write post VOP_WRITE_POST
|
||||
#
|
||||
vop_write {
|
||||
IN struct vnode *vp;
|
||||
@ -254,6 +259,7 @@ vop_fsync {
|
||||
#
|
||||
#% remove dvp E E E
|
||||
#% remove vp E E E
|
||||
#! remove post vop_remove_post
|
||||
#
|
||||
vop_remove {
|
||||
IN struct vnode *dvp;
|
||||
@ -264,6 +270,7 @@ vop_remove {
|
||||
#
|
||||
#% link tdvp E E E
|
||||
#% link vp E E E
|
||||
#! link post vop_link_post
|
||||
#
|
||||
vop_link {
|
||||
IN struct vnode *tdvp;
|
||||
@ -277,6 +284,7 @@ vop_link {
|
||||
# rename tdvp E U U
|
||||
# rename tvp X U U
|
||||
#! rename pre vop_rename_pre
|
||||
#! rename post vop_rename_post
|
||||
#
|
||||
vop_rename {
|
||||
IN WILLRELE struct vnode *fdvp;
|
||||
@ -290,6 +298,7 @@ vop_rename {
|
||||
#
|
||||
#% mkdir dvp E E E
|
||||
#% mkdir vpp - E -
|
||||
#! mkdir post vop_mkdir_post
|
||||
#
|
||||
vop_mkdir {
|
||||
IN struct vnode *dvp;
|
||||
@ -301,6 +310,7 @@ vop_mkdir {
|
||||
#
|
||||
#% rmdir dvp E E E
|
||||
#% rmdir vp E E E
|
||||
#! rmdir post vop_rmdir_post
|
||||
#
|
||||
vop_rmdir {
|
||||
IN struct vnode *dvp;
|
||||
@ -311,6 +321,7 @@ vop_rmdir {
|
||||
#
|
||||
#% symlink dvp E E E
|
||||
#% symlink vpp - E -
|
||||
#! symlink post vop_symlink_post
|
||||
#
|
||||
vop_symlink {
|
||||
IN struct vnode *dvp;
|
||||
|
@ -141,6 +141,8 @@ MALLOC_DECLARE(M_KQUEUE);
|
||||
#define KNOTE_LOCKED(list, hint) knote(list, hint, 1)
|
||||
#define KNOTE_UNLOCKED(list, hint) knote(list, hint, 0)
|
||||
|
||||
#define KNLIST_EMPTY(list) SLIST_EMPTY(&(list)->kl_list)
|
||||
|
||||
/*
|
||||
* Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also
|
||||
* shared by EVFILT_PROC (all knotes attached to p->p_klist)
|
||||
|
@ -270,6 +270,7 @@ struct vnode *__mnt_vnode_next(struct vnode **nvp, struct mount *mp);
|
||||
#define MNTK_SUSPEND 0x08000000 /* request write suspension */
|
||||
#define MNTK_SUSPENDED 0x10000000 /* write operations are suspended */
|
||||
#define MNTK_MPSAFE 0x20000000 /* Filesystem is MPSAFE. */
|
||||
#define MNTK_NOKNOTE 0x80000000 /* Don't send KNOTEs from VOP hooks */
|
||||
|
||||
/*
|
||||
* Sysctl CTL_VFS definitions.
|
||||
@ -549,6 +550,13 @@ extern int mpsafe_vfs;
|
||||
mtx_assert(&Giant, MA_OWNED); \
|
||||
} while (0)
|
||||
|
||||
#define VFS_SEND_KNOTE(vp, hint) do \
|
||||
{ \
|
||||
if ((vp)->v_mount && \
|
||||
((vp)->v_mount->mnt_kern_flag & MNTK_NOKNOTE) == 0) \
|
||||
VN_KNOTE_UNLOCKED((vp), (hint)); \
|
||||
} while (0)
|
||||
|
||||
#include <sys/module.h>
|
||||
|
||||
/*
|
||||
|
@ -222,9 +222,13 @@ struct xvnode {
|
||||
#define xv_dev xv_un.xv_uns.xvu_dev
|
||||
#define xv_ino xv_un.xv_uns.xvu_ino
|
||||
|
||||
#define VN_KNOTE(vp, b, a) \
|
||||
/* We don't need to lock the knlist */
|
||||
#define VN_KNLIST_EMPTY(vp) ((vp)->v_pollinfo == NULL || \
|
||||
KNLIST_EMPTY(&(vp)->v_pollinfo->vpi_selinfo.si_note))
|
||||
|
||||
#define VN_KNOTE(vp, b, a) \
|
||||
do { \
|
||||
if ((vp)->v_pollinfo != NULL) \
|
||||
if (!VN_KNLIST_EMPTY(vp)) \
|
||||
KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b), (a)); \
|
||||
} while (0)
|
||||
#define VN_KNOTE_LOCKED(vp, b) VN_KNOTE(vp, b, 1)
|
||||
@ -489,16 +493,6 @@ voi0 assert_vop_slocked(struct vnode *vp, const char *str);
|
||||
#endif
|
||||
void assert_vop_unlocked(struct vnode *vp, const char *str);
|
||||
|
||||
/* These are called from within the actual VOPS. */
|
||||
void vop_lock_pre(void *a);
|
||||
void vop_lock_post(void *a, int rc);
|
||||
void vop_lookup_post(void *a, int rc);
|
||||
void vop_lookup_pre(void *a);
|
||||
void vop_rename_pre(void *a);
|
||||
void vop_strategy_pre(void *a);
|
||||
void vop_unlock_post(void *a, int rc);
|
||||
void vop_unlock_pre(void *a);
|
||||
|
||||
#define ASSERT_VI_LOCKED(vp, str) assert_vi_locked((vp), (str))
|
||||
#define ASSERT_VI_UNLOCKED(vp, str) assert_vi_unlocked((vp), (str))
|
||||
#define ASSERT_VOP_ELOCKED(vp, str) assert_vop_elocked((vp), (str))
|
||||
@ -659,6 +653,7 @@ int vop_stdgetwritemount(struct vop_getwritemount_args *);
|
||||
int vop_stdgetpages(struct vop_getpages_args *);
|
||||
int vop_stdinactive(struct vop_inactive_args *);
|
||||
int vop_stdislocked(struct vop_islocked_args *);
|
||||
int vop_stdkqfilter(struct vop_kqfilter_args *);
|
||||
int vop_stdlock(struct vop_lock_args *);
|
||||
int vop_stdputpages(struct vop_putpages_args *);
|
||||
int vop_stdunlock(struct vop_unlock_args *);
|
||||
@ -672,6 +667,46 @@ int vop_enotty(struct vop_generic_args *ap);
|
||||
int vop_null(struct vop_generic_args *ap);
|
||||
int vop_panic(struct vop_generic_args *ap);
|
||||
|
||||
/* These are called from within the actual VOPS. */
|
||||
void vop_create_post(void *a, int rc);
|
||||
void vop_link_post(void *a, int rc);
|
||||
void vop_lock_pre(void *a);
|
||||
void vop_lock_post(void *a, int rc);
|
||||
void vop_lookup_post(void *a, int rc);
|
||||
void vop_lookup_pre(void *a);
|
||||
void vop_mkdir_post(void *a, int rc);
|
||||
void vop_mknod_post(void *a, int rc);
|
||||
void vop_remove_post(void *a, int rc);
|
||||
void vop_rename_post(void *a, int rc);
|
||||
void vop_rename_pre(void *a);
|
||||
void vop_rmdir_post(void *a, int rc);
|
||||
void vop_setattr_post(void *a, int rc);
|
||||
void vop_strategy_pre(void *a);
|
||||
void vop_symlink_post(void *a, int rc);
|
||||
void vop_unlock_post(void *a, int rc);
|
||||
void vop_unlock_pre(void *a);
|
||||
|
||||
#define VOP_WRITE_PRE(ap) \
|
||||
struct vattr va; \
|
||||
int error, osize, ooffset, noffset; \
|
||||
\
|
||||
osize = ooffset = noffset = 0; \
|
||||
if (!VN_KNLIST_EMPTY((ap)->a_vp)) { \
|
||||
error = VOP_GETATTR((ap)->a_vp, &va, (ap)->a_cred, \
|
||||
curthread); \
|
||||
if (error) \
|
||||
return (error); \
|
||||
ooffset = (ap)->a_uio->uio_offset; \
|
||||
osize = va.va_size; \
|
||||
}
|
||||
|
||||
#define VOP_WRITE_POST(ap, ret) \
|
||||
noffset = (ap)->a_uio->uio_offset; \
|
||||
if (noffset > ooffset && !VN_KNLIST_EMPTY((ap)->a_vp)) { \
|
||||
VFS_SEND_KNOTE((ap)->a_vp, NOTE_WRITE \
|
||||
| (noffset > osize ? NOTE_EXTEND : 0)); \
|
||||
}
|
||||
|
||||
void vput(struct vnode *vp);
|
||||
void vrele(struct vnode *vp);
|
||||
void vref(struct vnode *vp);
|
||||
@ -700,6 +735,8 @@ int vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td,
|
||||
void vfs_hash_rehash(struct vnode *vp, u_int hash);
|
||||
void vfs_hash_remove(struct vnode *vp);
|
||||
|
||||
int vfs_kqfilter(struct vop_kqfilter_args *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_VNODE_H_ */
|
||||
|
@ -89,21 +89,17 @@ function add_debug_code(name, arg, pos, ind)
|
||||
}
|
||||
}
|
||||
|
||||
function add_debug_pre(name)
|
||||
function add_pre(name)
|
||||
{
|
||||
if (lockdata[name, "pre"]) {
|
||||
printc("#ifdef DEBUG_VFS_LOCKS");
|
||||
printc("\t"lockdata[name, "pre"]"(a);");
|
||||
printc("#endif");
|
||||
}
|
||||
}
|
||||
|
||||
function add_debug_post(name)
|
||||
function add_post(name)
|
||||
{
|
||||
if (lockdata[name, "post"]) {
|
||||
printc("#ifdef DEBUG_VFS_LOCKS");
|
||||
printc("\t"lockdata[name, "post"]"(a, rc);");
|
||||
printc("#endif");
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,9 +170,10 @@ if (hfile) {
|
||||
if (cfile) {
|
||||
printc(common_head \
|
||||
"#include <sys/param.h>\n" \
|
||||
"#include <sys/event.h>\n" \
|
||||
"#include <sys/mount.h>\n" \
|
||||
"#include <sys/systm.h>\n" \
|
||||
"#include <sys/vnode.h>\n" \
|
||||
"#include <sys/systm.h>\n" \
|
||||
"\n" \
|
||||
"struct vnodeop_desc vop_default_desc = {\n" \
|
||||
" \"default\",\n" \
|
||||
@ -369,7 +366,7 @@ while ((getline < srcfile) > 0) {
|
||||
printc("\tVNASSERT(vop != NULL, a->a_" args[0]", (\"No "name"(%p, %p)\", a->a_" args[0]", a));")
|
||||
for (i = 0; i < numargs; ++i)
|
||||
add_debug_code(name, args[i], "Entry", "\t");
|
||||
add_debug_pre(name);
|
||||
add_pre(name);
|
||||
printc("\tif (vop->"name" != NULL)")
|
||||
printc("\t\trc = vop->"name"(a);")
|
||||
printc("\telse")
|
||||
@ -382,7 +379,7 @@ while ((getline < srcfile) > 0) {
|
||||
for (i = 0; i < numargs; ++i)
|
||||
add_debug_code(name, args[i], "Error", "\t\t");
|
||||
printc("\t}");
|
||||
add_debug_post(name);
|
||||
add_post(name);
|
||||
printc("\treturn (rc);");
|
||||
printc("}\n");
|
||||
|
||||
|
@ -572,7 +572,7 @@ ffs_write(ap)
|
||||
ufs_lbn_t lbn;
|
||||
off_t osize;
|
||||
int seqcount;
|
||||
int blkoffset, error, extended, flags, ioflag, resid, size, xfersize;
|
||||
int blkoffset, error, flags, ioflag, resid, size, xfersize;
|
||||
|
||||
vp = ap->a_vp;
|
||||
uio = ap->a_uio;
|
||||
@ -584,7 +584,6 @@ ffs_write(ap)
|
||||
panic("ffs_write+IO_EXT");
|
||||
#endif
|
||||
|
||||
extended = 0;
|
||||
seqcount = ap->a_ioflag >> IO_SEQSHIFT;
|
||||
ip = VTOI(vp);
|
||||
|
||||
@ -681,7 +680,6 @@ ffs_write(ap)
|
||||
if (uio->uio_offset + xfersize > ip->i_size) {
|
||||
ip->i_size = uio->uio_offset + xfersize;
|
||||
DIP_SET(ip, i_size, ip->i_size);
|
||||
extended = 1;
|
||||
}
|
||||
|
||||
size = blksize(fs, ip, lbn) - bp->b_resid;
|
||||
@ -737,8 +735,6 @@ ffs_write(ap)
|
||||
ip->i_mode &= ~(ISUID | ISGID);
|
||||
DIP_SET(ip, i_mode, ip->i_mode);
|
||||
}
|
||||
if (resid > uio->uio_resid)
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
|
||||
if (error) {
|
||||
if (ioflag & IO_UNIT) {
|
||||
(void)ffs_truncate(vp, osize,
|
||||
|
@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/lockf.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/mac.h>
|
||||
@ -109,11 +108,6 @@ static vop_symlink_t ufs_symlink;
|
||||
static vop_whiteout_t ufs_whiteout;
|
||||
static vop_close_t ufsfifo_close;
|
||||
static vop_kqfilter_t ufsfifo_kqfilter;
|
||||
static int filt_ufsread(struct knote *kn, long hint);
|
||||
static int filt_ufswrite(struct knote *kn, long hint);
|
||||
static int filt_ufsvnode(struct knote *kn, long hint);
|
||||
static void filt_ufsdetach(struct knote *kn);
|
||||
static vop_kqfilter_t ufs_kqfilter;
|
||||
|
||||
/*
|
||||
* A virgin directory (no blushing please).
|
||||
@ -179,7 +173,6 @@ ufs_create(ap)
|
||||
ap->a_dvp, ap->a_vpp, ap->a_cnp);
|
||||
if (error)
|
||||
return (error);
|
||||
VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -206,7 +199,6 @@ ufs_mknod(ap)
|
||||
ap->a_dvp, vpp, ap->a_cnp);
|
||||
if (error)
|
||||
return (error);
|
||||
VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE);
|
||||
ip = VTOI(*vpp);
|
||||
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
|
||||
if (vap->va_rdev != VNOVAL) {
|
||||
@ -590,7 +582,6 @@ ufs_setattr(ap)
|
||||
return (EPERM);
|
||||
error = ufs_chmod(vp, (int)vap->va_mode, cred, td);
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -774,8 +765,6 @@ ufs_remove(ap)
|
||||
error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
|
||||
if (ip->i_nlink <= 0)
|
||||
vp->v_vflag |= VV_NOSYNC;
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_DELETE);
|
||||
VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE);
|
||||
out:
|
||||
return (error);
|
||||
}
|
||||
@ -836,8 +825,6 @@ ufs_link(ap)
|
||||
softdep_change_linkcnt(ip);
|
||||
}
|
||||
out:
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_LINK);
|
||||
VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1012,7 +999,6 @@ ufs_rename(ap)
|
||||
oldparent = dp->i_number;
|
||||
doingdirectory = 1;
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(fdvp, NOTE_WRITE); /* XXX right place? */
|
||||
vrele(fdvp);
|
||||
|
||||
/*
|
||||
@ -1121,7 +1107,6 @@ ufs_rename(ap)
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE);
|
||||
vput(tdvp);
|
||||
} else {
|
||||
if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
|
||||
@ -1205,9 +1190,7 @@ ufs_rename(ap)
|
||||
tcnp->cn_cred, tcnp->cn_thread)) != 0)
|
||||
goto bad;
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE);
|
||||
vput(tdvp);
|
||||
VN_KNOTE_UNLOCKED(tvp, NOTE_DELETE);
|
||||
vput(tvp);
|
||||
xp = NULL;
|
||||
}
|
||||
@ -1277,7 +1260,6 @@ ufs_rename(ap)
|
||||
error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
|
||||
xp->i_flag &= ~IN_RENAME;
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(fvp, NOTE_RENAME);
|
||||
if (dp)
|
||||
vput(fdvp);
|
||||
if (xp)
|
||||
@ -1596,7 +1578,6 @@ ufs_mkdir(ap)
|
||||
|
||||
bad:
|
||||
if (error == 0) {
|
||||
VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE | NOTE_LINK);
|
||||
*ap->a_vpp = tvp;
|
||||
} else {
|
||||
#ifdef UFS_ACL
|
||||
@ -1694,7 +1675,6 @@ ufs_rmdir(ap)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE | NOTE_LINK);
|
||||
cache_purge(dvp);
|
||||
/*
|
||||
* Truncate inode. The only stuff left in the directory is "." and
|
||||
@ -1723,7 +1703,6 @@ ufs_rmdir(ap)
|
||||
ufsdirhash_free(ip);
|
||||
#endif
|
||||
out:
|
||||
VN_KNOTE_UNLOCKED(vp, NOTE_DELETE);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1748,7 +1727,6 @@ ufs_symlink(ap)
|
||||
vpp, ap->a_cnp);
|
||||
if (error)
|
||||
return (error);
|
||||
VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE);
|
||||
vp = *vpp;
|
||||
len = strlen(ap->a_target);
|
||||
if (len < vp->v_mount->mnt_maxsymlinklen) {
|
||||
@ -2005,7 +1983,7 @@ ufsfifo_kqfilter(ap)
|
||||
|
||||
error = fifo_specops.vop_kqfilter(ap);
|
||||
if (error)
|
||||
error = ufs_kqfilter(ap);
|
||||
error = vfs_kqfilter(ap);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -2389,106 +2367,6 @@ ufs_makeinode(mode, dvp, vpp, cnp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct filterops ufsread_filtops =
|
||||
{ 1, NULL, filt_ufsdetach, filt_ufsread };
|
||||
static struct filterops ufswrite_filtops =
|
||||
{ 1, NULL, filt_ufsdetach, filt_ufswrite };
|
||||
static struct filterops ufsvnode_filtops =
|
||||
{ 1, NULL, filt_ufsdetach, filt_ufsvnode };
|
||||
|
||||
static int
|
||||
ufs_kqfilter(ap)
|
||||
struct vop_kqfilter_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct knote *a_kn;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct knote *kn = ap->a_kn;
|
||||
|
||||
switch (kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
kn->kn_fop = &ufsread_filtops;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
kn->kn_fop = &ufswrite_filtops;
|
||||
break;
|
||||
case EVFILT_VNODE:
|
||||
kn->kn_fop = &ufsvnode_filtops;
|
||||
break;
|
||||
default:
|
||||
return (1);
|
||||
}
|
||||
|
||||
kn->kn_hook = (caddr_t)vp;
|
||||
|
||||
if (vp->v_pollinfo == NULL)
|
||||
v_addpollinfo(vp);
|
||||
if (vp->v_pollinfo == NULL)
|
||||
return ENOMEM;
|
||||
knlist_add(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
filt_ufsdetach(struct knote *kn)
|
||||
{
|
||||
struct vnode *vp = (struct vnode *)kn->kn_hook;
|
||||
|
||||
KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo"));
|
||||
knlist_remove(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_ufsread(struct knote *kn, long hint)
|
||||
{
|
||||
struct vnode *vp = (struct vnode *)kn->kn_hook;
|
||||
struct inode *ip = VTOI(vp);
|
||||
|
||||
/*
|
||||
* filesystem is gone, so set the EOF flag and schedule
|
||||
* the knote for deletion.
|
||||
*/
|
||||
if (hint == NOTE_REVOKE) {
|
||||
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
|
||||
return (1);
|
||||
}
|
||||
|
||||
kn->kn_data = ip->i_size - kn->kn_fp->f_offset;
|
||||
return (kn->kn_data != 0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_ufswrite(struct knote *kn, long hint)
|
||||
{
|
||||
|
||||
/*
|
||||
* filesystem is gone, so set the EOF flag and schedule
|
||||
* the knote for deletion.
|
||||
*/
|
||||
if (hint == NOTE_REVOKE)
|
||||
kn->kn_flags |= (EV_EOF | EV_ONESHOT);
|
||||
|
||||
kn->kn_data = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
filt_ufsvnode(struct knote *kn, long hint)
|
||||
{
|
||||
|
||||
if (kn->kn_sfflags & hint)
|
||||
kn->kn_fflags |= hint;
|
||||
if (hint == NOTE_REVOKE) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
return (1);
|
||||
}
|
||||
return (kn->kn_fflags != 0);
|
||||
}
|
||||
|
||||
/* Global vfs data structures for ufs. */
|
||||
struct vop_vector ufs_vnodeops = {
|
||||
.vop_default = &default_vnodeops,
|
||||
@ -2511,7 +2389,6 @@ struct vop_vector ufs_vnodeops = {
|
||||
.vop_open = ufs_open,
|
||||
.vop_pathconf = ufs_pathconf,
|
||||
.vop_poll = vop_stdpoll,
|
||||
.vop_kqfilter = ufs_kqfilter,
|
||||
.vop_print = ufs_print,
|
||||
.vop_readdir = ufs_readdir,
|
||||
.vop_readlink = ufs_readlink,
|
||||
|
Loading…
Reference in New Issue
Block a user