From: Jinseok Kim <always.starving0@gmail.com>
To: shuah@kernel.org
Cc: Jan Kara <jack@suse.cz>, Amir Goldstein <amir73il@gmail.com>,
Matthew Bobrowski <repnop@google.com>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-fsdevel@vger.kernel.org
Subject: [RFC PATCH] selftests: fanotify: Add basic create/modify/delete event test
Date: Wed, 4 Feb 2026 03:15:43 +0900 [thread overview]
Message-ID: <20260203181549.21750-1-always.starving0@gmail.com> (raw)
Hello,
Currently there are almost no automated selftests for fanotify notification
events in tools/testing/selftests/ (only mount namespace
related tests exist).
This patch adds a very basic selftest that exercises three fundamental
fanotify events:
- FAN_CREATE (file creation)
- FAN_MODIFY (file content modification via write())
- FAN_DELETE (file removal)
The test
- creates a test file, appends data, and removes it
- verifies that corresponding events are received and the masks contain
the expected bits (0x100, 0x2, 0x200)
Test TAP output:
ok 1 FAN_CREATE detected
ok 2 FAN_MODIFY detected
ok 3 FAN_DELETE detected
# PASSED: 1 / 1 tests passed.
This is intentionally kept minimal as a starting point.
Future work ideas (not in this patch):
- Test permission events
- Test rename/move events
- Verify file names
- Run under different filesystems
Any feedback on the direction, style, or additional test cases
would be greatly appreciated.
Thanks,
Jinseok.
Signed-off-by: Jinseok Kim <always.starving0@gmail.com>
---
tools/testing/selftests/filesystems/Makefile | 7 +
.../selftests/filesystems/fanotify_basic.c | 122 ++++++++++++++++++
2 files changed, 129 insertions(+)
create mode 100644 tools/testing/selftests/filesystems/Makefile
create mode 100644 tools/testing/selftests/filesystems/fanotify_basic.c
diff --git a/tools/testing/selftests/filesystems/Makefile b/tools/testing/selftests/filesystems/Makefile
new file mode 100644
index 0000000..c0e0242
--- /dev/null
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += $(KHDR_INCLUDES)
+TEST_GEN_PROGS := devpts_pts file_stressor anon_inode_test kernfs_test fclog fanotify_basic
+TEST_GEN_PROGS_EXTENDED := dnotify_test
+
+include ../lib.mk
diff --git a/tools/testing/selftests/filesystems/fanotify_basic.c b/tools/testing/selftests/filesystems/fanotify_basic.c
new file mode 100644
index 0000000..4a4fbb4
--- /dev/null
+++ b/tools/testing/selftests/filesystems/fanotify_basic.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/fanotify.h>
+#include <linux/fanotify.h>
+#include "../kselftest_harness.h"
+#include "wrappers.h"
+
+static void create_file(const char *filename)
+{
+ int fd;
+ int ret;
+
+ fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd == -1)
+ ksft_exit_fail_msg("(create)open failed: %s\n", strerror(errno));
+ ret = write(fd, "create_file", 11);
+ if (ret == -1)
+ ksft_exit_fail_msg("(create) writing failed: %s\n", strerror(errno));
+ close(fd);
+}
+
+static void modify_file(const char *filename)
+{
+ int fd;
+ int ret;
+
+ fd = open(filename, O_RDWR);
+ if (fd == -1)
+ ksft_exit_fail_msg("(modify)open failed :%s\n", strerror(errno));
+ if (lseek(fd, 0, SEEK_END) < 0)
+ ksft_exit_fail_msg("(modify)lseek failed");
+ ret = write(fd, "modify_file", 11);
+ if (ret == -1)
+ ksft_exit_fail_msg("(modify)write failed :%s\n", strerror(errno));
+ if (fsync(fd) == -1)
+ ksft_exit_fail_msg("(modify)fsync failed: %s\n", strerror(errno));
+
+ close(fd);
+}
+
+TEST(fanotify_cud_test)
+{
+ int fan_fd;
+ char buf[4096];
+ int ret;
+ ssize_t len;
+ struct fanotify_event_metadata *meta;
+
+ fan_fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, O_RDONLY);
+ ASSERT_GE(fan_fd, 0)
+ TH_LOG("fanotify_init failed: %s", strerror(errno));
+
+ ret = fanotify_mark(fan_fd, FAN_MARK_ADD,
+ FAN_EVENT_ON_CHILD | FAN_CREATE |
+ FAN_MODIFY | FAN_DELETE,
+ AT_FDCWD, "/tmp");
+ ASSERT_GE(ret, 0)
+ TH_LOG("fanotify_mark failed: %s", strerror(errno));
+
+ // FAN_CREATE Test
+ create_file("/tmp/fanotify_test");
+ len = read(fan_fd, buf, sizeof(buf));
+ ASSERT_GT(len, 0)
+ TH_LOG("No event after create_file");
+
+ meta = (void *)buf;
+ if (FAN_EVENT_OK(meta, len)) {
+ TH_LOG("Event after create: mask = 0x%llx, pid=%d",
+ (unsigned long long)meta->mask, meta->pid);
+ if (meta->mask & FAN_CREATE)
+ ksft_test_result_pass("FAN_CREATE detected\n");
+ else
+ TH_LOG("FAN_CREATE missing");
+ } else
+ ksft_test_result_fail("Invalid event metadata after create\n");
+
+ // FAN_MODIFY Test
+ modify_file("/tmp/fanotify_test");
+ len = read(fan_fd, buf, sizeof(buf));
+ ASSERT_GT(len, 0)
+ TH_LOG("No event after modify_file");
+
+ meta = (void *)buf;
+ if (FAN_EVENT_OK(meta, len)) {
+ TH_LOG("Event after modify: mask = 0x%llx, pid=%d",
+ (unsigned long long)meta->mask, meta->pid);
+ if (meta->mask & FAN_MODIFY)
+ ksft_test_result_pass("FAN_MODIFY detected\n");
+ else
+ ksft_test_result_fail("FAN_MODIFY missing\n");
+ } else
+ ksft_test_result_fail("Invalid event metadata after modify\n");
+
+ // FAN_DELETE
+ ASSERT_EQ(unlink("/tmp/fanotify_test"), 0)
+ TH_LOG("unlink failed: %s", strerror(errno));
+
+ len = read(fan_fd, buf, sizeof(buf));
+ ASSERT_GT(len, 0)
+ TH_LOG("No event after unlink");
+
+ meta = (void *)buf;
+ if (FAN_EVENT_OK(meta, len)) {
+ TH_LOG("Event after delete: mask = 0x%llx, pid=%d",
+ (unsigned long long)meta->mask, meta->pid);
+ if (meta->mask & FAN_DELETE)
+ ksft_test_result_pass("FAN_DELETE detected\n");
+ else
+ ksft_test_result_fail("FAN_DELETE missing\n");
+ } else
+ ksft_test_result_fail("Invalid event metadata after delete\n");
+
+ // Clean up
+ if (fan_fd >= 0) {
+ fanotify_mark(fan_fd, FAN_MARK_REMOVE, 0, AT_FDCWD, ".");
+ close(fan_fd);
+ }
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
next reply other threads:[~2026-02-03 18:16 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-03 18:15 Jinseok Kim [this message]
2026-02-04 12:56 ` [RFC PATCH] selftests: fanotify: Add basic create/modify/delete event test Jan Kara
2026-02-05 10:04 ` [RFC PATCH] selftests: fanotify: Add basic create/modify/delete event Jinseok Kim
2026-02-05 11:34 ` Amir Goldstein
2026-02-05 12:55 ` Jinseok Kim
2026-02-05 12:21 ` Jan Kara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260203181549.21750-1-always.starving0@gmail.com \
--to=always.starving0@gmail.com \
--cc=amir73il@gmail.com \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=repnop@google.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox