From: Giuseppe Scrivano <gscrivan@redhat.com>
To: linux-erofs@lists.ozlabs.org
Cc: cyphar@cyphar.com, hsiangkao@linux.alibaba.com,
linux-fsdevel@vger.kernel.org, gscrivan@redhat.com
Subject: [PATCH v5] erofs: accept source file descriptor via fsconfig
Date: Tue, 28 Jul 2026 18:05:32 +0200 [thread overview]
Message-ID: <20260728160619.853924-1-gscrivan@redhat.com> (raw)
Allow userspace to pass an already-opened file descriptor as the mount
source instead of a path string. This is useful for tools that already
hold an fd to the image, such as composefs reusing an existing erofs
backing file.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
v4: https://lore.kernel.org/linux-fsdevel/20260717134147.1602735-1-gscrivan@redhat.com/
v3: https://lore.kernel.org/linux-fsdevel/20260714154917.489993-1-gscrivan@redhat.com/
v2: https://lore.kernel.org/linux-fsdevel/20260711071137.4130824-1-gscrivan@redhat.com/
v1: https://lore.kernel.org/linux-fsdevel/ak5GfvVfWLJU1EwK@debian/
Documentation/filesystems/erofs.rst | 15 ++++++
fs/erofs/super.c | 73 ++++++++++++++++++++++++-----
2 files changed, 77 insertions(+), 11 deletions(-)
diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst
index 4230884fb359..774e8b236d09 100644
--- a/Documentation/filesystems/erofs.rst
+++ b/Documentation/filesystems/erofs.rst
@@ -139,6 +139,21 @@ inode_share Enable inode page sharing for this filesystem. Inodes wi
page cache.
=================== =========================================================
+File-backed mounts
+==================
+
+When CONFIG_EROFS_FS_BACKED_BY_FILE is enabled, EROFS file-backed images
+can be mounted directly without a loopback block device. The backing file
+can be given either as a path, or as an already-opened file descriptor.
+
+When a file descriptor is used, the kernel resolves its path and records it
+so that /proc/mounts and similar interfaces can still report the mount
+source.
+
+Only regular files are accepted as backing files; to mount an image that
+resides on a block device, use the traditional block device mount path
+instead.
+
Sysfs Entries
=============
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 86fa5c6a0c70..558041011398 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,
};
static const struct constant_table erofs_param_cache_strategy[] = {
@@ -402,17 +403,18 @@ static const struct constant_table erofs_dax_param_enums[] = {
};
static const struct fs_parameter_spec erofs_fs_parameters[] = {
- fsparam_flag_no("user_xattr", Opt_user_xattr),
- fsparam_flag_no("acl", Opt_acl),
- fsparam_enum("cache_strategy", Opt_cache_strategy,
+ fsparam_flag_no("user_xattr", Opt_user_xattr),
+ fsparam_flag_no("acl", Opt_acl),
+ fsparam_enum("cache_strategy", Opt_cache_strategy,
erofs_param_cache_strategy),
- fsparam_flag("dax", Opt_dax),
- fsparam_enum("dax", Opt_dax_enum, erofs_dax_param_enums),
- fsparam_string("device", Opt_device),
- fsparam_string("domain_id", Opt_domain_id),
- fsparam_flag_no("directio", Opt_directio),
- fsparam_u64("fsoffset", Opt_fsoffset),
- fsparam_flag("inode_share", Opt_inode_share),
+ fsparam_flag("dax", Opt_dax),
+ fsparam_enum("dax", Opt_dax_enum, erofs_dax_param_enums),
+ fsparam_string("device", Opt_device),
+ fsparam_string("domain_id", Opt_domain_id),
+ fsparam_flag_no("directio", Opt_directio),
+ fsparam_u64("fsoffset", Opt_fsoffset),
+ fsparam_flag("inode_share", Opt_inode_share),
+ fsparam_file_or_string("source", Opt_source),
{}
};
@@ -437,6 +439,40 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
return false;
}
+static int erofs_fc_parse_source(struct fs_context *fc,
+ struct fs_parameter *param)
+{
+ struct erofs_sb_info *sbi = fc->s_fs_info;
+
+ if (fc->source || sbi->dif0.file)
+ return invalf(fc, "Multiple sources");
+
+ switch (param->type) {
+ case fs_value_is_string:
+ fc->source = param->string;
+ param->string = NULL;
+ return 0;
+ case fs_value_is_file: {
+ char *buf __free(kfree) = kmalloc(PATH_MAX, GFP_KERNEL);
+ char *p;
+
+ if (!buf)
+ return -ENOMEM;
+ p = file_path(param->file, buf, PATH_MAX);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+ fc->source = kstrdup(p, GFP_KERNEL);
+ if (!fc->source)
+ return -ENOMEM;
+ sbi->dif0.file = no_free_ptr(param->file);
+ return 0;
+ }
+ default:
+ WARN_ON_ONCE(true);
+ return -EINVAL;
+ }
+}
+
static int erofs_fc_parse_param(struct fs_context *fc,
struct fs_parameter *param)
{
@@ -524,6 +560,8 @@ static int erofs_fc_parse_param(struct fs_context *fc,
else
set_opt(&sbi->opt, INODE_SHARE);
break;
+ case Opt_source:
+ return erofs_fc_parse_source(fc, param);
}
return 0;
}
@@ -752,13 +790,26 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
static int erofs_fc_get_tree(struct fs_context *fc)
{
+ struct erofs_sb_info *sbi = fc->s_fs_info;
int ret;
+ if (sbi->dif0.file) {
+ if (!IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE)) {
+ errorfc(fc, "source fd option not supported");
+ return -EINVAL;
+ }
+ if (!S_ISREG(file_inode(sbi->dif0.file)->i_mode) ||
+ !sbi->dif0.file->f_mapping->a_ops->read_folio) {
+ errorfc(fc, "source is unsupported");
+ return -EINVAL;
+ }
+ return get_tree_nodev(fc, erofs_fc_fill_super);
+ }
+
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;
struct file *file;
if (!fc->source)
--
2.55.0
next reply other threads:[~2026-07-28 16:06 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 16:05 Giuseppe Scrivano [this message]
2026-07-29 1:40 ` [PATCH v5] erofs: accept source file descriptor via fsconfig Gao Xiang
2026-07-29 9:57 ` Jan Kara
2026-07-29 20:19 ` Gao Xiang
2026-07-30 9:45 ` Christian Brauner
2026-08-03 11:24 ` Chao Yu
2026-08-03 12:01 ` Giuseppe Scrivano
2026-08-03 23:37 ` Gao Xiang
2026-08-04 6:06 ` Giuseppe Scrivano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260728160619.853924-1-gscrivan@redhat.com \
--to=gscrivan@redhat.com \
--cc=cyphar@cyphar.com \
--cc=hsiangkao@linux.alibaba.com \
--cc=linux-erofs@lists.ozlabs.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox