From 117b5f5104df9cc2888eefee236986c003469219 Mon Sep 17 00:00:00 2001 From: jmmv Date: Thu, 9 Nov 2006 15:06:03 +0000 Subject: [PATCH] Audit kqueue notifications. The reference behavior is taken from MFS and is represented in the regression tests. --- sys/fs/tmpfs/TODO | 3 --- sys/fs/tmpfs/tmpfs_subr.c | 46 +++++++++++++++++++++++++++++++------ sys/fs/tmpfs/tmpfs_vfsops.c | 5 ++-- sys/fs/tmpfs/tmpfs_vnops.c | 21 +++++++---------- sys/fs/tmpfs/tmpfs_vnops.h | 4 ++-- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/sys/fs/tmpfs/TODO b/sys/fs/tmpfs/TODO index 54ddbf89e814..3d1cc887af41 100644 --- a/sys/fs/tmpfs/TODO +++ b/sys/fs/tmpfs/TODO @@ -18,6 +18,3 @@ jmmv: I may agree with the removal of the visual lines, but not with the vop_*_args assignment. Those are very ugly and add a lot of redundancy. - -- Check and fix KNOTE_* calls (e.g. missing NOTE_LINK on link(2), perhaps - others) diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 94b228c25cd1..063f46f3a21f 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmpfs_subr.c,v 1.28 2006/11/05 19:40:31 jmmv Exp $ */ +/* $NetBSD: tmpfs_subr.c,v 1.29 2006/11/09 15:06:03 jmmv Exp $ */ /* * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.28 2006/11/05 19:40:31 jmmv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.29 2006/11/09 15:06:03 jmmv Exp $"); #include #include @@ -155,6 +155,10 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type, nnode->tn_spec.tn_dir.tn_readdir_lastp = NULL; nnode->tn_links++; nnode->tn_spec.tn_dir.tn_parent->tn_links++; + if (parent != NULL) { + KASSERT(parent->tn_vnode != NULL); + VN_KNOTE(parent->tn_vnode, NOTE_LINK); + } break; case VFIFO: @@ -270,7 +274,8 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node) * The new directory entry is returned in *de. * * The link count of node is increased by one to reflect the new object - * referencing it. + * referencing it. This takes care of notifying kqueue listeners about + * this change. * * Returns zero on success or an appropriate error code on failure. */ @@ -294,6 +299,8 @@ tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, nde->td_node = node; node->tn_links++; + if (node->tn_links > 1 && node->tn_vnode != NULL) + VN_KNOTE(node->tn_vnode, NOTE_LINK); *de = nde; return 0; @@ -309,6 +316,10 @@ tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node, * object that referenced it. This only happens if 'node_exists' is true; * otherwise the function will not access the node referred to by the * directory entry, as it may already have been released from the outside. + * + * Interested parties (kqueue) are notified of the link count change; note + * that this can include both the node pointed to by the directory entry + * as well as its parent. */ void tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de, @@ -321,6 +332,12 @@ tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de, KASSERT(node->tn_links > 0); node->tn_links--; + if (node->tn_vnode != NULL) + VN_KNOTE(node->tn_vnode, node->tn_links == 0 ? + NOTE_DELETE : NOTE_LINK); + if (node->tn_type == VDIR) + VN_KNOTE(node->tn_spec.tn_dir.tn_parent->tn_vnode, + NOTE_LINK); } tmpfs_str_pool_put(&tmp->tm_str_pool, de->td_name, de->td_namelen); @@ -522,7 +539,6 @@ tmpfs_alloc_file(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, * insert the new node into the directory, an operation that * cannot fail. */ tmpfs_dir_attach(dvp, de); - VN_KNOTE(dvp, NOTE_WRITE); out: if (error != 0 || !(cnp->cn_flags & SAVESTART)) @@ -541,6 +557,9 @@ out: * Attaches the directory entry de to the directory represented by vp. * Note that this does not change the link count of the node pointed by * the directory entry, as this is done by tmpfs_alloc_dirent. + * + * As the "parent" directory changes, interested parties are notified of + * a write to it. */ void tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de) @@ -554,6 +573,8 @@ tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de) dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ TMPFS_NODE_MODIFIED; uvm_vnp_setsize(vp, dnode->tn_size); + + VN_KNOTE(vp, NOTE_WRITE); } /* --------------------------------------------------------------------- */ @@ -562,6 +583,9 @@ tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de) * Detaches the directory entry de from the directory represented by vp. * Note that this does not change the link count of the node pointed by * the directory entry, as this is done by tmpfs_free_dirent. + * + * As the "parent" directory changes, interested parties are notified of + * a write to it. */ void tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de) @@ -582,6 +606,8 @@ tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de) dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ TMPFS_NODE_MODIFIED; uvm_vnp_setsize(vp, dnode->tn_size); + + VN_KNOTE(vp, NOTE_WRITE); } /* --------------------------------------------------------------------- */ @@ -845,6 +871,10 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp) * the size newsize. 'vp' must point to a vnode that represents a regular * file. 'newsize' must be positive. * + * If the file is extended, the appropriate kevent is raised. This does + * not rise a write event though because resizing is not the same as + * writing. + * * Returns zero on success or an appropriate error code on failure. */ int @@ -908,6 +938,9 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize) error = 0; + if (newsize > oldsize) + VN_KNOTE(vp, NOTE_EXTEND); + out: return error; } @@ -1210,6 +1243,7 @@ tmpfs_chtimes(struct vnode *vp, struct timespec *atime, struct timespec *mtime, node->tn_status |= TMPFS_NODE_MODIFIED; tmpfs_update(vp, atime, mtime, 0); + VN_KNOTE(vp, NOTE_ATTRIB); KASSERT(VOP_ISLOCKED(vp)); @@ -1296,10 +1330,8 @@ tmpfs_truncate(struct vnode *vp, off_t length) } error = tmpfs_reg_resize(vp, length); - if (error == 0) { - VN_KNOTE(vp, NOTE_ATTRIB | (extended ? NOTE_EXTEND : 0)); + if (error == 0) node->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; - } out: tmpfs_update(vp, NULL, NULL, 0); diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c index 4652e6f97b48..f814a01b1ffd 100644 --- a/sys/fs/tmpfs/tmpfs_vfsops.c +++ b/sys/fs/tmpfs/tmpfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmpfs_vfsops.c,v 1.15 2006/10/12 01:32:14 christos Exp $ */ +/* $NetBSD: tmpfs_vfsops.c,v 1.16 2006/11/09 15:06:03 jmmv Exp $ */ /* * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. @@ -49,7 +49,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.15 2006/10/12 01:32:14 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.16 2006/11/09 15:06:03 jmmv Exp $"); #include #include @@ -237,6 +237,7 @@ tmpfs_unmount(struct mount *mp, int mntflags, struct lwp *l __unused) struct tmpfs_dirent *nde; nde = TAILQ_NEXT(de, td_entries); + KASSERT(de->td_node->tn_vnode == NULL); tmpfs_free_dirent(tmp, de, FALSE); de = nde; node->tn_size -= sizeof(struct tmpfs_dirent); diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 0675b110b6c4..8b1b54af0579 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: tmpfs_vnops.c,v 1.30 2006/11/07 14:08:13 jmmv Exp $ */ +/* $NetBSD: tmpfs_vnops.c,v 1.31 2006/11/09 15:06:03 jmmv Exp $ */ /* * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.30 2006/11/07 14:08:13 jmmv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.31 2006/11/09 15:06:03 jmmv Exp $"); #include #include @@ -630,6 +630,8 @@ tmpfs_write(void *v) if (error != 0) (void)tmpfs_reg_resize(vp, oldsize); + VN_KNOTE(vp, NOTE_WRITE); + out: KASSERT(VOP_ISLOCKED(vp)); KASSERT(IMPLIES(error == 0, uio->uio_resid == 0)); @@ -691,10 +693,6 @@ tmpfs_remove(void *v) * have to change the number of hard links of the directory. */ tmpfs_dir_detach(dvp, de); - /* Notify interested parties about the modification of dvp. - * The removal of vp is notified when it is reclaimed. */ - VN_KNOTE(dvp, NOTE_WRITE); - /* Free the directory entry we just deleted. Note that the node * referred by it will not be removed until the vnode is really * reclaimed. */ @@ -775,7 +773,6 @@ tmpfs_link(void *v) /* Insert the new directory entry into the appropriate directory. */ tmpfs_dir_attach(dvp, de); - VN_KNOTE(dvp, NOTE_WRITE); /* vp link count has changed, so update node times. */ node->tn_status |= TMPFS_NODE_CHANGED; @@ -952,8 +949,10 @@ tmpfs_rename(void *v) } /* Notify listeners of tdvp about the change in the directory (either - * because a new entry was added or because one was removed). */ + * because a new entry was added or because one was removed) and + * listeners of fvp about the rename. */ VN_KNOTE(tdvp, NOTE_WRITE); + VN_KNOTE(fvp, NOTE_RENAME); error = 0; @@ -1046,8 +1045,7 @@ tmpfs_rmdir(void *v) node->tn_spec.tn_dir.tn_parent->tn_status |= TMPFS_NODE_ACCESSED | \ TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; - /* Notify modification of parent directory and release it. */ - VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); + /* Release the parent. */ cache_purge(dvp); /* XXX Is this needed? */ vput(dvp); @@ -1256,9 +1254,6 @@ tmpfs_reclaim(void *v) node = VP_TO_TMPFS_NODE(vp); tmp = VFS_TO_TMPFS(vp->v_mount); - if (node->tn_links == 0) - VN_KNOTE(vp, NOTE_DELETE); - cache_purge(vp); tmpfs_free_vp(vp); diff --git a/sys/fs/tmpfs/tmpfs_vnops.h b/sys/fs/tmpfs/tmpfs_vnops.h index fc67f7a64931..0e8a00faccd4 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.h +++ b/sys/fs/tmpfs/tmpfs_vnops.h @@ -1,4 +1,4 @@ -/* $NetBSD: tmpfs_vnops.h,v 1.7 2005/12/03 17:34:44 christos Exp $ */ +/* $NetBSD: tmpfs_vnops.h,v 1.8 2006/11/09 15:06:03 jmmv Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ int tmpfs_write (void *); #define tmpfs_fcntl genfs_fcntl #define tmpfs_ioctl genfs_enoioctl #define tmpfs_poll genfs_poll -#define tmpfs_kqfilter genfs_eopnotsupp +#define tmpfs_kqfilter genfs_kqfilter #define tmpfs_revoke genfs_revoke #define tmpfs_mmap genfs_mmap int tmpfs_fsync (void *);