In preparation for future changes and more generic use of iomap_iter_advance(), lift the high level iter continuation logic out of iomap_iter_advance() into the caller. Also add some comments and rework iomap_iter() to jump straight to ->iomap_begin() on the first iteration. Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx> --- fs/iomap/iter.c | 54 +++++++++++++++++++++++-------------------- include/linux/iomap.h | 1 + 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c index 731ea7267f27..260ec702ddd5 100644 --- a/fs/iomap/iter.c +++ b/fs/iomap/iter.c @@ -15,31 +15,19 @@ static inline void iomap_iter_reset_iomap(struct iomap_iter *iter) } /* - * Advance to the next range we need to map. - * - * If the iomap is marked IOMAP_F_STALE, it means the existing map was not fully - * processed - it was aborted because the extent the iomap spanned may have been - * changed during the operation. In this case, the iteration behaviour is to - * remap the unprocessed range of the iter, and that means we may need to remap - * even when we've made no progress (i.e. count = 0). Hence the "finished - * 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. + * Advance the current iterator position and return the length remaining for the + * current mapping. */ -static inline int iomap_iter_advance(struct iomap_iter *iter, s64 count) +s64 iomap_iter_advance(struct iomap_iter *iter, s64 count) { - bool stale = iter->iomap.flags & IOMAP_F_STALE; - int ret = 1; - if (count < 0) return count; if (WARN_ON_ONCE(count > iomap_length(iter))) return -EIO; iter->pos += count; iter->len -= count; - if (!iter->len || (!count && !stale)) - ret = 0; - return ret; + return iomap_length(iter); } static inline void iomap_iter_done(struct iomap_iter *iter) @@ -71,9 +59,15 @@ static inline void iomap_iter_done(struct iomap_iter *iter) */ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops) { - int ret; + s64 ret; + bool stale = iter->iomap.flags & IOMAP_F_STALE; - if (iter->iomap.length && ops->iomap_end) { + if (!iter->iomap.length) { + trace_iomap_iter(iter, ops, _RET_IP_); + goto begin; + } + + if (ops->iomap_end) { ret = ops->iomap_end(iter->inode, iter->pos, iomap_length(iter), iter->processed > 0 ? iter->processed : 0, iter->flags, &iter->iomap); @@ -81,15 +75,25 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops) return ret; } - /* advance and clear state from the previous iteration */ + /* + * Advance the iter and clear state from the previous iteration. The + * remaining length of the previous iteration should be zero by this + * point, so use iter->len to determine whether to continue onto the + * next mapping. Explicitly terminate in the case where the current iter + * has not advanced at all (i.e. no work was done for some reason) + * unless the mapping has been marked stale and needs to be reprocessed. + */ trace_iomap_iter(iter, ops, _RET_IP_); - if (iter->iomap.length) { - ret = iomap_iter_advance(iter, iter->processed); - iomap_iter_reset_iomap(iter); - if (ret <= 0) - return ret; - } + ret = iomap_iter_advance(iter, iter->processed); + if (!ret) + ret = iter->len; + if (ret > 0 && !iter->processed && !stale) + ret = 0; + iomap_iter_reset_iomap(iter); + if (ret <= 0) + return ret; +begin: ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags, &iter->iomap, &iter->srcmap); if (ret < 0) diff --git a/include/linux/iomap.h b/include/linux/iomap.h index b6f7d96156f2..88bde0259035 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -229,6 +229,7 @@ struct iomap_iter { }; int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops); +s64 iomap_iter_advance(struct iomap_iter *iter, s64 count); static inline u64 iomap_length_trim(const struct iomap_iter *iter, loff_t pos, u64 len) -- 2.47.1