linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/3] ovl: specify layers via file descriptors
@ 2024-10-11 15:43 Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 1/3] " Christian Brauner
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Christian Brauner @ 2024-10-11 15:43 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein
  Cc: Josef Bacik, linux-fsdevel, linux-unionfs, Christian Brauner

Hey,

Currently overlayfs only allows specifying layers through path names.
This is inconvenient for users such as systemd that want to assemble an
overlayfs mount purely based on file descriptors.

When porting overlayfs to the new mount api I already provided patches
for this but we decided to keep this work separate. This is a revamp of
the patchset as the use-case has become more urgent.

This introduces the new mount options:

lowerdir_fd+
datadir_fd+
upperdir_fd
workdir_fd

which can be used as follows:

fsconfig(fd_overlay, FSCONFIG_SET_FD, "upperdir_fd+", NULL, fd_upper);
fsconfig(fd_overlay, FSCONFIG_SET_FD, "workdir_fd+", NULL, fd_work);
fsconfig(fd_overlay, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, fd_lower1);
fsconfig(fd_overlay, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, fd_lower2);

The selftest contains an example for this.

The mount api doesn't allow overloading of mount option parameters
(except for strings and flags). Making this work for arbitrary
parameters would be quite ugly or file descriptors would have to be
special cased. Neither is very appealing. I do prefer the *_fd mount
options because they aren't ambiguous.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
Christian Brauner (3):
      ovl: specify layers via file descriptors
      selftests: use shared header
      selftests: add overlayfs fd mounting selftests

 fs/overlayfs/params.c                              | 132 +++++++++++++++++----
 .../selftests/filesystems/overlayfs/.gitignore     |   1 +
 .../selftests/filesystems/overlayfs/Makefile       |   2 +-
 .../selftests/filesystems/overlayfs/dev_in_maps.c  |  27 +----
 .../filesystems/overlayfs/set_layers_via_fds.c     | 122 +++++++++++++++++++
 .../selftests/filesystems/overlayfs/wrappers.h     |  47 ++++++++
 6 files changed, 281 insertions(+), 50 deletions(-)
---
base-commit: 8cf0b93919e13d1e8d4466eb4080a4c4d9d66d7b
change-id: 20241011-work-overlayfs-dbcfa9223e87


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH RFC 1/3] ovl: specify layers via file descriptors
  2024-10-11 15:43 [PATCH RFC 0/3] ovl: specify layers via file descriptors Christian Brauner
@ 2024-10-11 15:43 ` Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 2/3] selftests: use shared header Christian Brauner
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Christian Brauner @ 2024-10-11 15:43 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein
  Cc: Josef Bacik, linux-fsdevel, linux-unionfs, Christian Brauner

Currently overlayfs only allows specifying layers through path names.
This is inconvenient for users such as systemd that want to assemble an
overlayfs mount purely based on file descriptors.

This introduces the new mount options:

    lowerdir_fd+
    datadir_fd+
    upperdir_fd
    workdir_fd

which can be used as follows:

    fsconfig(fd_overlay, FSCONFIG_SET_FD, "upperdir_fd+", NULL, fd_upper);
    fsconfig(fd_overlay, FSCONFIG_SET_FD, "workdir_fd+",  NULL, fd_work);
    fsconfig(fd_overlay, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, fd_lower1);
    fsconfig(fd_overlay, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, fd_lower2);

Since the mount api doesn't allow overloading of mount option parameters
(except for strings and flags). Making this work for arbitrary
parameters would be quite ugly or file descriptors would have to be
special cased. Neither is very appealing. I do prefer the *_fd mount
options because they aren't ambiguous.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/overlayfs/params.c | 132 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 109 insertions(+), 23 deletions(-)

diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
index e42546c6c5dfbea930414856d791e3e4424a999e..2da7f231401ef034bb62d72a5d34f4a7e9179f8b 100644
--- a/fs/overlayfs/params.c
+++ b/fs/overlayfs/params.c
@@ -59,6 +59,10 @@ enum ovl_opt {
 	Opt_metacopy,
 	Opt_verity,
 	Opt_volatile,
+	Opt_lowerdir_add_fd,
+	Opt_datadir_add_fd,
+	Opt_upperdir_fd,
+	Opt_workdir_fd,
 };
 
 static const struct constant_table ovl_parameter_bool[] = {
@@ -155,6 +159,10 @@ const struct fs_parameter_spec ovl_parameter_spec[] = {
 	fsparam_enum("metacopy",            Opt_metacopy, ovl_parameter_bool),
 	fsparam_enum("verity",              Opt_verity, ovl_parameter_verity),
 	fsparam_flag("volatile",            Opt_volatile),
+	fsparam_fd("lowerdir_fd+",          Opt_lowerdir_add_fd),
+	fsparam_fd("datadir_fd+",           Opt_datadir_add_fd),
+	fsparam_fd("upperdir_fd",           Opt_upperdir_fd),
+	fsparam_fd("workdir_fd",            Opt_workdir_fd),
 	{}
 };
 
@@ -343,19 +351,27 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
 
 	switch (layer) {
 	case Opt_workdir:
+		fallthrough;
+	case Opt_workdir_fd:
 		swap(config->workdir, *pname);
 		swap(ctx->work, *path);
 		break;
 	case Opt_upperdir:
+		fallthrough;
+	case Opt_upperdir_fd:
 		swap(config->upperdir, *pname);
 		swap(ctx->upper, *path);
 		break;
 	case Opt_datadir_add:
+		fallthrough;
+	case Opt_datadir_add_fd:
 		ctx->nr_data++;
 		fallthrough;
 	case Opt_lowerdir:
 		fallthrough;
 	case Opt_lowerdir_add:
+		fallthrough;
+	case Opt_lowerdir_add_fd:
 		WARN_ON(ctx->nr >= ctx->capacity);
 		l = &ctx->lower[ctx->nr++];
 		memset(l, 0, sizeof(*l));
@@ -367,43 +383,96 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
 	}
 }
 
-static int ovl_parse_layer(struct fs_context *fc, const char *layer_name, enum ovl_opt layer)
+static inline bool is_upper_layer(enum ovl_opt layer)
 {
-	char *name = kstrdup(layer_name, GFP_KERNEL);
-	bool upper = (layer == Opt_upperdir || layer == Opt_workdir);
-	struct path path;
-	int err;
+	return layer == Opt_upperdir || layer == Opt_upperdir_fd ||
+	       layer == Opt_workdir || layer == Opt_workdir_fd;
+}
+
+static inline bool is_layer_fd(enum ovl_opt layer)
+{
+	return layer == Opt_upperdir_fd || layer == Opt_workdir_fd ||
+	       layer == Opt_lowerdir_add_fd || layer == Opt_datadir_add_fd;
+}
+
+/* Handle non-file descriptor-based layer options that require path lookup. */
+static inline int ovl_kern_path(const char *layer_name, struct path *layer_path,
+				enum ovl_opt layer)
+{
+	switch (layer) {
+	case Opt_upperdir:
+		fallthrough;
+	case Opt_workdir:
+		fallthrough;
+	case Opt_lowerdir:
+		return ovl_mount_dir(layer_name, layer_path);
+	case Opt_lowerdir_add:
+		fallthrough;
+	case Opt_datadir_add:
+		return ovl_mount_dir_noesc(layer_name, layer_path);
+	default:
+		WARN_ON_ONCE(true);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ovl_do_parse_layer(struct fs_context *fc, const char *layer_name,
+			      struct path *layer_path, enum ovl_opt layer)
+{
+	char *name __free(kfree) = kstrdup(layer_name, GFP_KERNEL);
+	bool upper;
+	int err = 0;
 
 	if (!name)
 		return -ENOMEM;
 
-	if (upper || layer == Opt_lowerdir)
-		err = ovl_mount_dir(name, &path);
-	else
-		err = ovl_mount_dir_noesc(name, &path);
-	if (err)
-		goto out_free;
-
-	err = ovl_mount_dir_check(fc, &path, layer, name, upper);
+	upper = is_upper_layer(layer);
+	err = ovl_mount_dir_check(fc, layer_path, layer, name, upper);
 	if (err)
-		goto out_put;
+		return err;
 
 	if (!upper) {
 		err = ovl_ctx_realloc_lower(fc);
 		if (err)
-			goto out_put;
+			return err;
 	}
 
 	/* Store the user provided path string in ctx to show in mountinfo */
-	ovl_add_layer(fc, layer, &path, &name);
-
-out_put:
-	path_put(&path);
-out_free:
-	kfree(name);
+	ovl_add_layer(fc, layer, layer_path, &name);
 	return err;
 }
 
+static int ovl_parse_layer(struct fs_context *fc, struct fs_parameter *param,
+			   enum ovl_opt layer)
+{
+	struct path path __free(path_put) = {};
+	char *buf __free(kfree) = NULL;
+	char *layer_name;
+	int err = 0;
+
+	if (is_layer_fd(layer)) {
+		buf = kmalloc(PATH_MAX, GFP_KERNEL_ACCOUNT);
+		if (!buf)
+			return -ENOMEM;
+
+		path = param->file->f_path;
+		path_get(&path);
+
+		layer_name = d_path(&path, buf, PATH_MAX);
+		if (IS_ERR(layer_name))
+			return PTR_ERR(layer_name);
+	} else {
+		layer_name = param->string;
+		err = ovl_kern_path(layer_name, &path, layer);
+	}
+	if (err)
+		return err;
+
+	return ovl_do_parse_layer(fc, layer_name, &path, layer);
+}
+
 static void ovl_reset_lowerdirs(struct ovl_fs_context *ctx)
 {
 	struct ovl_fs_context_layer *l = ctx->lower;
@@ -474,7 +543,13 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
 
 	iter = dup;
 	for (nr = 0; nr < nr_lower; nr++) {
-		err = ovl_parse_layer(fc, iter, Opt_lowerdir);
+		struct path path __free(path_put) = {};
+
+		err = ovl_kern_path(iter, &path, Opt_lowerdir);
+		if (err)
+			goto out_err;
+
+		err = ovl_do_parse_layer(fc, iter, &path, Opt_lowerdir);
 		if (err)
 			goto out_err;
 
@@ -552,10 +627,21 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
 		err = ovl_parse_param_lowerdir(param->string, fc);
 		break;
 	case Opt_lowerdir_add:
+		fallthrough;
 	case Opt_datadir_add:
+		fallthrough;
 	case Opt_upperdir:
+		fallthrough;
 	case Opt_workdir:
-		err = ovl_parse_layer(fc, param->string, opt);
+		fallthrough;
+	case Opt_lowerdir_add_fd:
+		fallthrough;
+	case Opt_datadir_add_fd:
+		fallthrough;
+	case Opt_upperdir_fd:
+		fallthrough;
+	case Opt_workdir_fd:
+		err = ovl_parse_layer(fc, param, opt);
 		break;
 	case Opt_default_permissions:
 		config->default_permissions = true;

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH RFC 2/3] selftests: use shared header
  2024-10-11 15:43 [PATCH RFC 0/3] ovl: specify layers via file descriptors Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 1/3] " Christian Brauner
@ 2024-10-11 15:43 ` Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 3/3] selftests: add overlayfs fd mounting selftests Christian Brauner
  2024-10-11 15:52 ` [PATCH RFC 0/3] ovl: specify layers via file descriptors Miklos Szeredi
  3 siblings, 0 replies; 6+ messages in thread
From: Christian Brauner @ 2024-10-11 15:43 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein
  Cc: Josef Bacik, linux-fsdevel, linux-unionfs, Christian Brauner

So that we don't have to redefine the same system calls over and over.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 .../selftests/filesystems/overlayfs/dev_in_maps.c  | 27 +-------------
 .../selftests/filesystems/overlayfs/wrappers.h     | 43 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c b/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c
index 2862aae58b79acbe175ab6b36b42798bb99a2225..3b796264223f81fc753d0adaeccc04077023520b 100644
--- a/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c
+++ b/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c
@@ -17,32 +17,7 @@
 
 #include "../../kselftest.h"
 #include "log.h"
-
-static int sys_fsopen(const char *fsname, unsigned int flags)
-{
-	return syscall(__NR_fsopen, fsname, flags);
-}
-
-static int sys_fsconfig(int fd, unsigned int cmd, const char *key, const char *value, int aux)
-{
-	return syscall(__NR_fsconfig, fd, cmd, key, value, aux);
-}
-
-static int sys_fsmount(int fd, unsigned int flags, unsigned int attr_flags)
-{
-	return syscall(__NR_fsmount, fd, flags, attr_flags);
-}
-static int sys_mount(const char *src, const char *tgt, const char *fst,
-		unsigned long flags, const void *data)
-{
-	return syscall(__NR_mount, src, tgt, fst, flags, data);
-}
-static int sys_move_mount(int from_dfd, const char *from_pathname,
-			  int to_dfd, const char *to_pathname,
-			  unsigned int flags)
-{
-	return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags);
-}
+#include "wrappers.h"
 
 static long get_file_dev_and_inode(void *addr, struct statx *stx)
 {
diff --git a/tools/testing/selftests/filesystems/overlayfs/wrappers.h b/tools/testing/selftests/filesystems/overlayfs/wrappers.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f99e10f7f018fd9a7be5263f68d34807da4c53c
--- /dev/null
+++ b/tools/testing/selftests/filesystems/overlayfs/wrappers.h
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+#ifndef __SELFTEST_OVERLAYFS_WRAPPERS_H__
+#define __SELFTEST_OVERLAYFS_WRAPPERS_H__
+
+#define _GNU_SOURCE
+
+#include <linux/types.h>
+#include <linux/mount.h>
+#include <sys/syscall.h>
+
+static inline int sys_fsopen(const char *fsname, unsigned int flags)
+{
+	return syscall(__NR_fsopen, fsname, flags);
+}
+
+static inline int sys_fsconfig(int fd, unsigned int cmd, const char *key,
+			       const char *value, int aux)
+{
+	return syscall(__NR_fsconfig, fd, cmd, key, value, aux);
+}
+
+static inline int sys_fsmount(int fd, unsigned int flags,
+			      unsigned int attr_flags)
+{
+	return syscall(__NR_fsmount, fd, flags, attr_flags);
+}
+
+static inline int sys_mount(const char *src, const char *tgt, const char *fst,
+			    unsigned long flags, const void *data)
+{
+	return syscall(__NR_mount, src, tgt, fst, flags, data);
+}
+
+static inline int sys_move_mount(int from_dfd, const char *from_pathname,
+				 int to_dfd, const char *to_pathname,
+				 unsigned int flags)
+{
+	return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd,
+		       to_pathname, flags);
+}
+
+#endif

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH RFC 3/3] selftests: add overlayfs fd mounting selftests
  2024-10-11 15:43 [PATCH RFC 0/3] ovl: specify layers via file descriptors Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 1/3] " Christian Brauner
  2024-10-11 15:43 ` [PATCH RFC 2/3] selftests: use shared header Christian Brauner
@ 2024-10-11 15:43 ` Christian Brauner
  2024-10-11 15:52 ` [PATCH RFC 0/3] ovl: specify layers via file descriptors Miklos Szeredi
  3 siblings, 0 replies; 6+ messages in thread
From: Christian Brauner @ 2024-10-11 15:43 UTC (permalink / raw)
  To: Miklos Szeredi, Amir Goldstein
  Cc: Josef Bacik, linux-fsdevel, linux-unionfs, Christian Brauner

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 .../selftests/filesystems/overlayfs/.gitignore     |   1 +
 .../selftests/filesystems/overlayfs/Makefile       |   2 +-
 .../filesystems/overlayfs/set_layers_via_fds.c     | 122 +++++++++++++++++++++
 .../selftests/filesystems/overlayfs/wrappers.h     |   4 +
 4 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/filesystems/overlayfs/.gitignore b/tools/testing/selftests/filesystems/overlayfs/.gitignore
index 52ae618fdd980ee22424d35d79f077077b132401..e23a18c8b37f2cdbb121496b1df1faffd729ad79 100644
--- a/tools/testing/selftests/filesystems/overlayfs/.gitignore
+++ b/tools/testing/selftests/filesystems/overlayfs/.gitignore
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 dev_in_maps
+set_layers_via_fds
diff --git a/tools/testing/selftests/filesystems/overlayfs/Makefile b/tools/testing/selftests/filesystems/overlayfs/Makefile
index 56b2b48a765b1d6706faee14616597ed0315f267..e8d1adb021af44588dd7af1049de66833bb584ce 100644
--- a/tools/testing/selftests/filesystems/overlayfs/Makefile
+++ b/tools/testing/selftests/filesystems/overlayfs/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-TEST_GEN_PROGS := dev_in_maps
+TEST_GEN_PROGS := dev_in_maps set_layers_via_fds
 
 CFLAGS := -Wall -Werror
 
diff --git a/tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c b/tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c
new file mode 100644
index 0000000000000000000000000000000000000000..1796da8c2350f5063172a7cd591e5324f87a4c38
--- /dev/null
+++ b/tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#define __SANE_USERSPACE_TYPES__ // Use ll64
+
+#include <fcntl.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <unistd.h>
+
+#include "../../kselftest_harness.h"
+#include "log.h"
+#include "wrappers.h"
+
+FIXTURE(set_layers_via_fds) {
+};
+
+FIXTURE_SETUP(set_layers_via_fds)
+{
+	ASSERT_EQ(mkdir("/set_layers_via_fds", 0755), 0);
+}
+
+FIXTURE_TEARDOWN(set_layers_via_fds)
+{
+	umount2("/set_layers_via_fds", 0);
+	ASSERT_EQ(rmdir("/set_layers_via_fds"), 0);
+}
+
+TEST_F(set_layers_via_fds, set_layers_via_fds)
+{
+	int fd_context, fd_tmpfs, fd_overlay;
+	int layer_fds[5] = { -EBADF, -EBADF, -EBADF, -EBADF, -EBADF };
+	bool layers_found[5] = { false, false, false, false, false };
+	size_t len = 0;
+	char *line = NULL;
+	FILE *f_mountinfo;
+
+	ASSERT_EQ(unshare(CLONE_NEWNS), 0);
+	ASSERT_EQ(sys_mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL), 0);
+
+	fd_context = sys_fsopen("tmpfs", 0);
+	ASSERT_GE(fd_context, 0);
+
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
+	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
+	ASSERT_GE(fd_tmpfs, 0);
+	ASSERT_EQ(close(fd_context), 0);
+
+	ASSERT_EQ(mkdirat(fd_tmpfs, "w", 0755), 0);
+	ASSERT_EQ(mkdirat(fd_tmpfs, "u", 0755), 0);
+	ASSERT_EQ(mkdirat(fd_tmpfs, "l1", 0755), 0);
+	ASSERT_EQ(mkdirat(fd_tmpfs, "l2", 0755), 0);
+	ASSERT_EQ(mkdirat(fd_tmpfs, "l3", 0755), 0);
+
+	layer_fds[0] = openat(fd_tmpfs, "w", O_DIRECTORY);
+	ASSERT_GE(layer_fds[0], 0);
+
+	layer_fds[1] = openat(fd_tmpfs, "u", O_DIRECTORY);
+	ASSERT_GE(layer_fds[1], 0);
+
+	layer_fds[2] = openat(fd_tmpfs, "l1", O_DIRECTORY);
+	ASSERT_GE(layer_fds[2], 0);
+
+	layer_fds[3] = openat(fd_tmpfs, "l2", O_DIRECTORY);
+	ASSERT_GE(layer_fds[3], 0);
+
+	layer_fds[4] = openat(fd_tmpfs, "l3", O_DIRECTORY);
+	ASSERT_GE(layer_fds[4], 0);
+
+	ASSERT_EQ(sys_move_mount(fd_tmpfs, "", -EBADF, "/tmp", MOVE_MOUNT_F_EMPTY_PATH), 0);
+	ASSERT_EQ(close(fd_tmpfs), 0);
+
+	fd_context = sys_fsopen("overlay", 0);
+	ASSERT_GE(fd_context, 0);
+
+	ASSERT_NE(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir_fd", NULL, layer_fds[2]), 0);
+
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "workdir_fd", NULL, layer_fds[0]), 0);
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "upperdir_fd", NULL, layer_fds[1]), 0);
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, layer_fds[2]), 0);
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, layer_fds[3]), 0);
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_SET_FD, "lowerdir_fd+", NULL, layer_fds[4]), 0);
+
+	ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0);
+
+	fd_overlay = sys_fsmount(fd_context, 0, 0);
+	ASSERT_GE(fd_overlay, 0);
+
+	ASSERT_EQ(sys_move_mount(fd_overlay, "", -EBADF, "/set_layers_via_fds", MOVE_MOUNT_F_EMPTY_PATH), 0);
+
+	f_mountinfo = fopen("/proc/self/mountinfo", "r");
+	ASSERT_NE(f_mountinfo, NULL);
+
+	while (getline(&line, &len, f_mountinfo) != -1) {
+		char *haystack = line;
+
+		if (strstr(haystack, "workdir=/tmp/w"))
+			layers_found[0] = true;
+		if (strstr(haystack, "upperdir=/tmp/u"))
+			layers_found[1] = true;
+		if (strstr(haystack, "lowerdir+=/tmp/l1"))
+			layers_found[2] = true;
+		if (strstr(haystack, "lowerdir+=/tmp/l2"))
+			layers_found[3] = true;
+		if (strstr(haystack, "lowerdir+=/tmp/l3"))
+			layers_found[4] = true;
+	}
+	free(line);
+
+	for (int i = 0; i < 5; i++) {
+		ASSERT_EQ(layers_found[i], true);
+		ASSERT_EQ(close(layer_fds[i]), 0);
+	}
+
+	ASSERT_EQ(close(fd_context), 0);
+	ASSERT_EQ(close(fd_overlay), 0);
+	ASSERT_EQ(fclose(f_mountinfo), 0);
+}
+
+TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/filesystems/overlayfs/wrappers.h b/tools/testing/selftests/filesystems/overlayfs/wrappers.h
index 4f99e10f7f018fd9a7be5263f68d34807da4c53c..071b95fd2ac0ad7b02d90e8e89df73fd27be69c3 100644
--- a/tools/testing/selftests/filesystems/overlayfs/wrappers.h
+++ b/tools/testing/selftests/filesystems/overlayfs/wrappers.h
@@ -32,6 +32,10 @@ static inline int sys_mount(const char *src, const char *tgt, const char *fst,
 	return syscall(__NR_mount, src, tgt, fst, flags, data);
 }
 
+#ifndef MOVE_MOUNT_F_EMPTY_PATH
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
+#endif
+
 static inline int sys_move_mount(int from_dfd, const char *from_pathname,
 				 int to_dfd, const char *to_pathname,
 				 unsigned int flags)

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH RFC 0/3] ovl: specify layers via file descriptors
  2024-10-11 15:43 [PATCH RFC 0/3] ovl: specify layers via file descriptors Christian Brauner
                   ` (2 preceding siblings ...)
  2024-10-11 15:43 ` [PATCH RFC 3/3] selftests: add overlayfs fd mounting selftests Christian Brauner
@ 2024-10-11 15:52 ` Miklos Szeredi
  2024-10-11 20:57   ` Christian Brauner
  3 siblings, 1 reply; 6+ messages in thread
From: Miklos Szeredi @ 2024-10-11 15:52 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Amir Goldstein, Josef Bacik, linux-fsdevel, linux-unionfs

On Fri, 11 Oct 2024 at 17:43, Christian Brauner <brauner@kernel.org> wrote:

> The mount api doesn't allow overloading of mount option parameters
> (except for strings and flags). Making this work for arbitrary
> parameters would be quite ugly or file descriptors would have to be
> special cased. Neither is very appealing. I do prefer the *_fd mount
> options because they aren't ambiguous.

But the fd's just represent a path (they can be O_PATH, right?)

So upperdir and upperdir_fd are exactly the same options, no?  Just
the representation is different.

Am I missing something?

Thanks,
Miklos

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH RFC 0/3] ovl: specify layers via file descriptors
  2024-10-11 15:52 ` [PATCH RFC 0/3] ovl: specify layers via file descriptors Miklos Szeredi
@ 2024-10-11 20:57   ` Christian Brauner
  0 siblings, 0 replies; 6+ messages in thread
From: Christian Brauner @ 2024-10-11 20:57 UTC (permalink / raw)
  To: Miklos Szeredi; +Cc: Amir Goldstein, Josef Bacik, linux-fsdevel, linux-unionfs

> But the fd's just represent a path (they can be O_PATH, right?)
> 
> So upperdir and upperdir_fd are exactly the same options, no?  Just
> the representation is different.

So I misread the code which lead me to believe that aliasing would be
more involved but it really isn't. Just give me a minute to fix this.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-10-11 20:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-11 15:43 [PATCH RFC 0/3] ovl: specify layers via file descriptors Christian Brauner
2024-10-11 15:43 ` [PATCH RFC 1/3] " Christian Brauner
2024-10-11 15:43 ` [PATCH RFC 2/3] selftests: use shared header Christian Brauner
2024-10-11 15:43 ` [PATCH RFC 3/3] selftests: add overlayfs fd mounting selftests Christian Brauner
2024-10-11 15:52 ` [PATCH RFC 0/3] ovl: specify layers via file descriptors Miklos Szeredi
2024-10-11 20:57   ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).