File Index
Files and directories
Sign in
FILE

iterate_mntns.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c 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.