Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154984970
D56639.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D56639.diff
View Options
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -968,6 +968,7 @@
struct vnode *vp;
struct null_node *xp;
struct vnode *lowervp;
+ short flags;
vp = ap->a_vp;
xp = VTONULL(vp);
@@ -997,6 +998,17 @@
else if (vp->v_writecount < 0)
vp->v_writecount = 0;
+ /*
+ * Undo the effects of null_copy_inotify(): setting VIRF_INOTIFY* causes
+ * the VFS to invoke VOP_INOTIFY on the marked vnode, and for nullfs
+ * vnodes this is bypassed to the lower vnode. The inotify watch holds
+ * a ref on the lower vnode, but not the upper vnode, so VOP_INOTIFY
+ * must not be called on the upper vnode after this point.
+ */
+ flags = vn_irflag_read(vp) & (VIRF_INOTIFY | VIRF_INOTIFY_PARENT);
+ if (flags != 0)
+ vn_irflag_unset_locked(vp, flags);
+
VI_UNLOCK(vp);
if ((xp->null_flags & NULLV_NOUNLOCK) != 0)
diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c
--- a/sys/kern/vfs_inotify.c
+++ b/sys/kern/vfs_inotify.c
@@ -889,10 +889,6 @@
void
vn_inotify_revoke(struct vnode *vp)
{
- if (vp->v_pollinfo == NULL) {
- /* This is a nullfs vnode which shadows a watched vnode. */
- return;
- }
inotify_log(vp, NULL, 0, IN_UNMOUNT, 0);
}
diff --git a/tests/sys/kern/inotify_test.c b/tests/sys/kern/inotify_test.c
--- a/tests/sys/kern/inotify_test.c
+++ b/tests/sys/kern/inotify_test.c
@@ -392,6 +392,116 @@
}
}
+/*
+ * Watch a file in a nullfs mount, and remove it from the lower mount. Make
+ * sure that we get an IN_DELETE_SELF event and that the watch is removed.
+ */
+ATF_TC_WITH_CLEANUP(inotify_nullfs_remove);
+ATF_TC_HEAD(inotify_nullfs_remove, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(inotify_nullfs_remove, tc)
+{
+ char dir[PATH_MAX], path[PATH_MAX], *p;
+ int error, fd, ifd, wd;
+
+ strlcpy(dir, "./test.XXXXXX", sizeof(dir));
+ p = mkdtemp(dir);
+ ATF_REQUIRE(p == dir);
+
+ error = mkdir("./mnt", 0755);
+ ATF_REQUIRE(error == 0);
+
+ /* Mount the testdir onto ./mnt. */
+ mount_nullfs("./mnt", dir);
+
+ snprintf(path, sizeof(path), "%s/file", dir);
+ fd = open(path, O_RDWR | O_CREAT, 0644);
+ ATF_REQUIRE(fd != -1);
+ close_checked(fd);
+
+ ifd = inotify(IN_NONBLOCK);
+ wd = inotify_add_watch(ifd, "./mnt/file", IN_DELETE_SELF);
+ ATF_REQUIRE(wd != -1);
+
+ error = unlink(path);
+ ATF_REQUIRE(error == 0);
+
+ consume_event(ifd, wd, IN_DELETE_SELF, 0, NULL);
+ consume_event(ifd, wd, 0, IN_IGNORED, NULL);
+
+ close_inotify(ifd);
+}
+ATF_TC_CLEANUP(inotify_nullfs_remove, tc)
+{
+ int error;
+
+ error = unmount("./mnt", 0);
+ if (error != 0) {
+ perror("unmount");
+ exit(1);
+ }
+}
+
+/*
+ * Exercise a scenario where a watched lower vnode is deleted by a rename. The
+ * deletion causes the upper vnode to be reclaimed, and after that point it
+ * should stop trying to forward events back to the (now detached) lower vnode.
+ */
+ATF_TC_WITH_CLEANUP(inotify_nullfs_rename);
+ATF_TC_HEAD(inotify_nullfs_rename, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(inotify_nullfs_rename, tc)
+{
+ char dir[PATH_MAX], path1[PATH_MAX], path2[PATH_MAX], *p;
+ int error, fd, ifd, wd;
+
+ strlcpy(dir, "./test.XXXXXX", sizeof(dir));
+ p = mkdtemp(dir);
+ ATF_REQUIRE(p == dir);
+
+ error = mkdir("./mnt", 0755);
+ ATF_REQUIRE(error == 0);
+
+ /* Mount the testdir onto ./mnt. */
+ mount_nullfs("./mnt", dir);
+
+ ifd = inotify(IN_NONBLOCK);
+
+ /* Create two files, they will be renamed in the upper layer. */
+ snprintf(path1, sizeof(path1), "%s/file1", dir);
+ fd = open(path1, O_RDWR | O_CREAT, 0644);
+ ATF_REQUIRE(fd != -1);
+ close_checked(fd);
+ snprintf(path2, sizeof(path2), "%s/file2", dir);
+ fd = open(path2, O_RDWR | O_CREAT, 0644);
+ ATF_REQUIRE(fd != -1);
+ close_checked(fd);
+
+ wd = inotify_add_watch(ifd, "./mnt/file1", IN_DELETE_SELF);
+ ATF_REQUIRE(wd != -1);
+ error = rename("./mnt/file2", "./mnt/file1");
+ ATF_REQUIRE(error == 0);
+
+ consume_event(ifd, wd, IN_DELETE_SELF, 0, NULL);
+ consume_event(ifd, wd, 0, IN_IGNORED, NULL);
+
+ close_inotify(ifd);
+}
+ATF_TC_CLEANUP(inotify_nullfs_rename, tc)
+{
+ int error;
+
+ error = unmount("./mnt", 0);
+ if (error != 0) {
+ perror("unmount");
+ exit(1);
+ }
+}
+
/*
* Make sure that exceeding max_events pending events results in an overflow
* event.
@@ -878,6 +988,8 @@
ATF_TP_ADD_TC(tp, inotify_coalesce);
ATF_TP_ADD_TC(tp, inotify_mask_create);
ATF_TP_ADD_TC(tp, inotify_nullfs);
+ ATF_TP_ADD_TC(tp, inotify_nullfs_remove);
+ ATF_TP_ADD_TC(tp, inotify_nullfs_rename);
ATF_TP_ADD_TC(tp, inotify_queue_overflow);
/* Tests for the various inotify event types. */
ATF_TP_ADD_TC(tp, inotify_event_access_file);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 1, 11:57 AM (11 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32575332
Default Alt Text
D56639.diff (4 KB)
Attached To
Mode
D56639: nullfs: Clear inotify flags during reclaim
Attached
Detach File
Event Timeline
Log In to Comment