From: Brian Foster <bfoster@redhat.com>
To: linux-fsdevel@vger.kernel.org
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 3/6] iomap: support incremental iomap_iter advances
Date: Fri, 13 Dec 2024 09:36:07 -0500 [thread overview]
Message-ID: <20241213143610.1002526-4-bfoster@redhat.com> (raw)
In-Reply-To: <20241213143610.1002526-1-bfoster@redhat.com>
The current iomap_iter iteration model reads the mapping from the
filesystem, processes the subrange of the operation associated with
the current mapping, and returns the number of bytes processed back
to the iteration code. The latter advances the position and
remaining length of the iter in preparation for the next iteration.
At the _iter() handler level, this tends to produce a processing
loop where the local code pulls the current position and remaining
length out of the iter, iterates it locally based on file offset,
and then breaks out when the associated range has been fully
processed.
This works well enough for current handlers, but upcoming
enhancements require a bit more flexibility in certain situations.
Enhancements for zero range will lead to a situation where the
processing loop is no longer a pure ascending offset walk, but
rather dictated by pagecache state and folio lookup. Since folio
lookup and write preparation occur at different levels, it is more
difficult to manage position and length outside of the iter.
To provide more flexibility to certain iomap operations, introduce
support for incremental iomap_iter advances from within the
operation itself. This allows more granular advances for operations
that might not use the typical file offset based walk.
Note that the semantics for operations that use incremental advances
is slightly different than traditional operations. Operations that
advance the iter directly are expected to return success or failure
(i.e. 0 or negative error code) in iter.processed rather than the
number of bytes processed.
Signed-off-by: Brian Foster <bfoster@redhat.com>
---
fs/iomap/iter.c | 27 +++++++++++++++++++++------
include/linux/iomap.h | 4 ++++
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c
index 731ea7267f27..5fe0edb51fe5 100644
--- a/fs/iomap/iter.c
+++ b/fs/iomap/iter.c
@@ -25,7 +25,7 @@ static inline void iomap_iter_reset_iomap(struct iomap_iter *iter)
* iterating" case needs to distinguish between (count = 0) meaning we are done
* and (count = 0 && stale) meaning we need to remap the entire remaining range.
*/
-static inline int iomap_iter_advance(struct iomap_iter *iter, s64 count)
+int iomap_iter_advance(struct iomap_iter *iter, s64 count)
{
bool stale = iter->iomap.flags & IOMAP_F_STALE;
int ret = 1;
@@ -36,7 +36,7 @@ static inline int iomap_iter_advance(struct iomap_iter *iter, s64 count)
return -EIO;
iter->pos += count;
iter->len -= count;
- if (!iter->len || (!count && !stale))
+ if (!iter->len || (!count && !stale && iomap_length(iter)))
ret = 0;
return ret;
@@ -49,6 +49,8 @@ static inline void iomap_iter_done(struct iomap_iter *iter)
WARN_ON_ONCE(iter->iomap.offset + iter->iomap.length <= iter->pos);
WARN_ON_ONCE(iter->iomap.flags & IOMAP_F_STALE);
+ iter->iter_spos = iter->pos;
+
trace_iomap_iter_dstmap(iter->inode, &iter->iomap);
if (iter->srcmap.type != IOMAP_HOLE)
trace_iomap_iter_srcmap(iter->inode, &iter->srcmap);
@@ -74,10 +76,23 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
int ret;
if (iter->iomap.length && ops->iomap_end) {
- ret = ops->iomap_end(iter->inode, iter->pos, iomap_length(iter),
- iter->processed > 0 ? iter->processed : 0,
- iter->flags, &iter->iomap);
- if (ret < 0 && !iter->processed)
+ ssize_t processed = iter->processed > 0 ? iter->processed : 0;
+ u64 olen = iter->len;
+
+ /*
+ * If processed is zero, the op may have advanced the iter
+ * itself. Update the processed and original length bytes based
+ * on how far ->pos has advanced.
+ */
+ if (!processed) {
+ processed = iter->pos - iter->iter_spos;
+ olen += processed;
+ }
+
+ ret = ops->iomap_end(iter->inode, iter->iter_spos,
+ __iomap_length(iter, iter->iter_spos, olen),
+ processed, iter->flags, &iter->iomap);
+ if (ret < 0 && !processed)
return ret;
}
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index cbacccb3fb14..704ed98159f7 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -211,6 +211,8 @@ struct iomap_ops {
* calls to iomap_iter(). Treat as read-only in the body.
* @len: The remaining length of the file segment we're operating on.
* It is updated at the same time as @pos.
+ * @iter_spos: The original start pos for the current iomap. Used for
+ * incremental iter advance.
* @processed: The number of bytes processed by the body in the most recent
* iteration, or a negative errno. 0 causes the iteration to stop.
* @flags: Zero or more of the iomap_begin flags above.
@@ -221,6 +223,7 @@ struct iomap_iter {
struct inode *inode;
loff_t pos;
u64 len;
+ loff_t iter_spos;
s64 processed;
unsigned flags;
struct iomap iomap;
@@ -229,6 +232,7 @@ struct iomap_iter {
};
int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops);
+int iomap_iter_advance(struct iomap_iter *iter, s64 count);
/**
* iomap_length - length of the current iomap iteration
--
2.47.0
next prev parent reply other threads:[~2024-12-13 14:34 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-13 14:36 [PATCH 0/6] iomap: incremental per-operation iter advance Brian Foster
2024-12-13 14:36 ` [PATCH 1/6] iomap: split out iomap check and reset logic from " Brian Foster
2025-01-09 7:00 ` Christoph Hellwig
2024-12-13 14:36 ` [PATCH 2/6] iomap: factor out iomap length helper Brian Foster
2025-01-09 7:02 ` Christoph Hellwig
2025-01-10 17:49 ` Brian Foster
2025-01-13 4:46 ` Christoph Hellwig
2024-12-13 14:36 ` Brian Foster [this message]
2025-01-09 7:07 ` [PATCH 3/6] iomap: support incremental iomap_iter advances Christoph Hellwig
2025-01-10 17:50 ` Brian Foster
2025-01-13 4:48 ` Christoph Hellwig
2025-01-13 14:25 ` Brian Foster
2024-12-13 14:36 ` [PATCH 4/6] iomap: advance the iter directly on buffered writes Brian Foster
2025-01-09 7:10 ` Christoph Hellwig
2025-01-10 17:51 ` Brian Foster
2025-01-15 5:46 ` Christoph Hellwig
2024-12-13 14:36 ` [PATCH 5/6] iomap: advance the iter directly on unshare range Brian Foster
2024-12-13 14:36 ` [PATCH 6/6] iomap: advance the iter directly on zero range Brian Foster
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=20241213143610.1002526-4-bfoster@redhat.com \
--to=bfoster@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-xfs@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