Unverified Commit be1ca3ee authored by Christian Brauner's avatar Christian Brauner
Browse files

selftests/statmount: add statmount_alloc() helper

Add a helper to allocate a statmount buffer and call statmount(). This
helper will be shared by multiple test suites that need to query mount
information via statmount().

Link: https://patch.msgid.link/20260122-work-fsmount-namespace-v1-5-5ef0a886e646@kernel.org


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent fc1a05de
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ static void dump_mounts(struct __test_metadata *_metadata, uint64_t mnt_ns_id)
				     STATMOUNT_MNT_BASIC |
				     STATMOUNT_FS_TYPE |
				     STATMOUNT_MNT_ROOT |
				     STATMOUNT_MNT_POINT);
				     STATMOUNT_MNT_POINT, 0);
		if (!sm) {
			TH_LOG("  [%zd] mnt_id %llu: statmount failed: %s",
			       i, (unsigned long long)list[i], strerror(errno));
@@ -746,7 +746,7 @@ TEST_F(open_tree_ns_userns, umount_fails_einval)
			const char *mnt_point;

			sm = statmount_alloc(list[i], new_ns_id,
					     STATMOUNT_MNT_POINT);
					     STATMOUNT_MNT_POINT, 0);
			if (!sm)
				_exit(11);

@@ -863,7 +863,7 @@ TEST_F(open_tree_ns_userns, umount_succeeds)
			const char *mnt_point;

			sm = statmount_alloc(list[i], new_ns_id,
					     STATMOUNT_MNT_POINT);
					     STATMOUNT_MNT_POINT, 0);
			if (!sm)
				_exit(11);

@@ -1003,7 +1003,7 @@ TEST_F(open_tree_ns_unbindable, recursive_skips_on_unbindable)
		struct statmount *sm;
		const char *mnt_point;

		sm = statmount_alloc(list[i], new_ns_id, STATMOUNT_MNT_POINT);
		sm = statmount_alloc(list[i], new_ns_id, STATMOUNT_MNT_POINT, 0);
		ASSERT_NE(sm, NULL) {
			TH_LOG("statmount_alloc failed for mnt_id %llu",
			       (unsigned long long)list[i]);
+51 −0
Original line number Diff line number Diff line
@@ -3,10 +3,14 @@
#ifndef __STATMOUNT_H
#define __STATMOUNT_H

#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <linux/mount.h>
#include <asm/unistd.h>

#define STATMOUNT_BUFSIZE (1 << 15)

#ifndef __NR_statmount
	#if defined __alpha__
		#define __NR_statmount 567
@@ -84,4 +88,51 @@ static inline ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
	return syscall(__NR_listmount, &req, list, num, flags);
}

static inline struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mnt_ns_id,
						 uint64_t mask, unsigned int flags)
{
	struct statmount *buf;
	size_t bufsize = STATMOUNT_BUFSIZE;
	int ret;

	for (;;) {
		buf = malloc(bufsize);
		if (!buf)
			return NULL;

		ret = statmount(mnt_id, mnt_ns_id, 0, mask, buf, bufsize, flags);
		if (ret == 0)
			return buf;

		free(buf);
		if (errno != EOVERFLOW)
			return NULL;

		bufsize <<= 1;
	}
}

static inline struct statmount *statmount_alloc_by_fd(int fd, uint64_t mask)
{
	struct statmount *buf;
	size_t bufsize = STATMOUNT_BUFSIZE;
	int ret;

	for (;;) {
		buf = malloc(bufsize);
		if (!buf)
			return NULL;

		ret = statmount(0, 0, fd, mask, buf, bufsize, STATMOUNT_BY_FD);
		if (ret == 0)
			return buf;

		free(buf);
		if (errno != EOVERFLOW)
			return NULL;

		bufsize <<= 1;
	}
}

#endif /* __STATMOUNT_H */
+3 −42
Original line number Diff line number Diff line
@@ -33,45 +33,6 @@ static const char *const known_fs[] = {
	"sysv", "tmpfs", "tracefs", "ubifs", "udf", "ufs", "v7", "vboxsf",
	"vfat", "virtiofs", "vxfs", "xenfs", "xfs", "zonefs", NULL };

static struct statmount *statmount_alloc(uint64_t mnt_id, int fd, uint64_t mask, unsigned int flags)
{
	size_t bufsize = 1 << 15;
	struct statmount *buf = NULL, *tmp = NULL;
	int tofree = 0;
	int ret;

	if (flags & STATMOUNT_BY_FD && fd < 0)
		return NULL;

	tmp = alloca(bufsize);

	for (;;) {
		if (flags & STATMOUNT_BY_FD)
			ret = statmount(0, 0, (uint32_t) fd, mask, tmp, bufsize, flags);
		else
			ret = statmount(mnt_id, 0, 0, mask, tmp, bufsize, flags);

		if (ret != -1)
			break;
		if (tofree)
			free(tmp);
		if (errno != EOVERFLOW)
			return NULL;
		bufsize <<= 1;
		tofree = 1;
		tmp = malloc(bufsize);
		if (!tmp)
			return NULL;
	}
	buf = malloc(tmp->size);
	if (buf)
		memcpy(buf, tmp, tmp->size);
	if (tofree)
		free(tmp);

	return buf;
}

static void write_file(const char *path, const char *val)
{
	int fd = open(path, O_WRONLY);
@@ -715,7 +676,7 @@ static void test_statmount_by_fd(void)
		goto err_fd;
	}

	sm = statmount_alloc(0, fd, STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT, STATMOUNT_BY_FD);
	sm = statmount_alloc_by_fd(fd, STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT);
	if (!sm) {
		ksft_test_result_fail("statmount by fd failed: %s\n", strerror(errno));
		goto err_chroot;
@@ -750,7 +711,7 @@ static void test_statmount_by_fd(void)
	}

	free(sm);
	sm = statmount_alloc(0, fd, STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT, STATMOUNT_BY_FD);
	sm = statmount_alloc_by_fd(fd, STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT);
	if (!sm) {
		ksft_test_result_fail("statmount by fd failed: %s\n", strerror(errno));
		goto err_fd;
@@ -844,7 +805,7 @@ static void test_statmount_by_fd_unmounted(void)
		goto err_fd;
	}

	sm = statmount_alloc(0, fd, STATMOUNT_MNT_POINT | STATMOUNT_MNT_ROOT, STATMOUNT_BY_FD);
	sm = statmount_alloc_by_fd(fd, STATMOUNT_MNT_POINT | STATMOUNT_MNT_ROOT);
	if (!sm) {
		ksft_test_result_fail("statmount by fd unmounted: %s\n",
				      strerror(errno));