1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2010 Red Hat, Inc.
4 * Copyright (c) 2016-2021 Christoph Hellwig.
7 #include <linux/iomap.h>
11 * Advance to the next range we need to map.
13 * If the iomap is marked IOMAP_F_STALE, it means the existing map was not fully
14 * processed - it was aborted because the extent the iomap spanned may have been
15 * changed during the operation. In this case, the iteration behaviour is to
16 * remap the unprocessed range of the iter, and that means we may need to remap
17 * even when we've made no progress (i.e. iter->processed = 0). Hence the
18 * "finished iterating" case needs to distinguish between
19 * (processed = 0) meaning we are done and (processed = 0 && stale) meaning we
20 * need to remap the entire remaining range.
22 static inline int iomap_iter_advance(struct iomap_iter
*iter
)
24 bool stale
= iter
->iomap
.flags
& IOMAP_F_STALE
;
27 /* handle the previous iteration (if any) */
28 if (iter
->iomap
.length
) {
29 if (iter
->processed
< 0)
30 return iter
->processed
;
31 if (WARN_ON_ONCE(iter
->processed
> iomap_length(iter
)))
33 iter
->pos
+= iter
->processed
;
34 iter
->len
-= iter
->processed
;
35 if (!iter
->len
|| (!iter
->processed
&& !stale
))
39 /* clear the per iteration state */
41 memset(&iter
->iomap
, 0, sizeof(iter
->iomap
));
42 memset(&iter
->srcmap
, 0, sizeof(iter
->srcmap
));
46 static inline void iomap_iter_done(struct iomap_iter
*iter
)
48 WARN_ON_ONCE(iter
->iomap
.offset
> iter
->pos
);
49 WARN_ON_ONCE(iter
->iomap
.length
== 0);
50 WARN_ON_ONCE(iter
->iomap
.offset
+ iter
->iomap
.length
<= iter
->pos
);
51 WARN_ON_ONCE(iter
->iomap
.flags
& IOMAP_F_STALE
);
53 trace_iomap_iter_dstmap(iter
->inode
, &iter
->iomap
);
54 if (iter
->srcmap
.type
!= IOMAP_HOLE
)
55 trace_iomap_iter_srcmap(iter
->inode
, &iter
->srcmap
);
59 * iomap_iter - iterate over a ranges in a file
60 * @iter: iteration structue
61 * @ops: iomap ops provided by the file system
63 * Iterate over filesystem-provided space mappings for the provided file range.
65 * This function handles cleanup of resources acquired for iteration when the
66 * filesystem indicates there are no more space mappings, which means that this
67 * function must be called in a loop that continues as long it returns a
68 * positive value. If 0 or a negative value is returned, the caller must not
69 * return to the loop body. Within a loop body, there are two ways to break out
70 * of the loop body: leave @iter.processed unchanged, or set it to a negative
73 int iomap_iter(struct iomap_iter
*iter
, const struct iomap_ops
*ops
)
77 if (iter
->iomap
.length
&& ops
->iomap_end
) {
78 ret
= ops
->iomap_end(iter
->inode
, iter
->pos
, iomap_length(iter
),
79 iter
->processed
> 0 ? iter
->processed
: 0,
80 iter
->flags
, &iter
->iomap
);
81 if (ret
< 0 && !iter
->processed
)
85 trace_iomap_iter(iter
, ops
, _RET_IP_
);
86 ret
= iomap_iter_advance(iter
);
90 ret
= ops
->iomap_begin(iter
->inode
, iter
->pos
, iter
->len
, iter
->flags
,
91 &iter
->iomap
, &iter
->srcmap
);
94 iomap_iter_done(iter
);