[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <dnncglg3x26gdsshcniw5yb4l2zlxz6qcwjqyekkpngb6v26q4@ftqnoe5eeapy>
Date: Wed, 4 Feb 2026 13:56:28 +0100
From: Jan Kara <jack@...e.cz>
To: Jinseok Kim <always.starving0@...il.com>
Cc: shuah@...nel.org, Jan Kara <jack@...e.cz>,
Amir Goldstein <amir73il@...il.com>, Matthew Bobrowski <repnop@...gle.com>,
linux-kernel@...r.kernel.org, linux-kselftest@...r.kernel.org, linux-fsdevel@...r.kernel.org
Subject: Re: [RFC PATCH] selftests: fanotify: Add basic create/modify/delete
event test
Hello!
On Wed 04-02-26 03:15:43, Jinseok Kim wrote:
> Currently there are almost no automated selftests for fanotify notification
> events in tools/testing/selftests/ (only mount namespace
> related tests exist).
Thanks for the patch but we have a very comprehensive tests for inotify and
fanotify in LTP so I don't see a reason to duplicate those inside the
kernel...
Honza
>
> 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@...il.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
--
Jan Kara <jack@...e.com>
SUSE Labs, CR
Powered by blists - more mailing lists