File Index
Files and directories
Sign in
FILE

iter.c

File preview with syntax highlighting.

linux-6.19.14/fs/iomap/iter.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2010 Red Hat, Inc.
  4 * Copyright (c) 2016-2021 Christoph Hellwig.
  5 */
  6#include <linux/iomap.h>
  7#include "trace.h"
  8
  9static inline void iomap_iter_reset_iomap(struct iomap_iter *iter)
 10{
 11	if (iter->iomap.flags & IOMAP_F_FOLIO_BATCH) {
 12		folio_batch_release(iter->fbatch);
 13		folio_batch_reinit(iter->fbatch);
 14		iter->iomap.flags &= ~IOMAP_F_FOLIO_BATCH;
 15	}
 16
 17	iter->status = 0;
 18	memset(&iter->iomap, 0, sizeof(iter->iomap));
 19	memset(&iter->srcmap, 0, sizeof(iter->srcmap));
 20}
 21
 22/* Advance the current iterator position and decrement the remaining length */
 23int iomap_iter_advance(struct iomap_iter *iter, u64 count)
 24{
 25	if (WARN_ON_ONCE(count > iomap_length(iter)))
 26		return -EIO;
 27	iter->pos += count;
 28	iter->len -= count;
 29	return 0;
 30}
 31
 32static inline void iomap_iter_done(struct iomap_iter *iter)
 33{
 34	WARN_ON_ONCE(iter->iomap.offset > iter->pos);
 35	WARN_ON_ONCE(iter->iomap.length == 0);
 36	WARN_ON_ONCE(iter->iomap.offset + iter->iomap.length <= iter->pos);
 37	WARN_ON_ONCE(iter->iomap.flags & IOMAP_F_STALE);
 38
 39	iter->iter_start_pos = iter->pos;
 40
 41	trace_iomap_iter_dstmap(iter->inode, &iter->iomap);
 42	if (iter->srcmap.type != IOMAP_HOLE)
 43		trace_iomap_iter_srcmap(iter->inode, &iter->srcmap);
 44}
 45
 46/**
 47 * iomap_iter - iterate over a ranges in a file
 48 * @iter: iteration structue
 49 * @ops: iomap ops provided by the file system
 50 *
 51 * Iterate over filesystem-provided space mappings for the provided file range.
 52 *
 53 * This function handles cleanup of resources acquired for iteration when the
 54 * filesystem indicates there are no more space mappings, which means that this
 55 * function must be called in a loop that continues as long it returns a
 56 * positive value.  If 0 or a negative value is returned, the caller must not
 57 * return to the loop body.  Within a loop body, there are two ways to break out
 58 * of the loop body:  leave @iter.status unchanged, or set it to a negative
 59 * errno.
 60 */
 61int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops)
 62{
 63	bool stale = iter->iomap.flags & IOMAP_F_STALE;
 64	ssize_t advanced;
 65	u64 olen;
 66	int ret;
 67
 68	trace_iomap_iter(iter, ops, _RET_IP_);
 69
 70	if (!iter->iomap.length)
 71		goto begin;
 72
 73	/*
 74	 * Calculate how far the iter was advanced and the original length bytes
 75	 * for ->iomap_end().
 76	 */
 77	advanced = iter->pos - iter->iter_start_pos;
 78	olen = iter->len + advanced;
 79
 80	if (ops->iomap_end) {
 81		ret = ops->iomap_end(iter->inode, iter->iter_start_pos,
 82				iomap_length_trim(iter, iter->iter_start_pos,
 83						  olen),
 84				advanced, iter->flags, &iter->iomap);
 85		if (ret < 0 && !advanced)
 86			return ret;
 87	}
 88
 89	/* detect old return semantics where this would advance */
 90	if (WARN_ON_ONCE(iter->status > 0))
 91		iter->status = -EIO;
 92
 93	/*
 94	 * Use iter->len to determine whether to continue onto the next mapping.
 95	 * Explicitly terminate on error status or if the current iter has not
 96	 * advanced at all (i.e. no work was done for some reason) unless the
 97	 * mapping has been marked stale and needs to be reprocessed.
 98	 */
 99	if (iter->status < 0)
100		ret = iter->status;
101	else if (iter->len == 0 || (!advanced && !stale))
102		ret = 0;
103	else
104		ret = 1;
105	iomap_iter_reset_iomap(iter);
106	if (ret <= 0)
107		return ret;
108
109begin:
110	ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags,
111			       &iter->iomap, &iter->srcmap);
112	if (ret < 0)
113		return ret;
114	iomap_iter_done(iter);
115	return 1;
116}
~/ Read-only file preview.