From cae73d3bdce5dc6cdbf454fcc37a6fb2f025151e Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 13 Dec 2024 00:03:46 +0100 Subject: seltests: move nsfs into filesystems subfolder I'm going to be adding new tests for it and it belongs under filesystem selftests. Link: https://lore.kernel.org/r/20241213-work-mount-rbtree-lockless-v3-7-6e3cdaf9b280@kernel.org Reviewed-by: Jeff Layton Signed-off-by: Christian Brauner --- .../testing/selftests/filesystems/nsfs/.gitignore | 3 + tools/testing/selftests/filesystems/nsfs/Makefile | 6 ++ tools/testing/selftests/filesystems/nsfs/config | 3 + tools/testing/selftests/filesystems/nsfs/owner.c | 92 ++++++++++++++++++++++ tools/testing/selftests/filesystems/nsfs/pidns.c | 79 +++++++++++++++++++ tools/testing/selftests/nsfs/.gitignore | 3 - tools/testing/selftests/nsfs/Makefile | 6 -- tools/testing/selftests/nsfs/config | 3 - tools/testing/selftests/nsfs/owner.c | 92 ---------------------- tools/testing/selftests/nsfs/pidns.c | 79 ------------------- 10 files changed, 183 insertions(+), 183 deletions(-) create mode 100644 tools/testing/selftests/filesystems/nsfs/.gitignore create mode 100644 tools/testing/selftests/filesystems/nsfs/Makefile create mode 100644 tools/testing/selftests/filesystems/nsfs/config create mode 100644 tools/testing/selftests/filesystems/nsfs/owner.c create mode 100644 tools/testing/selftests/filesystems/nsfs/pidns.c delete mode 100644 tools/testing/selftests/nsfs/.gitignore delete mode 100644 tools/testing/selftests/nsfs/Makefile delete mode 100644 tools/testing/selftests/nsfs/config delete mode 100644 tools/testing/selftests/nsfs/owner.c delete mode 100644 tools/testing/selftests/nsfs/pidns.c (limited to 'tools') diff --git a/tools/testing/selftests/filesystems/nsfs/.gitignore b/tools/testing/selftests/filesystems/nsfs/.gitignore new file mode 100644 index 000000000000..ed79ebdf286e --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +owner +pidns diff --git a/tools/testing/selftests/filesystems/nsfs/Makefile b/tools/testing/selftests/filesystems/nsfs/Makefile new file mode 100644 index 000000000000..c2f3ca6e488e --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +TEST_GEN_PROGS := owner pidns + +CFLAGS := -Wall -Werror + +include ../../lib.mk diff --git a/tools/testing/selftests/filesystems/nsfs/config b/tools/testing/selftests/filesystems/nsfs/config new file mode 100644 index 000000000000..598d0a225fc9 --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/config @@ -0,0 +1,3 @@ +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_PID_NS=y diff --git a/tools/testing/selftests/filesystems/nsfs/owner.c b/tools/testing/selftests/filesystems/nsfs/owner.c new file mode 100644 index 000000000000..96a976c74550 --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/owner.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NSIO 0xb7 +#define NS_GET_USERNS _IO(NSIO, 0x1) + +#define pr_err(fmt, ...) \ + ({ \ + fprintf(stderr, "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + 1; \ + }) + +int main(int argc, char *argvp[]) +{ + int pfd[2], ns, uns, init_uns; + struct stat st1, st2; + char path[128]; + pid_t pid; + char c; + + if (pipe(pfd)) + return 1; + + pid = fork(); + if (pid < 0) + return pr_err("fork"); + if (pid == 0) { + prctl(PR_SET_PDEATHSIG, SIGKILL); + if (unshare(CLONE_NEWUTS | CLONE_NEWUSER)) + return pr_err("unshare"); + close(pfd[0]); + close(pfd[1]); + while (1) + sleep(1); + return 0; + } + close(pfd[1]); + if (read(pfd[0], &c, 1) != 0) + return pr_err("Unable to read from pipe"); + close(pfd[0]); + + snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid); + ns = open(path, O_RDONLY); + if (ns < 0) + return pr_err("Unable to open %s", path); + + uns = ioctl(ns, NS_GET_USERNS); + if (uns < 0) + return pr_err("Unable to get an owning user namespace"); + + if (fstat(uns, &st1)) + return pr_err("fstat"); + + snprintf(path, sizeof(path), "/proc/%d/ns/user", pid); + if (stat(path, &st2)) + return pr_err("stat"); + + if (st1.st_ino != st2.st_ino) + return pr_err("NS_GET_USERNS returned a wrong namespace"); + + init_uns = ioctl(uns, NS_GET_USERNS); + if (uns < 0) + return pr_err("Unable to get an owning user namespace"); + + if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + + if (unshare(CLONE_NEWUSER)) + return pr_err("unshare"); + + if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + + kill(pid, SIGKILL); + wait(NULL); + return 0; +} diff --git a/tools/testing/selftests/filesystems/nsfs/pidns.c b/tools/testing/selftests/filesystems/nsfs/pidns.c new file mode 100644 index 000000000000..e3c772c6a7c7 --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/pidns.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define pr_err(fmt, ...) \ + ({ \ + fprintf(stderr, "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + 1; \ + }) + +#define NSIO 0xb7 +#define NS_GET_USERNS _IO(NSIO, 0x1) +#define NS_GET_PARENT _IO(NSIO, 0x2) + +#define __stack_aligned__ __attribute__((aligned(16))) +struct cr_clone_arg { + char stack[128] __stack_aligned__; + char stack_ptr[]; +}; + +static int child(void *args) +{ + prctl(PR_SET_PDEATHSIG, SIGKILL); + while (1) + sleep(1); + exit(0); +} + +int main(int argc, char *argv[]) +{ + char *ns_strs[] = {"pid", "user"}; + char path[] = "/proc/0123456789/ns/pid"; + struct cr_clone_arg ca; + struct stat st1, st2; + int ns, pns, i; + pid_t pid; + + pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL); + if (pid < 0) + return pr_err("clone"); + + for (i = 0; i < 2; i++) { + snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]); + ns = open(path, O_RDONLY); + if (ns < 0) + return pr_err("Unable to open %s", path); + + pns = ioctl(ns, NS_GET_PARENT); + if (pns < 0) + return pr_err("Unable to get a parent pidns"); + + snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]); + if (stat(path, &st2)) + return pr_err("Unable to stat %s", path); + if (fstat(pns, &st1)) + return pr_err("Unable to stat the parent pidns"); + if (st1.st_ino != st2.st_ino) + return pr_err("NS_GET_PARENT returned a wrong namespace"); + + if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + } + + kill(pid, SIGKILL); + wait(NULL); + return 0; +} diff --git a/tools/testing/selftests/nsfs/.gitignore b/tools/testing/selftests/nsfs/.gitignore deleted file mode 100644 index ed79ebdf286e..000000000000 --- a/tools/testing/selftests/nsfs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -owner -pidns diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile deleted file mode 100644 index dd9bd50b7b93..000000000000 --- a/tools/testing/selftests/nsfs/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -TEST_GEN_PROGS := owner pidns - -CFLAGS := -Wall -Werror - -include ../lib.mk diff --git a/tools/testing/selftests/nsfs/config b/tools/testing/selftests/nsfs/config deleted file mode 100644 index 598d0a225fc9..000000000000 --- a/tools/testing/selftests/nsfs/config +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_USER_NS=y -CONFIG_UTS_NS=y -CONFIG_PID_NS=y diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c deleted file mode 100644 index 96a976c74550..000000000000 --- a/tools/testing/selftests/nsfs/owner.c +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NSIO 0xb7 -#define NS_GET_USERNS _IO(NSIO, 0x1) - -#define pr_err(fmt, ...) \ - ({ \ - fprintf(stderr, "%s:%d:" fmt ": %m\n", \ - __func__, __LINE__, ##__VA_ARGS__); \ - 1; \ - }) - -int main(int argc, char *argvp[]) -{ - int pfd[2], ns, uns, init_uns; - struct stat st1, st2; - char path[128]; - pid_t pid; - char c; - - if (pipe(pfd)) - return 1; - - pid = fork(); - if (pid < 0) - return pr_err("fork"); - if (pid == 0) { - prctl(PR_SET_PDEATHSIG, SIGKILL); - if (unshare(CLONE_NEWUTS | CLONE_NEWUSER)) - return pr_err("unshare"); - close(pfd[0]); - close(pfd[1]); - while (1) - sleep(1); - return 0; - } - close(pfd[1]); - if (read(pfd[0], &c, 1) != 0) - return pr_err("Unable to read from pipe"); - close(pfd[0]); - - snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid); - ns = open(path, O_RDONLY); - if (ns < 0) - return pr_err("Unable to open %s", path); - - uns = ioctl(ns, NS_GET_USERNS); - if (uns < 0) - return pr_err("Unable to get an owning user namespace"); - - if (fstat(uns, &st1)) - return pr_err("fstat"); - - snprintf(path, sizeof(path), "/proc/%d/ns/user", pid); - if (stat(path, &st2)) - return pr_err("stat"); - - if (st1.st_ino != st2.st_ino) - return pr_err("NS_GET_USERNS returned a wrong namespace"); - - init_uns = ioctl(uns, NS_GET_USERNS); - if (uns < 0) - return pr_err("Unable to get an owning user namespace"); - - if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM) - return pr_err("Don't get EPERM"); - - if (unshare(CLONE_NEWUSER)) - return pr_err("unshare"); - - if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM) - return pr_err("Don't get EPERM"); - if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM) - return pr_err("Don't get EPERM"); - - kill(pid, SIGKILL); - wait(NULL); - return 0; -} diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c deleted file mode 100644 index e3c772c6a7c7..000000000000 --- a/tools/testing/selftests/nsfs/pidns.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define pr_err(fmt, ...) \ - ({ \ - fprintf(stderr, "%s:%d:" fmt ": %m\n", \ - __func__, __LINE__, ##__VA_ARGS__); \ - 1; \ - }) - -#define NSIO 0xb7 -#define NS_GET_USERNS _IO(NSIO, 0x1) -#define NS_GET_PARENT _IO(NSIO, 0x2) - -#define __stack_aligned__ __attribute__((aligned(16))) -struct cr_clone_arg { - char stack[128] __stack_aligned__; - char stack_ptr[]; -}; - -static int child(void *args) -{ - prctl(PR_SET_PDEATHSIG, SIGKILL); - while (1) - sleep(1); - exit(0); -} - -int main(int argc, char *argv[]) -{ - char *ns_strs[] = {"pid", "user"}; - char path[] = "/proc/0123456789/ns/pid"; - struct cr_clone_arg ca; - struct stat st1, st2; - int ns, pns, i; - pid_t pid; - - pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL); - if (pid < 0) - return pr_err("clone"); - - for (i = 0; i < 2; i++) { - snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]); - ns = open(path, O_RDONLY); - if (ns < 0) - return pr_err("Unable to open %s", path); - - pns = ioctl(ns, NS_GET_PARENT); - if (pns < 0) - return pr_err("Unable to get a parent pidns"); - - snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]); - if (stat(path, &st2)) - return pr_err("Unable to stat %s", path); - if (fstat(pns, &st1)) - return pr_err("Unable to stat the parent pidns"); - if (st1.st_ino != st2.st_ino) - return pr_err("NS_GET_PARENT returned a wrong namespace"); - - if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM) - return pr_err("Don't get EPERM"); - } - - kill(pid, SIGKILL); - wait(NULL); - return 0; -} -- cgit v1.2.3 From 9d87b1067382be1ede395c9246ff1ee0519f0c64 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 13 Dec 2024 00:03:47 +0100 Subject: selftests: add tests for mntns iteration Test that forward and backward iteration works correctly. Link: https://lore.kernel.org/r/20241213-work-mount-rbtree-lockless-v3-8-6e3cdaf9b280@kernel.org Reviewed-by: Jeff Layton Signed-off-by: Christian Brauner --- .../testing/selftests/filesystems/nsfs/.gitignore | 1 + tools/testing/selftests/filesystems/nsfs/Makefile | 2 +- .../selftests/filesystems/nsfs/iterate_mntns.c | 149 +++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/filesystems/nsfs/iterate_mntns.c (limited to 'tools') diff --git a/tools/testing/selftests/filesystems/nsfs/.gitignore b/tools/testing/selftests/filesystems/nsfs/.gitignore index ed79ebdf286e..92a8249006d1 100644 --- a/tools/testing/selftests/filesystems/nsfs/.gitignore +++ b/tools/testing/selftests/filesystems/nsfs/.gitignore @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only owner pidns +iterate_mntns diff --git a/tools/testing/selftests/filesystems/nsfs/Makefile b/tools/testing/selftests/filesystems/nsfs/Makefile index c2f3ca6e488e..231aaa7dfd95 100644 --- a/tools/testing/selftests/filesystems/nsfs/Makefile +++ b/tools/testing/selftests/filesystems/nsfs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -TEST_GEN_PROGS := owner pidns +TEST_GEN_PROGS := owner pidns iterate_mntns CFLAGS := -Wall -Werror diff --git a/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c b/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c new file mode 100644 index 000000000000..457cf76f3c5f --- /dev/null +++ b/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2024 Christian Brauner + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include "../../kselftest_harness.h" + +#define MNT_NS_COUNT 11 +#define MNT_NS_LAST_INDEX 10 + +struct mnt_ns_info { + __u32 size; + __u32 nr_mounts; + __u64 mnt_ns_id; +}; + +#define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */ + +/* Get information about namespace. */ +#define NS_MNT_GET_INFO _IOR(0xb7, 10, struct mnt_ns_info) +/* Get next namespace. */ +#define NS_MNT_GET_NEXT _IOR(0xb7, 11, struct mnt_ns_info) +/* Get previous namespace. */ +#define NS_MNT_GET_PREV _IOR(0xb7, 12, struct mnt_ns_info) + +FIXTURE(iterate_mount_namespaces) { + int fd_mnt_ns[MNT_NS_COUNT]; + __u64 mnt_ns_id[MNT_NS_COUNT]; +}; + +FIXTURE_SETUP(iterate_mount_namespaces) +{ + for (int i = 0; i < MNT_NS_COUNT; i++) + self->fd_mnt_ns[i] = -EBADF; + + /* + * Creating a new user namespace let's us guarantee that we only see + * mount namespaces that we did actually create. + */ + ASSERT_EQ(unshare(CLONE_NEWUSER), 0); + + for (int i = 0; i < MNT_NS_COUNT; i++) { + struct mnt_ns_info info = {}; + + ASSERT_EQ(unshare(CLONE_NEWNS), 0); + self->fd_mnt_ns[i] = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC); + ASSERT_GE(self->fd_mnt_ns[i], 0); + ASSERT_EQ(ioctl(self->fd_mnt_ns[i], NS_MNT_GET_INFO, &info), 0); + self->mnt_ns_id[i] = info.mnt_ns_id; + } +} + +FIXTURE_TEARDOWN(iterate_mount_namespaces) +{ + for (int i = 0; i < MNT_NS_COUNT; i++) { + if (self->fd_mnt_ns[i] < 0) + continue; + ASSERT_EQ(close(self->fd_mnt_ns[i]), 0); + } +} + +TEST_F(iterate_mount_namespaces, iterate_all_forward) +{ + int fd_mnt_ns_cur, count = 0; + + fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[0], F_DUPFD_CLOEXEC); + ASSERT_GE(fd_mnt_ns_cur, 0); + + for (;; count++) { + struct mnt_ns_info info = {}; + int fd_mnt_ns_next; + + fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info); + if (fd_mnt_ns_next < 0 && errno == ENOENT) + break; + ASSERT_GE(fd_mnt_ns_next, 0); + ASSERT_EQ(close(fd_mnt_ns_cur), 0); + fd_mnt_ns_cur = fd_mnt_ns_next; + } + ASSERT_EQ(count, MNT_NS_LAST_INDEX); +} + +TEST_F(iterate_mount_namespaces, iterate_all_backwards) +{ + int fd_mnt_ns_cur, count = 0; + + fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[MNT_NS_LAST_INDEX], F_DUPFD_CLOEXEC); + ASSERT_GE(fd_mnt_ns_cur, 0); + + for (;; count++) { + struct mnt_ns_info info = {}; + int fd_mnt_ns_prev; + + fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info); + if (fd_mnt_ns_prev < 0 && errno == ENOENT) + break; + ASSERT_GE(fd_mnt_ns_prev, 0); + ASSERT_EQ(close(fd_mnt_ns_cur), 0); + fd_mnt_ns_cur = fd_mnt_ns_prev; + } + ASSERT_EQ(count, MNT_NS_LAST_INDEX); +} + +TEST_F(iterate_mount_namespaces, iterate_forward) +{ + int fd_mnt_ns_cur; + + ASSERT_EQ(setns(self->fd_mnt_ns[0], CLONE_NEWNS), 0); + + fd_mnt_ns_cur = self->fd_mnt_ns[0]; + for (int i = 1; i < MNT_NS_COUNT; i++) { + struct mnt_ns_info info = {}; + int fd_mnt_ns_next; + + fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info); + ASSERT_GE(fd_mnt_ns_next, 0); + ASSERT_EQ(close(fd_mnt_ns_cur), 0); + fd_mnt_ns_cur = fd_mnt_ns_next; + ASSERT_EQ(info.mnt_ns_id, self->mnt_ns_id[i]); + } +} + +TEST_F(iterate_mount_namespaces, iterate_backward) +{ + int fd_mnt_ns_cur; + + ASSERT_EQ(setns(self->fd_mnt_ns[MNT_NS_LAST_INDEX], CLONE_NEWNS), 0); + + fd_mnt_ns_cur = self->fd_mnt_ns[MNT_NS_LAST_INDEX]; + for (int i = MNT_NS_LAST_INDEX - 1; i >= 0; i--) { + struct mnt_ns_info info = {}; + int fd_mnt_ns_prev; + + fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info); + ASSERT_GE(fd_mnt_ns_prev, 0); + ASSERT_EQ(close(fd_mnt_ns_cur), 0); + fd_mnt_ns_cur = fd_mnt_ns_prev; + ASSERT_EQ(info.mnt_ns_id, self->mnt_ns_id[i]); + } +} + +TEST_HARNESS_MAIN -- cgit v1.2.3 From d3238e8944e2bd1d6a006d35850e86fa80469751 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 13 Dec 2024 00:03:48 +0100 Subject: selftests: remove unneeded include The pidfd header will be included in a sample program and this pulls in all the mount definitions that would be causing problems. Link: https://lore.kernel.org/r/20241213-work-mount-rbtree-lockless-v3-9-6e3cdaf9b280@kernel.org Reviewed-by: Jeff Layton Signed-off-by: Christian Brauner --- tools/testing/selftests/pidfd/pidfd.h | 1 - 1 file changed, 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h index 88d6830ee004..3a96053e52e7 100644 --- a/tools/testing/selftests/pidfd/pidfd.h +++ b/tools/testing/selftests/pidfd/pidfd.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 3ab8a0b2a0ff1038412cd644b51714e35970f415 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 15 Dec 2024 21:17:07 +0100 Subject: selftests: add listmount() iteration tests Add a forward and backward iteration test for listmount(). Link: https://lore.kernel.org/r/20241215-vfs-6-14-mount-work-v1-3-fd55922c4af8@kernel.org Signed-off-by: Christian Brauner --- .../selftests/filesystems/statmount/Makefile | 2 +- .../filesystems/statmount/listmount_test.c | 66 ++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/filesystems/statmount/listmount_test.c (limited to 'tools') diff --git a/tools/testing/selftests/filesystems/statmount/Makefile b/tools/testing/selftests/filesystems/statmount/Makefile index 3af3136e35a4..14ee91a41650 100644 --- a/tools/testing/selftests/filesystems/statmount/Makefile +++ b/tools/testing/selftests/filesystems/statmount/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) -TEST_GEN_PROGS := statmount_test statmount_test_ns +TEST_GEN_PROGS := statmount_test statmount_test_ns listmount_test include ../../lib.mk diff --git a/tools/testing/selftests/filesystems/statmount/listmount_test.c b/tools/testing/selftests/filesystems/statmount/listmount_test.c new file mode 100644 index 000000000000..15f0834f7557 --- /dev/null +++ b/tools/testing/selftests/filesystems/statmount/listmount_test.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (c) 2024 Christian Brauner + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include "statmount.h" +#include "../../kselftest_harness.h" + +#ifndef LISTMOUNT_REVERSE +#define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */ +#endif + +#define LISTMNT_BUFFER 10 + +/* Check that all mount ids are in increasing order. */ +TEST(listmount_forward) +{ + uint64_t list[LISTMNT_BUFFER], last_mnt_id = 0; + + for (;;) { + ssize_t nr_mounts; + + nr_mounts = listmount(LSMT_ROOT, 0, last_mnt_id, + list, LISTMNT_BUFFER, 0); + ASSERT_GE(nr_mounts, 0); + if (nr_mounts == 0) + break; + + for (size_t cur = 0; cur < nr_mounts; cur++) { + if (cur < nr_mounts - 1) + ASSERT_LT(list[cur], list[cur + 1]); + last_mnt_id = list[cur]; + } + } +} + +/* Check that all mount ids are in decreasing order. */ +TEST(listmount_backward) +{ + uint64_t list[LISTMNT_BUFFER], last_mnt_id = 0; + + for (;;) { + ssize_t nr_mounts; + + nr_mounts = listmount(LSMT_ROOT, 0, last_mnt_id, + list, LISTMNT_BUFFER, LISTMOUNT_REVERSE); + ASSERT_GE(nr_mounts, 0); + if (nr_mounts == 0) + break; + + for (size_t cur = 0; cur < nr_mounts; cur++) { + if (cur < nr_mounts - 1) + ASSERT_GT(list[cur], list[cur + 1]); + last_mnt_id = list[cur]; + } + } +} + +TEST_HARNESS_MAIN -- cgit v1.2.3