[LTP] [PATCH 1/2] kernel/fs/fs-notify: fsnotify stress tests
Murphy Zhou
jencce.kernel@gmail.com
Tue Jan 25 03:47:18 CET 2022
Exercise fsnotify and inotify interfaces while IO going on.
Signed-off-by: Murphy Zhou <jencce.kernel@gmail.com>
---
testcases/kernel/fs/fs-notify/Makefile | 18 ++
.../fs/fs-notify/fanotify_flush_stress.c | 52 ++++
.../fs/fs-notify/fanotify_init_stress.c | 32 +++
.../fs/fs-notify/fanotify_mark_stress.c | 58 +++++
.../kernel/fs/fs-notify/fanotify_watch.c | 244 ++++++++++++++++++
testcases/kernel/fs/fs-notify/freadfile.c | 27 ++
.../kernel/fs/fs-notify/fsnotify-stress.sh | 64 +++++
testcases/kernel/fs/fs-notify/fwritefile.c | 27 ++
.../fs/fs-notify/inotify_add_rm_stress.c | 36 +++
.../kernel/fs/fs-notify/inotify_init_stress.c | 22 ++
.../fs/fs-notify/inotify_inmodify_stress.c | 17 ++
testcases/kernel/fs/fs-notify/inotify_watch.c | 98 +++++++
testcases/kernel/fs/fs-notify/readfile.c | 28 ++
testcases/kernel/fs/fs-notify/rw_files.sh | 90 +++++++
testcases/kernel/fs/fs-notify/writefile.c | 28 ++
15 files changed, 841 insertions(+)
create mode 100644 testcases/kernel/fs/fs-notify/Makefile
create mode 100644 testcases/kernel/fs/fs-notify/fanotify_flush_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/fanotify_init_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/fanotify_mark_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/fanotify_watch.c
create mode 100644 testcases/kernel/fs/fs-notify/freadfile.c
create mode 100755 testcases/kernel/fs/fs-notify/fsnotify-stress.sh
create mode 100644 testcases/kernel/fs/fs-notify/fwritefile.c
create mode 100644 testcases/kernel/fs/fs-notify/inotify_add_rm_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/inotify_init_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/inotify_inmodify_stress.c
create mode 100644 testcases/kernel/fs/fs-notify/inotify_watch.c
create mode 100644 testcases/kernel/fs/fs-notify/readfile.c
create mode 100755 testcases/kernel/fs/fs-notify/rw_files.sh
create mode 100644 testcases/kernel/fs/fs-notify/writefile.c
diff --git a/testcases/kernel/fs/fs-notify/Makefile b/testcases/kernel/fs/fs-notify/Makefile
new file mode 100644
index 000000000..328783942
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/Makefile
@@ -0,0 +1,18 @@
+#
+# kernel/fs/fs-notify testcases Makefile.
+#
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+BINARIES:=fanotify_flush_stress fanotify_init_stress \
+fanotify_mark_stress fanotify_watch inotify_watch \
+inotify_add_rm_stress inotify_init_stress inotify_inmodify_stress\
+writefile freadfile fwritefile readfile
+
+INSTALL_TARGETS := fsnotify-stress.sh $(BINARIES) rw_files.sh
+
+MAKE_TARGETS := $(BINARIES)
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/fs/fs-notify/fanotify_flush_stress.c b/testcases/kernel/fs/fs-notify/fanotify_flush_stress.c
new file mode 100644
index 000000000..493acfb56
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fanotify_flush_stress.c
@@ -0,0 +1,52 @@
+#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ char buf;
+ int fd;
+
+ /* Create the file descriptor for accessing the fanotify API */
+ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+ O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ perror("fanotify_init");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Loop marking all kinds of events and flush */
+ while (1) {
+
+ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+ FAN_ACCESS | FAN_MODIFY | FAN_OPEN_PERM | FAN_CLOSE |
+ FAN_OPEN | FAN_ACCESS_PERM | FAN_ONDIR |
+ FAN_EVENT_ON_CHILD, -1, argv[1]) == -1)
+
+ perror("fanotify_mark add");
+
+ if (fanotify_mark(fd, FAN_MARK_FLUSH | FAN_MARK_MOUNT,
+ 0, -1, argv[1]) == -1)
+ perror("fanotify_mark flush mount");
+
+ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+ FAN_ACCESS | FAN_MODIFY | FAN_OPEN_PERM | FAN_CLOSE |
+ FAN_OPEN | FAN_ACCESS_PERM | FAN_ONDIR |
+ FAN_EVENT_ON_CHILD, -1, argv[1]) == -1)
+
+ perror("fanotify_mark add");
+
+ if (fanotify_mark(fd, FAN_MARK_FLUSH, 0, -1, argv[1]) == -1)
+ perror("fanotify_mark flush");
+ }
+
+ close(fd);
+ exit(EXIT_SUCCESS);
+}
diff --git a/testcases/kernel/fs/fs-notify/fanotify_init_stress.c b/testcases/kernel/fs/fs-notify/fanotify_init_stress.c
new file mode 100644
index 000000000..d11924b57
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fanotify_init_stress.c
@@ -0,0 +1,32 @@
+#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+
+int main(int argc, char *argv[])
+{
+ char buf;
+ int fd;
+ while (1) {
+
+ /* Create the file descriptor for accessing the fanotify API */
+ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT |
+ FAN_NONBLOCK, O_RDONLY | O_LARGEFILE);
+ if (fd == -1)
+ perror("fanotify_init");
+
+ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+ FAN_ACCESS | FAN_MODIFY | FAN_OPEN_PERM |
+ FAN_CLOSE | FAN_OPEN | FAN_ACCESS_PERM |
+ FAN_ONDIR | FAN_EVENT_ON_CHILD, -1,
+ argv[1]) == -1)
+ perror("fanotify_mark");
+
+ close(fd);
+ }
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/testcases/kernel/fs/fs-notify/fanotify_mark_stress.c b/testcases/kernel/fs/fs-notify/fanotify_mark_stress.c
new file mode 100644
index 000000000..7f648e103
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fanotify_mark_stress.c
@@ -0,0 +1,58 @@
+#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+#include <string.h>
+
+void add_mark(int fd, uint64_t mask, char *path)
+{
+ if (fanotify_mark(fd, FAN_MARK_ADD, mask, -1, path) == -1)
+ perror("fanotify_mark add");
+}
+
+void remove_mark(int fd, uint64_t mask, char *path)
+{
+ if (fanotify_mark(fd, FAN_MARK_REMOVE, mask, -1, path) == -1)
+ perror("fanotify_mark remove");
+}
+
+int main(int argc, char *argv[])
+{
+ char buf;
+ int fd;
+ /* Create the file descriptor for accessing the fanotify API */
+ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+ O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ perror("fanotify_init");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Loop marking all kinds of events */
+ while (1) {
+ add_mark(fd, FAN_ACCESS, argv[1]);
+ remove_mark(fd, FAN_ACCESS, argv[1]);
+ add_mark(fd, FAN_MODIFY, argv[1]);
+ remove_mark(fd, FAN_MODIFY, argv[1]);
+ add_mark(fd, FAN_OPEN_PERM, argv[1]);
+ remove_mark(fd, FAN_OPEN_PERM, argv[1]);
+ add_mark(fd, FAN_CLOSE, argv[1]);
+ remove_mark(fd, FAN_CLOSE, argv[1]);
+ add_mark(fd, FAN_OPEN, argv[1]);
+ remove_mark(fd, FAN_OPEN, argv[1]);
+ add_mark(fd, FAN_ACCESS_PERM, argv[1]);
+ remove_mark(fd, FAN_ACCESS_PERM, argv[1]);
+ add_mark(fd, FAN_ONDIR, argv[1]);
+ remove_mark(fd, FAN_ONDIR, argv[1]);
+ add_mark(fd, FAN_EVENT_ON_CHILD, argv[1]);
+ remove_mark(fd, FAN_EVENT_ON_CHILD, argv[1]);
+ }
+
+ close(fd);
+ exit(EXIT_SUCCESS);
+}
diff --git a/testcases/kernel/fs/fs-notify/fanotify_watch.c b/testcases/kernel/fs/fs-notify/fanotify_watch.c
new file mode 100644
index 000000000..1028e0e30
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fanotify_watch.c
@@ -0,0 +1,244 @@
+/* Example in man 7 fanotify */
+
+#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+#include <string.h>
+
+/* get comm for pid from /proc/pid/comm */
+static char * get_comm_pid(unsigned int pid)
+{
+ char * proc_name;
+ char * comm;
+ int comm_fd, cnt;
+
+ proc_name = (char *)malloc(50);
+ if (proc_name != NULL)
+ sprintf(proc_name, "/proc/%u/comm\0", pid);
+ else
+ return NULL;
+
+ comm = (char *)malloc(50);
+ if (comm != NULL)
+ memset(comm, 0, 50);
+ else
+ return NULL;
+
+ comm_fd = open(proc_name, O_RDONLY);
+ if (comm_fd != -1) {
+ cnt = read(comm_fd, comm, 50);
+ if (cnt != -1) {
+ comm[cnt] = '\0';
+ close(comm_fd);
+ return comm;
+ }
+ close(comm_fd);
+ }
+
+ return NULL;
+}
+
+/* Read all available fanotify events from the file descriptor 'fd' */
+
+static void handle_events(int fd)
+{
+ const struct fanotify_event_metadata *metadata;
+ struct fanotify_event_metadata buf[200];
+ ssize_t len;
+ char path[PATH_MAX];
+ ssize_t path_len;
+ char procfd_path[PATH_MAX];
+ struct fanotify_response response;
+
+ /* Loop while events can be read from fanotify file descriptor */
+ for(;;) {
+
+ /* Read some events */
+ len = read(fd, (void *) &buf, sizeof(buf));
+ if (len == -1 && errno != EAGAIN) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Check if end of available data reached */
+ if (len <= 0)
+ break;
+
+ /* Point to the first event in the buffer */
+ metadata = buf;
+
+ /* Loop over all events in the buffer */
+ while (FAN_EVENT_OK(metadata, len)) {
+
+ /* Check that run-time and compile-time structures match */
+
+ if (metadata->vers != FANOTIFY_METADATA_VERSION) {
+ fprintf(stderr,
+ "Mismatch of fanotify metadata version.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* metadata->fd contains either FAN_NOFD, indicating a
+ queue overflow, or a file descriptor (a nonnegative
+ integer). Here, we simply ignore queue overflow. */
+
+ if (metadata->fd >= 0) {
+
+ /* Handle open permission event */
+ if (metadata->mask & FAN_OPEN_PERM) {
+ printf("FAN_OPEN_PERM: ");
+
+ /* Allow file to be opened */
+ response.fd = metadata->fd;
+ response.response = FAN_ALLOW;
+ write(fd, &response,
+ sizeof(struct fanotify_response));
+ }
+
+ /* Handle access permission event */
+ if (metadata->mask & FAN_ACCESS_PERM) {
+ printf("FAN_ACCESS_PERM: ");
+
+ /* Allow file to be accessed */
+ response.fd = metadata->fd;
+ response.response = FAN_ALLOW;
+ write(fd, &response,
+ sizeof(struct fanotify_response));
+ }
+
+ /* Handle closing of writable file event */
+ if (metadata->mask & FAN_CLOSE_WRITE)
+ printf("FAN_CLOSE_WRITE: ");
+
+ /* Handle closing of not writable file event */
+ if (metadata->mask & FAN_CLOSE_NOWRITE)
+ printf("FAN_CLOSE_NOWRITE: ");
+
+ /* Handle modify file event */
+ if (metadata->mask & FAN_MODIFY)
+ printf("FAN_MODIFY: ");
+
+ /* Handle open event */
+ if (metadata->mask & FAN_OPEN)
+ printf("FAN_OPEN: ");
+
+ /* Handle access event */
+ if (metadata->mask & FAN_ACCESS)
+ printf("FAN_ACCESS: ");
+
+ /* Handle access event */
+ if (metadata->mask & FAN_ONDIR)
+ printf("FAN_ONDIR: ");
+
+ /* Handle access event */
+ if (metadata->mask & FAN_EVENT_ON_CHILD)
+ printf("FAN_EVENT_ON_CHILD: ");
+
+ /* Retrieve/print the accessed file path*/
+ snprintf(procfd_path, sizeof(procfd_path),
+ "/proc/self/fd/%d", metadata->fd);
+ path_len = readlink(procfd_path, path,
+ sizeof(path) - 1);
+ if (path_len == -1) {
+ perror("readlink");
+ exit(EXIT_FAILURE);
+ }
+
+ path[path_len] = '\0';
+ printf("File %s.\t\t Comm %s", path,
+ get_comm_pid(metadata->pid));
+
+ /* Close the file descriptor of the event */
+
+ close(metadata->fd);
+ }
+
+ /* Advance to next event */
+ metadata = FAN_EVENT_NEXT(metadata, len);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char buf;
+ int fd, poll_num;
+ nfds_t nfds;
+ struct pollfd fds[2];
+ FILE *f;
+#if 0
+ /* Check mount point is supplied */
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ printf("%s on %s\n", argv[0], argv[1]);
+ fflush(stdout);
+ f = freopen("fanotify.log", "w+", stdout);
+ if (f == NULL) {
+ perror("freopen");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create the file descriptor for accessing the fanotify API */
+ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+ O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ perror("fanotify_init");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Mark the mount for:
+ - permission events before opening files
+ - notification events after closing a write-enabled
+ file descriptor */
+ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+ FAN_ACCESS | FAN_MODIFY | FAN_OPEN_PERM |
+ FAN_CLOSE | FAN_OPEN | FAN_ACCESS_PERM |
+ FAN_ONDIR | FAN_EVENT_ON_CHILD,
+ -1, argv[1]) == -1) {
+
+ perror("fanotify_mark");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Prepare for polling */
+ nfds = 1;
+
+ /* Fanotify input */
+ fds[0].fd = fd;
+ fds[0].events = POLLIN;
+
+ /* This is the loop to wait for incoming events */
+ printf("Listening for events.\n");
+ while (1) {
+ poll_num = poll(fds, nfds, -1);
+ if (poll_num == -1) {
+ if (errno == EINTR) /* Interrupted by a signal */
+ continue; /* Restart poll() */
+
+ perror("poll"); /* Unexpected error */
+ exit(EXIT_FAILURE);
+ }
+
+ if (poll_num > 0) {
+
+ if (fds[0].revents & POLLIN) {
+
+ /* Fanotify events are available */
+ handle_events(fd);
+ }
+ }
+ }
+
+ fclose(f);
+ printf("Listening for events stopped.\n");
+ exit(EXIT_SUCCESS);
+}
diff --git a/testcases/kernel/fs/fs-notify/freadfile.c b/testcases/kernel/fs/fs-notify/freadfile.c
new file mode 100644
index 000000000..24bf76bcd
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/freadfile.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv)
+{
+ int fd;
+ char buf[BUFSIZ];
+ FILE *f;
+
+ memset(buf, 1, BUFSIZ);
+ while(1) {
+ f = fopen(argv[1], "r+");
+ if (f == NULL) {
+ perror("freadfile fopen");
+ exit(EXIT_FAILURE);
+ }
+ fread(buf, sizeof(char), BUFSIZ, f);
+ usleep(1);
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/fsnotify-stress.sh b/testcases/kernel/fs/fs-notify/fsnotify-stress.sh
new file mode 100755
index 000000000..d6fd5482b
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fsnotify-stress.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+export TIMEOUT=10
+
+STRESSES="fanotify_flush_stress fanotify_init_stress \
+fanotify_mark_stress fanotify_watch inotify_watch \
+inotify_add_rm_stress inotify_init_stress inotify_inmodify_stress"
+IO_OPES="writefile freadfile fwritefile readfile"
+
+NR_CPUS=$(grep -c processor /proc/cpuinfo)
+[ $NR_CPUS -lt 4 ] && NR_CPUS=4
+
+function cleanup_processes()
+{
+ while ps -eo pid,comm | \
+ grep -q -E "fanotify|inotify|rw_files|readfile|writefile" ; do
+ killall rw_files.sh $STRESSES $IO_OPES > /dev/null 2>&1
+ sleep 1
+ done
+}
+
+function cleanup()
+{
+ sleep 3 # waiting possible unfinished processes
+ cleanup_processes
+ rm -f $STRESSES $IO_OPES fanotify.log inotify.log tmp
+ cd /
+ sync
+}
+
+function run_stress()
+{
+ local i j rcnt=0
+ echo -e "* CPU count: $NR_CPUS"
+ echo -e "* TIMEOUT for each subcase: $TIMEOUT"
+
+ echo -e "* Starting fsnotify stress on directory and regular file"
+ touch $TMPDIR/testfile
+ >tmp
+ for i in $STRESSES $IO_OPES rw_files.sh; do
+ for j in $STRESSES ; do
+ [ "$i" == "$j" ] && continue
+ # skip duplicate combinations
+ grep -w $j tmp | grep -qw $i && continue
+ echo -e "* Starting $i and $j, rcnt $rcnt"
+ ./$i $TMPDIR $TIMEOUT > /dev/null 2>&1 &
+ ./$i $TMPDIR/testfile $TIMEOUT > /dev/null 2>&1 &
+ ./$j $TMPDIR $TIMEOUT > /dev/null 2>&1 &
+ ./$j $TMPDIR/testfile $TIMEOUT > /dev/null 2>&1 &
+ sleep $TIMEOUT
+ cleanup_processes
+ echo -e "$i $j" >> tmp
+ ((rcnt++))
+ done
+ done
+}
+
+trap "cleanup; exit;" 2
+
+echo "***** Starting tests *****"
+run_stress
+
+echo -e "\n***** Cleanup fanotify inotify device *****"
+cleanup
diff --git a/testcases/kernel/fs/fs-notify/fwritefile.c b/testcases/kernel/fs/fs-notify/fwritefile.c
new file mode 100644
index 000000000..a2956d60b
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/fwritefile.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv)
+{
+ int fd;
+ char buf[BUFSIZ];
+ FILE *f;
+
+ memset(buf, 1, BUFSIZ);
+ while(1) {
+ f = fopen(argv[1], "w+");
+ if (f == NULL) {
+ perror("fwritefile fopen");
+ exit(EXIT_FAILURE);
+ }
+ fwrite(buf, sizeof(char), BUFSIZ, f);
+ usleep(1);
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/inotify_add_rm_stress.c b/testcases/kernel/fs/fs-notify/inotify_add_rm_stress.c
new file mode 100644
index 000000000..e88fc088e
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/inotify_add_rm_stress.c
@@ -0,0 +1,36 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/inotify.h>
+
+int main(int argc, char *argv[])
+{
+ int notify_fd;
+ int wd, ret;
+
+ notify_fd = inotify_init1(IN_CLOEXEC);
+ if (notify_fd == -1) {
+ perror("inotify_init1");
+ return -1;
+ }
+
+ while (1) {
+ wd = inotify_add_watch(notify_fd, argv[1],
+ IN_ACCESS | IN_ATTRIB | IN_CLOSE_WRITE |
+ IN_CLOSE_NOWRITE | IN_CREATE | IN_DELETE |
+ IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF |
+ IN_MOVED_FROM | IN_MOVED_TO | IN_OPEN);
+ if (wd < 0)
+ perror("inotify_add_watch");
+
+ ret = inotify_rm_watch(notify_fd, wd);
+ if (ret < 0)
+ perror("inotify_rm_watch");
+ }
+ close(notify_fd);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/inotify_init_stress.c b/testcases/kernel/fs/fs-notify/inotify_init_stress.c
new file mode 100644
index 000000000..62cb7c2e6
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/inotify_init_stress.c
@@ -0,0 +1,22 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/inotify.h>
+
+int main(int argc, char *argv[])
+{
+ int notify_fd;
+ int wd;
+
+ while (1) {
+ notify_fd = inotify_init1(IN_CLOEXEC);
+ if (notify_fd == -1)
+ perror("inotify_init1");
+ close(notify_fd);
+ }
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/inotify_inmodify_stress.c b/testcases/kernel/fs/fs-notify/inotify_inmodify_stress.c
new file mode 100644
index 000000000..546ccb76f
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/inotify_inmodify_stress.c
@@ -0,0 +1,17 @@
+#include <sys/inotify.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/*
+ * Calls inotify_rm_watch in a loop.
+ */
+int main(int argc, char **argv)
+{
+ int fd = inotify_init();
+ while (1) {
+ int wd = inotify_add_watch(fd, argv[1], IN_MODIFY);
+ inotify_rm_watch(fd, wd);
+ }
+ close(fd);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/inotify_watch.c b/testcases/kernel/fs/fs-notify/inotify_watch.c
new file mode 100644
index 000000000..b4b908b6b
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/inotify_watch.c
@@ -0,0 +1,98 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/inotify.h>
+
+int main(int argc, char *argv[])
+{
+ int notify_fd;
+ int wd, ret;
+ char *buf;
+ FILE *f;
+
+ f = freopen("inotify.log", "w+", stdout);
+ if (f == NULL) {
+ perror("freopen");
+ exit(EXIT_FAILURE);
+ }
+
+ buf = malloc(sizeof(struct inotify_event) + NAME_MAX + 1);
+ if (buf == NULL) {
+ perror("malloc");
+ return -1;
+ }
+
+ notify_fd = inotify_init1(IN_CLOEXEC);
+ if (notify_fd == -1) {
+ perror("inotify_init1");
+ return -1;
+ }
+
+ wd = inotify_add_watch(notify_fd, argv[1],
+ IN_ACCESS | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE |
+ IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY |
+ IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO | IN_OPEN);
+
+ if (wd < 0) {
+ perror("inotify_add_watch");
+ return -1;
+ }
+
+ while (ret = read(notify_fd, buf, NAME_MAX) != -1) {
+ struct inotify_event *ip = (struct inotify_event *)buf;
+ printf("name %s event ", ip->name);
+ switch (ip->mask) {
+ case IN_ACCESS:
+ printf("access\n");
+ break;
+ case IN_ATTRIB:
+ printf("attrib\n");
+ break;
+ case IN_CLOSE_WRITE:
+ printf("close write\n");
+ break;
+ case IN_CLOSE_NOWRITE:
+ printf("close nowrite\n");
+ break;
+ case IN_CREATE:
+ printf("create\n");
+ break;
+ case IN_DELETE:
+ printf("delete\n");
+ break;
+ case IN_DELETE_SELF:
+ printf("deleteself\n");
+ break;
+ case IN_MODIFY:
+ printf("modify\n");
+ break;
+ case IN_MOVE_SELF:
+ printf("move self\n");
+ break;
+ case IN_MOVED_FROM:
+ printf("move from\n");
+ break;
+ case IN_MOVED_TO:
+ printf("move to\n");
+ break;
+ case IN_OPEN:
+ printf("open\n");
+ break;
+ default:
+ printf("\n");
+ break;
+ };
+ }
+
+ ret = inotify_rm_watch(notify_fd, wd);
+ if (ret < 0)
+ perror("inotify_rm_watch");
+
+ fclose(f);
+ close(notify_fd);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/readfile.c b/testcases/kernel/fs/fs-notify/readfile.c
new file mode 100644
index 000000000..2ab1a3694
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/readfile.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv)
+{
+ int fd, ret;
+ char buf[BUFSIZ];
+
+ memset(buf, 1, BUFSIZ);
+ while (1) {
+ fd = open(argv[1], O_RDWR);
+ if (fd == -1) {
+ perror("readfile open");
+ exit(EXIT_FAILURE);
+ }
+ ret = read(fd, buf, BUFSIZ);
+ if (ret == -1)
+ perror("readfile read");
+ usleep(1);
+ }
+ close(fd);
+ return 0;
+}
diff --git a/testcases/kernel/fs/fs-notify/rw_files.sh b/testcases/kernel/fs/fs-notify/rw_files.sh
new file mode 100755
index 000000000..bb3387160
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/rw_files.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+TDIR=$1
+TIMEO=$2
+
+[ -z "$TDIR" ] && TDIR=/tmp/
+[ -d $TDIR ] || TDIR=/tmp/
+[ -z "$TIMEO" ] && TIMEO=1m
+
+[ ! -d $TDIR ] && exit
+
+function add_files()
+{
+ local i=0
+
+ while true ; do
+
+ touch f-$i
+ ln -s f-$i f-$i-sym
+ ln f-$i f-$i-hdl
+
+ mkdir d-$i
+
+ mknod c-$i c 1 2
+ mknod b-$i b 1 2
+ mknod p-$i p
+
+ ((i++))
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+}
+
+function mv_files()
+{
+ local i=0
+
+ while true ; do
+
+ mv -f f-$i f-$i-rename
+ mv -f f-$i-rename f-$i
+ ((i++))
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+}
+
+function read_files()
+{
+ while true ; do
+
+ find .
+ cat f-*
+ ls d-*
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+}
+
+function write_files()
+{
+ while true ; do
+
+ for j in f-* d-* c-* b-* p-* ; do
+ echo 1 > $j
+ echo 2 >> $j
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+}
+
+function rm_files()
+{
+ while true ; do
+
+ rm -rf d-* f-* c-* b-* p-*
+ sleep 3
+ [ -e stoptest ] && { echo $FUNCNAME; exit; }
+ done
+}
+
+pushd $TDIR > /dev/null 2>&1
+rm -f stoptest
+add_files > /dev/null 2>&1 &
+mv_files > /dev/null 2>&1 &
+read_files > /dev/null 2>&1 &
+write_files > /dev/null 2>&1 &
+rm_files > /dev/null 2>&1 &
+popd > /dev/null 2>&1
+
+sleep $TIMEO
+touch $TDIR/stoptest
diff --git a/testcases/kernel/fs/fs-notify/writefile.c b/testcases/kernel/fs/fs-notify/writefile.c
new file mode 100644
index 000000000..9025b5d95
--- /dev/null
+++ b/testcases/kernel/fs/fs-notify/writefile.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv)
+{
+ int fd, ret;
+ char buf[BUFSIZ];
+
+ memset(buf, 1, BUFSIZ);
+ while (1) {
+ fd = open(argv[1], O_RDWR);
+ if (fd == -1) {
+ perror("writefile open");
+ exit(EXIT_FAILURE);
+ }
+ ret = write(fd, buf, BUFSIZ);
+ if (ret == -1)
+ perror("writefile write");
+ usleep(1);
+ }
+ close(fd);
+ return 0;
+}
--
2.31.1
More information about the ltp
mailing list