From: Miklos Szeredi <mszeredi@redhat.com>
To: fuse-devel@lists.linux.dev
Cc: John Groves <john@groves.net>,
Amir Goldstein <amir73il@gmail.com>,
"Darrick J . Wong" <djwong@kernel.org>,
Vishal Verma <vishal.l.verma@intel.com>,
Dave Jiang <dave.jiang@intel.com>,
Alison Schofield <alison.schofield@intel.com>,
nvdimm@lists.linux.dev, linux-cxl@vger.kernel.org
Subject: [PATCH v3 9/9] fuse: add support for striped backing
Date: Tue, 6 Oct 2026 20:01:14 +0200 [thread overview]
Message-ID: <20261006180115.1425232-10-mszeredi@redhat.com> (raw)
In-Reply-To: <20261006180115.1425232-1-mszeredi@redhat.com>
Add the FUSE_BACKING_MAP_CYCLIC flag for FUSE_NOTIFY_BACKING_MAP
notifications to enable creating striped maps.
This is just a set of regular extents that repeats after the end of the
last extent using a striping pattern (i.e. on the target backings the
stripes have a contiguous footprint).
Two additional limits apply compared to non-cyclic extent map population:
- the size of the extents (chunk size) must be equal
- the extents must start from zero offset and follow each other without
gaps.
Originally-by: John Groves <john@groves.net>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/fuse/ext_map.c | 30 +++++++++++++++++++++++++++---
fs/fuse/fuse_i.h | 1 +
fs/fuse/notify.c | 2 +-
include/uapi/linux/fuse.h | 5 ++++-
4 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/fs/fuse/ext_map.c b/fs/fuse/ext_map.c
index 4f418185c0b7..049e0b4514bc 100644
--- a/fs/fuse/ext_map.c
+++ b/fs/fuse/ext_map.c
@@ -109,12 +109,18 @@ static int fuse_ext_map_iomap_begin(struct inode *inode, loff_t offset, loff_t l
{
struct fuse_backing *fb = fuse_inode_backing(get_fuse_inode(inode));
struct fuse_iext *fie;
+ u64 ncycle = 0, seq_off = 0, addr, tmp;
loff_t ext_len;
if (!fb || fb->type != FUSE_BACKING_EXTMAP)
return fuse_EIO("missing or wrong type backing");
- fie = fuse_find_extent(&fb->extents, offset);
+ if (fb->cycle_length) {
+ ncycle = div64_u64(offset, fb->cycle_length);
+ seq_off = ncycle * fb->cycle_length;
+ }
+
+ fie = fuse_find_extent(&fb->extents, offset - seq_off);
if (!fie)
return fuse_EIO("missing mapping");
@@ -127,9 +133,15 @@ static int fuse_ext_map_iomap_begin(struct inode *inode, loff_t offset, loff_t l
}
ext_len = fie->end - fie->start;
+ addr = fie->backing_offset;
+ if (check_mul_overflow(ncycle, ext_len, &tmp) || check_add_overflow(addr, tmp, &addr))
+ return fuse_EIO("extent address overflow");
- iomap->offset = fie->start;
- iomap->addr = fie->backing_offset;
+ if (check_add_overflow(addr, ext_len, &tmp))
+ return fuse_EIO("extent end overflow");
+
+ iomap->offset = fie->start + seq_off;
+ iomap->addr = addr;
iomap->length = ext_len;
iomap->dax_dev = fie->backing->dax_dev;
iomap->type = IOMAP_MAPPED;
@@ -256,6 +268,7 @@ int fuse_ext_map_populate(struct fuse_conn *fc, struct fuse_notify_backing_map_o
struct fuse_backing *fb;
unsigned int i;
int err;
+ u64 chunk_size = 0;
if (!arg->num_extents)
return fuse_EIO("no extents");
@@ -273,7 +286,18 @@ int fuse_ext_map_populate(struct fuse_conn *fc, struct fuse_notify_backing_map_o
return -EINVAL;
}
+ if (arg->flags & FUSE_BACKING_MAP_CYCLIC) {
+ chunk_size = ext[0].length;
+ err = -EINVAL;
+ if (check_mul_overflow(chunk_size, arg->num_extents, &fb->cycle_length))
+ goto err_put;
+ }
+
for (i = 0; i < arg->num_extents; i++) {
+ err = -EINVAL;
+ if (chunk_size && (ext[i].offset != chunk_size * i || ext[i].length != chunk_size))
+ goto err_put;
+
err = fuse_add_extent(fc, &fb->extents, &ext[i]);
if (err)
goto err_put;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5d38dc1b6f0c..cd10156e09d4 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -110,6 +110,7 @@ struct fuse_backing {
};
struct {
struct rb_root extents;
+ u64 cycle_length;
};
};
u64 backing_id;
diff --git a/fs/fuse/notify.c b/fs/fuse/notify.c
index 3bfedd0cdbdd..31172de72477 100644
--- a/fs/fuse/notify.c
+++ b/fs/fuse/notify.c
@@ -461,7 +461,7 @@ static int fuse_notify_map(struct fuse_conn *fc, unsigned int size,
if (outarg.reserved[0] != 0 || outarg.reserved[1] != 0)
return -EINVAL;
- if (outarg.flags & ~FUSE_BACKING_MAP_CREATE)
+ if (outarg.flags & ~(FUSE_BACKING_MAP_CREATE | FUSE_BACKING_MAP_CYCLIC))
return -EINVAL;
if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 60060da98e8d..6b2fe68b4ab5 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -255,7 +255,8 @@
* - add FUSE_DEV_IOC_BACKING_CREATE, struct fuse_backing_create_in
* - add FUSE_NOTIFY_BACKING_REMOVE, struct fuse_notify_backing_remove_out
* - add backing_id_64 to fuse_open_out
- * - add FUSE_NOTIFY_BACKING_MAP, fuse_notify_backing_map_out, fuse_extent, FUSE_BACKING_MAP_CREATE
+ * - add FUSE_NOTIFY_BACKING_MAP, fuse_notify_backing_map_out, fuse_extent
+ * - add FUSE_BACKING_MAP_CREATE, FUSE_BACKING_MAP_CYCLIC
*/
#ifndef _LINUX_FUSE_H
@@ -1219,8 +1220,10 @@ struct fuse_notify_backing_remove_out {
* notify_map flags
*
* FUSE_BACKING_MAP_CREATE: create backing with the supplied ID
+ * FUSE_BACKING_MAP_CYCLIC: map repeats after last extent
*/
#define FUSE_BACKING_MAP_CREATE (1 << 0)
+#define FUSE_BACKING_MAP_CYCLIC (1 << 1)
struct fuse_notify_backing_map_out {
uint64_t backing_id;
--
2.54.0
prev parent reply other threads:[~2026-10-06 18:01 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 18:01 [PATCH v3 0/9] fuse: DAX device based extent maps (famfs) Miklos Szeredi
2026-10-06 18:01 ` [PATCH v3 1/9] dax: replace exported dax_dev_get() with non-allocating dax_dev_find() Miklos Szeredi
2026-10-06 18:10 ` sashiko-bot
2026-10-06 18:01 ` [PATCH v3 2/9] dax: use READ_ONCE() in dax_holder() Miklos Szeredi
2026-10-06 18:13 ` sashiko-bot
2026-10-08 1:02 ` Alison Schofield
2026-10-08 6:58 ` Miklos Szeredi
2026-10-06 18:01 ` [PATCH v3 3/9] fuse: add helpers for EIO return value with kernel message Miklos Szeredi
2026-10-06 21:03 ` Amir Goldstein
2026-10-06 18:01 ` [PATCH v3 4/9] fuse: support 64 bit, server allocated backing ID Miklos Szeredi
2026-10-06 18:20 ` sashiko-bot
2026-10-06 20:10 ` John Groves
2026-10-07 12:49 ` Miklos Szeredi
2026-10-06 22:08 ` Amir Goldstein
2026-10-07 12:54 ` Miklos Szeredi
2026-10-06 18:01 ` [PATCH v3 5/9] fuse: support opening 64 bit " Miklos Szeredi
2026-10-06 18:01 ` [PATCH v3 6/9] fuse: add support for opening dax device as backing Miklos Szeredi
2026-10-06 18:18 ` sashiko-bot
2026-10-06 18:01 ` [PATCH v3 7/9] fuse: add extent map data structure Miklos Szeredi
2026-10-06 18:17 ` sashiko-bot
2026-10-06 18:01 ` [PATCH v3 8/9] fuse: add extent map I/O support Miklos Szeredi
2026-10-06 18:22 ` sashiko-bot
2026-10-06 18:01 ` Miklos Szeredi [this message]
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=20261006180115.1425232-10-mszeredi@redhat.com \
--to=mszeredi@redhat.com \
--cc=alison.schofield@intel.com \
--cc=amir73il@gmail.com \
--cc=dave.jiang@intel.com \
--cc=djwong@kernel.org \
--cc=fuse-devel@lists.linux.dev \
--cc=john@groves.net \
--cc=linux-cxl@vger.kernel.org \
--cc=nvdimm@lists.linux.dev \
--cc=vishal.l.verma@intel.com \
/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