FILE
iterate_mntns.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c
1// SPDX-License-Identifier: GPL-2.0-or-later 2// Copyright (c) 2024 Christian Brauner <brauner@kernel.org> 3 4#define _GNU_SOURCE 5#include <fcntl.h> 6#include <linux/auto_dev-ioctl.h> 7#include <linux/errno.h> 8#include <sched.h> 9#include <stdio.h> 10#include <string.h> 11#include <sys/stat.h> 12#include <sys/mount.h> 13#include <unistd.h> 14 15#include "kselftest_harness.h" 16 17#define MNT_NS_COUNT 11 18#define MNT_NS_LAST_INDEX 10 19 20struct mnt_ns_info { 21 __u32 size; 22 __u32 nr_mounts; 23 __u64 mnt_ns_id; 24}; 25 26#define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */ 27 28/* Get information about namespace. */ 29#define NS_MNT_GET_INFO _IOR(0xb7, 10, struct mnt_ns_info) 30/* Get next namespace. */ 31#define NS_MNT_GET_NEXT _IOR(0xb7, 11, struct mnt_ns_info) 32/* Get previous namespace. */ 33#define NS_MNT_GET_PREV _IOR(0xb7, 12, struct mnt_ns_info) 34 35FIXTURE(iterate_mount_namespaces) { 36 int fd_mnt_ns[MNT_NS_COUNT]; 37 __u64 mnt_ns_id[MNT_NS_COUNT]; 38}; 39 40static inline bool mntns_in_list(__u64 *mnt_ns_id, struct mnt_ns_info *info) 41{ 42 for (int i = 0; i < MNT_NS_COUNT; i++) { 43 if (mnt_ns_id[i] == info->mnt_ns_id) 44 return true; 45 } 46 return false; 47} 48 49FIXTURE_SETUP(iterate_mount_namespaces) 50{ 51 for (int i = 0; i < MNT_NS_COUNT; i++) 52 self->fd_mnt_ns[i] = -EBADF; 53 54 for (int i = 0; i < MNT_NS_COUNT; i++) { 55 struct mnt_ns_info info = {}; 56 57 ASSERT_EQ(unshare(CLONE_NEWNS), 0); 58 self->fd_mnt_ns[i] = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC); 59 ASSERT_GE(self->fd_mnt_ns[i], 0); 60 ASSERT_EQ(ioctl(self->fd_mnt_ns[i], NS_MNT_GET_INFO, &info), 0); 61 self->mnt_ns_id[i] = info.mnt_ns_id; 62 } 63} 64 65FIXTURE_TEARDOWN(iterate_mount_namespaces) 66{ 67 for (int i = 0; i < MNT_NS_COUNT; i++) { 68 if (self->fd_mnt_ns[i] < 0) 69 continue; 70 ASSERT_EQ(close(self->fd_mnt_ns[i]), 0); 71 } 72} 73 74TEST_F(iterate_mount_namespaces, iterate_all_forward) 75{ 76 int fd_mnt_ns_cur, count = 0; 77 78 fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[0], F_DUPFD_CLOEXEC); 79 ASSERT_GE(fd_mnt_ns_cur, 0); 80 81 for (;;) { 82 struct mnt_ns_info info = {}; 83 int fd_mnt_ns_next; 84 85 fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info); 86 if (fd_mnt_ns_next < 0 && errno == ENOENT) 87 break; 88 if (mntns_in_list(self->mnt_ns_id, &info)) 89 count++; 90 ASSERT_GE(fd_mnt_ns_next, 0); 91 ASSERT_EQ(close(fd_mnt_ns_cur), 0); 92 fd_mnt_ns_cur = fd_mnt_ns_next; 93 } 94 ASSERT_EQ(count, MNT_NS_LAST_INDEX); 95} 96 97TEST_F(iterate_mount_namespaces, iterate_all_backwards) 98{ 99 int fd_mnt_ns_cur, count = 0; 100 101 fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[MNT_NS_LAST_INDEX], F_DUPFD_CLOEXEC); 102 ASSERT_GE(fd_mnt_ns_cur, 0); 103 104 for (;;) { 105 struct mnt_ns_info info = {}; 106 int fd_mnt_ns_prev; 107 108 fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info); 109 if (fd_mnt_ns_prev < 0 && errno == ENOENT) 110 break; 111 if (mntns_in_list(self->mnt_ns_id, &info)) 112 count++; 113 ASSERT_GE(fd_mnt_ns_prev, 0); 114 ASSERT_EQ(close(fd_mnt_ns_cur), 0); 115 fd_mnt_ns_cur = fd_mnt_ns_prev; 116 } 117 ASSERT_EQ(count, MNT_NS_LAST_INDEX); 118} 119 120TEST_F(iterate_mount_namespaces, iterate_forward) 121{ 122 int fd_mnt_ns_cur; 123 124 ASSERT_EQ(setns(self->fd_mnt_ns[0], CLONE_NEWNS), 0); 125 126 fd_mnt_ns_cur = self->fd_mnt_ns[0]; 127 for (int i = 1; i < MNT_NS_COUNT; i++) { 128 struct mnt_ns_info info = {}; 129 int fd_mnt_ns_next; 130 131 fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info); 132 ASSERT_GE(fd_mnt_ns_next, 0); 133 ASSERT_EQ(close(fd_mnt_ns_cur), 0); 134 fd_mnt_ns_cur = fd_mnt_ns_next; 135 } 136} 137 138TEST_F(iterate_mount_namespaces, iterate_backward) 139{ 140 int fd_mnt_ns_cur; 141 142 ASSERT_EQ(setns(self->fd_mnt_ns[MNT_NS_LAST_INDEX], CLONE_NEWNS), 0); 143 144 fd_mnt_ns_cur = self->fd_mnt_ns[MNT_NS_LAST_INDEX]; 145 for (int i = MNT_NS_LAST_INDEX - 1; i >= 0; i--) { 146 struct mnt_ns_info info = {}; 147 int fd_mnt_ns_prev; 148 149 fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info); 150 ASSERT_GE(fd_mnt_ns_prev, 0); 151 ASSERT_EQ(close(fd_mnt_ns_cur), 0); 152 fd_mnt_ns_cur = fd_mnt_ns_prev; 153 } 154} 155 156TEST_F(iterate_mount_namespaces, nfs_valid_ioctl) 157{ 158 ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_OPENMOUNT, NULL), 0); 159 ASSERT_EQ(errno, ENOTTY); 160 161 ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_CLOSEMOUNT, NULL), 0); 162 ASSERT_EQ(errno, ENOTTY); 163 164 ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_READY, NULL), 0); 165 ASSERT_EQ(errno, ENOTTY); 166} 167 168TEST_HARNESS_MAIN
~/
Read-only file preview.