* [PATCH 0/2] erofs: fd-based source and backing file introspection
@ 2026-07-08 9:34 Giuseppe Scrivano
2026-07-08 9:34 ` [PATCH 1/2] erofs: accept source file descriptor via fsconfig Giuseppe Scrivano
2026-07-08 9:34 ` [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor Giuseppe Scrivano
0 siblings, 2 replies; 7+ messages in thread
From: Giuseppe Scrivano @ 2026-07-08 9:34 UTC (permalink / raw)
To: linux-erofs; +Cc: linux-fsdevel, linux-api
This series adds two features to erofs for file-backed mounts:
1. Accept a source file descriptor via fsconfig(FSCONFIG_SET_FD,
"source", NULL, fd) as an alternative to a path string. This is
useful when the backing file isn't reachable by path in the caller's
mount namespace. For example, composefs reusing an already-mounted
erofs image's backing file.
2. Add an EROFS_IOC_GET_SOURCE_FD ioctl that returns a file descriptor
to the backing image file. This allows userspace to retrieve the
backing file from an existing erofs mount without needing to know or
parse the original source path.
Giuseppe Scrivano (2):
erofs: accept source file descriptor via fsconfig
erofs: add ioctl to retrieve the backing source file descriptor
fs/erofs/inode.c | 25 +++++++++++++++++++++++++
fs/erofs/super.c | 36 +++++++++++++++++++++++++-----------
include/uapi/linux/erofs.h | 9 +++++++++
3 files changed, 59 insertions(+), 11 deletions(-)
create mode 100644 include/uapi/linux/erofs.h
--
2.55.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] erofs: accept source file descriptor via fsconfig
2026-07-08 9:34 [PATCH 0/2] erofs: fd-based source and backing file introspection Giuseppe Scrivano
@ 2026-07-08 9:34 ` Giuseppe Scrivano
2026-07-08 12:45 ` Gao Xiang
2026-07-08 9:34 ` [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor Giuseppe Scrivano
1 sibling, 1 reply; 7+ messages in thread
From: Giuseppe Scrivano @ 2026-07-08 9:34 UTC (permalink / raw)
To: linux-erofs; +Cc: linux-fsdevel, linux-api
Add fsparam_fd("source") so that userspace can pass an already-opened
file descriptor instead of a path string. When the fd is provided via
fsconfig(FSCONFIG_SET_FD, "source", NULL, fd), it is stored directly
in sbi->dif0.file and erofs_fc_get_tree() skips the filp_open() call.
This is useful for mount namespaces where the backing file may not be
reachable by path, and for tools that already hold an fd to the image
(e.g. composefs reusing an erofs mount's backing file).
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
fs/erofs/super.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 86fa5c6a0c70..8ad1689f74b2 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -386,6 +386,7 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
enum {
Opt_user_xattr, Opt_acl, Opt_cache_strategy, Opt_dax, Opt_dax_enum,
Opt_device, Opt_domain_id, Opt_directio, Opt_fsoffset, Opt_inode_share,
+ Opt_source_fd,
};
static const struct constant_table erofs_param_cache_strategy[] = {
@@ -413,6 +414,7 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
fsparam_flag_no("directio", Opt_directio),
fsparam_u64("fsoffset", Opt_fsoffset),
fsparam_flag("inode_share", Opt_inode_share),
+ fsparam_fd("source", Opt_source_fd),
{}
};
@@ -524,6 +526,15 @@ static int erofs_fc_parse_param(struct fs_context *fc,
else
set_opt(&sbi->opt, INODE_SHARE);
break;
+ case Opt_source_fd:
+ if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE)) {
+ errorfc(fc, "source fd option not supported");
+ return -EINVAL;
+ }
+ if (sbi->dif0.file)
+ fput(sbi->dif0.file);
+ sbi->dif0.file = get_file(param->file);
+ break;
}
return 0;
}
@@ -752,14 +763,18 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
static int erofs_fc_get_tree(struct fs_context *fc)
{
- int ret;
+ struct erofs_sb_info *sbi = fc->s_fs_info;
- ret = get_tree_bdev_flags(fc, erofs_fc_fill_super,
- IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ?
- GET_TREE_BDEV_QUIET_LOOKUP : 0);
- if (IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && ret == -ENOTBLK) {
- struct erofs_sb_info *sbi = fc->s_fs_info;
+ if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) || !sbi->dif0.file) {
struct file *file;
+ int ret;
+
+ ret = get_tree_bdev_flags(fc, erofs_fc_fill_super,
+ IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ?
+ GET_TREE_BDEV_QUIET_LOOKUP : 0);
+ if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ||
+ ret != -ENOTBLK)
+ return ret;
if (!fc->source)
return invalf(fc, "No source specified");
@@ -767,12 +782,11 @@ static int erofs_fc_get_tree(struct fs_context *fc)
if (IS_ERR(file))
return PTR_ERR(file);
sbi->dif0.file = file;
-
- if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
- sbi->dif0.file->f_mapping->a_ops->read_folio)
- return get_tree_nodev(fc, erofs_fc_fill_super);
}
- return ret;
+ if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
+ sbi->dif0.file->f_mapping->a_ops->read_folio)
+ return get_tree_nodev(fc, erofs_fc_fill_super);
+ return -EINVAL;
}
static int erofs_fc_reconfigure(struct fs_context *fc)
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor
2026-07-08 9:34 [PATCH 0/2] erofs: fd-based source and backing file introspection Giuseppe Scrivano
2026-07-08 9:34 ` [PATCH 1/2] erofs: accept source file descriptor via fsconfig Giuseppe Scrivano
@ 2026-07-08 9:34 ` Giuseppe Scrivano
2026-07-08 12:51 ` Gao Xiang
2026-07-08 14:55 ` Andy Lutomirski
1 sibling, 2 replies; 7+ messages in thread
From: Giuseppe Scrivano @ 2026-07-08 9:34 UTC (permalink / raw)
To: linux-erofs; +Cc: linux-fsdevel, linux-api
Add EROFS_IOC_GET_SOURCE_FD ioctl that returns a file descriptor to the
backing image file for file-backed erofs mounts.
Returns -ENOENT for block-device-backed erofs mounts where there is no
backing file.
The UAPI constant is defined in include/uapi/linux/erofs.h.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
fs/erofs/inode.c | 25 +++++++++++++++++++++++++
include/uapi/linux/erofs.h | 9 +++++++++
2 files changed, 34 insertions(+)
create mode 100644 include/uapi/linux/erofs.h
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index 45afe5c50de8..0a38cb5cfc5d 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -6,6 +6,8 @@
*/
#include "xattr.h"
#include <linux/compat.h>
+#include <linux/file.h>
+#include <uapi/linux/erofs.h>
#include <trace/events/erofs.h>
static int erofs_fill_symlink(struct inode *inode, void *bptr, unsigned int ofs)
@@ -356,6 +358,27 @@ static int erofs_ioctl_get_volume_label(struct inode *inode, void __user *arg)
return ret ? -EFAULT : 0;
}
+static int erofs_ioctl_get_source_fd(struct file *filp)
+{
+ struct erofs_sb_info *sbi = EROFS_I_SB(file_inode(filp));
+ struct file *f;
+ int fd;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!erofs_is_fileio_mode(sbi))
+ return -ENOENT;
+
+ fd = get_unused_fd_flags(O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ f = get_file(sbi->dif0.file);
+ fd_install(fd, f);
+ return fd;
+}
+
long erofs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file_inode(filp);
@@ -364,6 +387,8 @@ long erofs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
switch (cmd) {
case FS_IOC_GETFSLABEL:
return erofs_ioctl_get_volume_label(inode, argp);
+ case EROFS_IOC_GET_SOURCE_FD:
+ return erofs_ioctl_get_source_fd(filp);
default:
return -ENOTTY;
}
diff --git a/include/uapi/linux/erofs.h b/include/uapi/linux/erofs.h
new file mode 100644
index 000000000000..17c835785ea9
--- /dev/null
+++ b/include/uapi/linux/erofs.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_EROFS_H
+#define _UAPI_LINUX_EROFS_H
+
+#include <linux/ioctl.h>
+
+#define EROFS_IOC_GET_SOURCE_FD _IO('e', 1)
+
+#endif /* _UAPI_LINUX_EROFS_H */
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] erofs: accept source file descriptor via fsconfig
2026-07-08 9:34 ` [PATCH 1/2] erofs: accept source file descriptor via fsconfig Giuseppe Scrivano
@ 2026-07-08 12:45 ` Gao Xiang
0 siblings, 0 replies; 7+ messages in thread
From: Gao Xiang @ 2026-07-08 12:45 UTC (permalink / raw)
To: Giuseppe Scrivano; +Cc: linux-erofs, linux-fsdevel, linux-api
Hi Giuseppe,
On Wed, Jul 08, 2026 at 11:34:26AM +0200, Giuseppe Scrivano wrote:
> Add fsparam_fd("source") so that userspace can pass an already-opened
> file descriptor instead of a path string. When the fd is provided via
> fsconfig(FSCONFIG_SET_FD, "source", NULL, fd), it is stored directly
> in sbi->dif0.file and erofs_fc_get_tree() skips the filp_open() call.
>
> This is useful for mount namespaces where the backing file may not be
> reachable by path, and for tools that already hold an fd to the image
> (e.g. composefs reusing an erofs mount's backing file).
>
> Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
> ---
> fs/erofs/super.c | 36 +++++++++++++++++++++++++-----------
> 1 file changed, 25 insertions(+), 11 deletions(-)
>
> diff --git a/fs/erofs/super.c b/fs/erofs/super.c
> index 86fa5c6a0c70..8ad1689f74b2 100644
> --- a/fs/erofs/super.c
> +++ b/fs/erofs/super.c
> @@ -386,6 +386,7 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
> enum {
> Opt_user_xattr, Opt_acl, Opt_cache_strategy, Opt_dax, Opt_dax_enum,
> Opt_device, Opt_domain_id, Opt_directio, Opt_fsoffset, Opt_inode_share,
> + Opt_source_fd,
> };
>
> static const struct constant_table erofs_param_cache_strategy[] = {
> @@ -413,6 +414,7 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
> fsparam_flag_no("directio", Opt_directio),
> fsparam_u64("fsoffset", Opt_fsoffset),
> fsparam_flag("inode_share", Opt_inode_share),
> + fsparam_fd("source", Opt_source_fd),
> {}
> };
>
> @@ -524,6 +526,15 @@ static int erofs_fc_parse_param(struct fs_context *fc,
> else
> set_opt(&sbi->opt, INODE_SHARE);
> break;
> + case Opt_source_fd:
> + if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE)) {
> + errorfc(fc, "source fd option not supported");
Thanks for the patch!
For this commit, it looks good to me overall, just some nits:
I guess we could just move this one into erofs_fc_get_tree(), see below.
> + return -EINVAL;
> + }
> + if (sbi->dif0.file)
Do we need to allow multi-shot source_fd?
I guess we could just bail out directly instead.
> + fput(sbi->dif0.file);
> + sbi->dif0.file = get_file(param->file);
> + break;
> }
> return 0;
> }
> @@ -752,14 +763,18 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
>
> static int erofs_fc_get_tree(struct fs_context *fc)
> {
> - int ret;
> + struct erofs_sb_info *sbi = fc->s_fs_info;
Nit:
struct file *file = sbi->dif0.file;
>
> - ret = get_tree_bdev_flags(fc, erofs_fc_fill_super,
> - IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ?
> - GET_TREE_BDEV_QUIET_LOOKUP : 0);
> - if (IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && ret == -ENOTBLK) {
> - struct erofs_sb_info *sbi = fc->s_fs_info;
> + if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) || !sbi->dif0.file) {
if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) || !file) {
> struct file *file;
> + int ret;
> +
> + ret = get_tree_bdev_flags(fc, erofs_fc_fill_super,
> + IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ?
> + GET_TREE_BDEV_QUIET_LOOKUP : 0);
> + if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) ||
> + ret != -ENOTBLK)
> + return ret;
>
> if (!fc->source)
> return invalf(fc, "No source specified");
> @@ -767,12 +782,11 @@ static int erofs_fc_get_tree(struct fs_context *fc)
> if (IS_ERR(file))
> return PTR_ERR(file);
> sbi->dif0.file = file;
> -
> - if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
> - sbi->dif0.file->f_mapping->a_ops->read_folio)
> - return get_tree_nodev(fc, erofs_fc_fill_super);
> }
> - return ret;
> + if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
> + sbi->dif0.file->f_mapping->a_ops->read_folio)
> + return get_tree_nodev(fc, erofs_fc_fill_super);
> + return -EINVAL;
Currently we don't support bdev-backed mounts for this, so I'm fine to
support file-backed mounts only for now.
So nit:
if (!S_ISREG(file_inode(file)->i_mode) ||
!file->f_mapping->a_ops->read_folio) {
errorfc(fc, "source is unsupported");
return -EINVAL;
}
return get_tree_nodev(fc, erofs_fc_fill_super);
Thanks,
Gao Xiang
> }
>
> static int erofs_fc_reconfigure(struct fs_context *fc)
> --
> 2.55.0
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor
2026-07-08 9:34 ` [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor Giuseppe Scrivano
@ 2026-07-08 12:51 ` Gao Xiang
2026-07-08 14:55 ` Andy Lutomirski
1 sibling, 0 replies; 7+ messages in thread
From: Gao Xiang @ 2026-07-08 12:51 UTC (permalink / raw)
To: Giuseppe Scrivano
Cc: linux-erofs, linux-fsdevel, linux-api, Christian Brauner
Hi Giuseppe,
On Wed, Jul 08, 2026 at 11:34:27AM +0200, Giuseppe Scrivano wrote:
> Add EROFS_IOC_GET_SOURCE_FD ioctl that returns a file descriptor to the
> backing image file for file-backed erofs mounts.
>
> Returns -ENOENT for block-device-backed erofs mounts where there is no
> backing file.
>
> The UAPI constant is defined in include/uapi/linux/erofs.h.
>
> Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Thanks for the patch!
The functionality is indeed useful to users, but similar to overlayfs
one, I'm not sure if the interface is the best way. Since after we add
this to EROFS, we will support this way forever.
I wonder if there could be a way as a common vfs uapi to get source
fds, but I don't have better ideas for now... (that is why I suggested
to Cc linux-api too..)
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor
2026-07-08 9:34 ` [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor Giuseppe Scrivano
2026-07-08 12:51 ` Gao Xiang
@ 2026-07-08 14:55 ` Andy Lutomirski
2026-07-08 15:20 ` Giuseppe Scrivano
1 sibling, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2026-07-08 14:55 UTC (permalink / raw)
To: Giuseppe Scrivano; +Cc: linux-erofs, linux-fsdevel, linux-api
On Wed, Jul 8, 2026 at 2:36 AM Giuseppe Scrivano <gscrivan@redhat.com> wrote:
>
> Add EROFS_IOC_GET_SOURCE_FD ioctl that returns a file descriptor to the
> backing image file for file-backed erofs mounts.
What’s the use case?
In any event, this seems to have potential security and API-oddity implications.
1. That capable(CAP_SYS_ADMIN) seems critical — otherwise a task that
is admin in a userns can get an fd to a backing file *outside* its
container or to an otherwise inaccessible file. It at least needs a
comment IMO.
2. This series appears to fully round-trip the struct file. That
means that f_cred and mode are preserved. This seems strange and may
have all kinds of accidental effects. For mode in parallel, if the
program that mounts the backing store opened it for write, then this
API gives a writable fd, which seems like an odd choice for a
filesystem that literally has read only in the name.
The OVL variant has these issues to a lesser extent due to the fact
that it returns an O_PATH fd instead of an actual open file.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor
2026-07-08 14:55 ` Andy Lutomirski
@ 2026-07-08 15:20 ` Giuseppe Scrivano
0 siblings, 0 replies; 7+ messages in thread
From: Giuseppe Scrivano @ 2026-07-08 15:20 UTC (permalink / raw)
To: Andy Lutomirski; +Cc: linux-erofs, linux-fsdevel, linux-api
Andy Lutomirski <luto@amacapital.net> writes:
> On Wed, Jul 8, 2026 at 2:36 AM Giuseppe Scrivano <gscrivan@redhat.com> wrote:
>>
>> Add EROFS_IOC_GET_SOURCE_FD ioctl that returns a file descriptor to the
>> backing image file for file-backed erofs mounts.
>
> What’s the use case?
the use case is to reuse EROFS mounts across multiple composefs mounts
without needing a user space daemon to keep the fd alive. The advantage
is that we can share the same superblock across multiple overlay mounts,
instead of limiting the sharing to the same backing file.
> In any event, this seems to have potential security and API-oddity implications.
>
> 1. That capable(CAP_SYS_ADMIN) seems critical — otherwise a task that
> is admin in a userns can get an fd to a backing file *outside* its
> container or to an otherwise inaccessible file. It at least needs a
> comment IMO.
thanks, I'll add that.
> 2. This series appears to fully round-trip the struct file. That
> means that f_cred and mode are preserved. This seems strange and may
> have all kinds of accidental effects. For mode in parallel, if the
> program that mounts the backing store opened it for write, then this
> API gives a writable fd, which seems like an odd choice for a
> filesystem that literally has read only in the name.
> The OVL variant has these issues to a lesser extent due to the fact
> that it returns an O_PATH fd instead of an actual open file.
I didn't think much of the file mode as I assumed requiring
CAP_SYS_ADMIN was enough. I'll change the file mode to O_RDONLY and use
current_cred() to open it. Would that be enough?
Thanks,
Giuseppe
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-07-08 15:20 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 9:34 [PATCH 0/2] erofs: fd-based source and backing file introspection Giuseppe Scrivano
2026-07-08 9:34 ` [PATCH 1/2] erofs: accept source file descriptor via fsconfig Giuseppe Scrivano
2026-07-08 12:45 ` Gao Xiang
2026-07-08 9:34 ` [PATCH 2/2] erofs: add ioctl to retrieve the backing source file descriptor Giuseppe Scrivano
2026-07-08 12:51 ` Gao Xiang
2026-07-08 14:55 ` Andy Lutomirski
2026-07-08 15:20 ` Giuseppe Scrivano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox