|
7 | 7 | #include <linux/iomap.h> |
8 | 8 | #include "trace.h" |
9 | 9 |
|
| 10 | +static inline void iomap_iter_reset_iomap(struct iomap_iter *iter) |
| 11 | +{ |
| 12 | + iter->processed = 0; |
| 13 | + memset(&iter->iomap, 0, sizeof(iter->iomap)); |
| 14 | + memset(&iter->srcmap, 0, sizeof(iter->srcmap)); |
| 15 | +} |
| 16 | + |
10 | 17 | /* |
11 | 18 | * Advance to the next range we need to map. |
12 | 19 | * |
13 | 20 | * If the iomap is marked IOMAP_F_STALE, it means the existing map was not fully |
14 | 21 | * processed - it was aborted because the extent the iomap spanned may have been |
15 | 22 | * changed during the operation. In this case, the iteration behaviour is to |
16 | 23 | * 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. |
| 24 | + * even when we've made no progress (i.e. count = 0). Hence the "finished |
| 25 | + * iterating" case needs to distinguish between (count = 0) meaning we are done |
| 26 | + * and (count = 0 && stale) meaning we need to remap the entire remaining range. |
21 | 27 | */ |
22 | | -static inline int iomap_iter_advance(struct iomap_iter *iter) |
| 28 | +static inline int iomap_iter_advance(struct iomap_iter *iter, s64 count) |
23 | 29 | { |
24 | 30 | bool stale = iter->iomap.flags & IOMAP_F_STALE; |
25 | 31 | int ret = 1; |
26 | 32 |
|
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))) |
32 | | - return -EIO; |
33 | | - iter->pos += iter->processed; |
34 | | - iter->len -= iter->processed; |
35 | | - if (!iter->len || (!iter->processed && !stale)) |
36 | | - ret = 0; |
37 | | - } |
| 33 | + if (count < 0) |
| 34 | + return count; |
| 35 | + if (WARN_ON_ONCE(count > iomap_length(iter))) |
| 36 | + return -EIO; |
| 37 | + iter->pos += count; |
| 38 | + iter->len -= count; |
| 39 | + if (!iter->len || (!count && !stale)) |
| 40 | + ret = 0; |
38 | 41 |
|
39 | | - /* clear the per iteration state */ |
40 | | - iter->processed = 0; |
41 | | - memset(&iter->iomap, 0, sizeof(iter->iomap)); |
42 | | - memset(&iter->srcmap, 0, sizeof(iter->srcmap)); |
43 | 42 | return ret; |
44 | 43 | } |
45 | 44 |
|
@@ -82,10 +81,14 @@ int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops) |
82 | 81 | return ret; |
83 | 82 | } |
84 | 83 |
|
| 84 | + /* advance and clear state from the previous iteration */ |
85 | 85 | trace_iomap_iter(iter, ops, _RET_IP_); |
86 | | - ret = iomap_iter_advance(iter); |
87 | | - if (ret <= 0) |
88 | | - return ret; |
| 86 | + if (iter->iomap.length) { |
| 87 | + ret = iomap_iter_advance(iter, iter->processed); |
| 88 | + iomap_iter_reset_iomap(iter); |
| 89 | + if (ret <= 0) |
| 90 | + return ret; |
| 91 | + } |
89 | 92 |
|
90 | 93 | ret = ops->iomap_begin(iter->inode, iter->pos, iter->len, iter->flags, |
91 | 94 | &iter->iomap, &iter->srcmap); |
|
0 commit comments