Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge patch series "iomap: incremental advance conversion -- phase 2"

Brian Foster <bfoster@redhat.com> says:

Here's phase 2 of the incremental iter advance conversions. This updates
all remaining iomap operations to advance the iter within the operation
and thus removes the need to advance from the core iomap iterator. Once
all operations are switched over, the core advance code is removed and
the processed field is renamed to reflect that it is now a pure status
code.

For context, this was first introduced in a previous series [1] that
focused mainly on the core mechanism and iomap buffered write. This is
because original impetus was to facilitate a folio batch mechanism where
a filesystem can optionally provide a batch of folios to process for a
given mapping (i.e. zero range of an unwritten mapping with dirty folios
in pagecache). That is still WIP, but the broader point is that this was
originally intended as an optional mode until consensus that fell out of
discussion was that it would be preferable to convert over everything.
This presumably facilitates some other future work and simplifies
semantics in the core iteration code.

Patches 1-3 convert over iomap buffered read, direct I/O and various
other remaining ops (swap, etc.). Patches 4-9 convert over the various
DAX iomap operations. Finally, patches 10-12 introduce some cleanups now
that all iomap operations have updated iteration semantics.

* patches from https://lore.kernel.org/r/20250224144757.237706-1-bfoster@redhat.com:
iomap: introduce a full map advance helper
iomap: rename iomap_iter processed field to status
iomap: remove unnecessary advance from iomap_iter()
dax: advance the iomap_iter on pte and pmd faults
dax: advance the iomap_iter on dedupe range
dax: advance the iomap_iter on unshare range
dax: advance the iomap_iter on zero range
dax: push advance down into dax_iomap_iter() for read and write
dax: advance the iomap_iter in the read/write path
iomap: convert misc simple ops to incremental advance
iomap: advance the iter on direct I/O
iomap: advance the iter directly on buffered read

Link: https://lore.kernel.org/r/20250224144757.237706-1-bfoster@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>

+163 -162
+61 -50
fs/dax.c
··· 1258 1258 } 1259 1259 #endif /* CONFIG_FS_DAX_PMD */ 1260 1260 1261 - static s64 dax_unshare_iter(struct iomap_iter *iter) 1261 + static int dax_unshare_iter(struct iomap_iter *iter) 1262 1262 { 1263 1263 struct iomap *iomap = &iter->iomap; 1264 1264 const struct iomap *srcmap = iomap_iter_srcmap(iter); ··· 1266 1266 u64 copy_len = iomap_length(iter); 1267 1267 u32 mod; 1268 1268 int id = 0; 1269 - s64 ret = 0; 1269 + s64 ret; 1270 1270 void *daddr = NULL, *saddr = NULL; 1271 1271 1272 1272 if (!iomap_want_unshare_iter(iter)) 1273 - return iomap_length(iter); 1273 + return iomap_iter_advance_full(iter); 1274 1274 1275 1275 /* 1276 1276 * Extend the file range to be aligned to fsblock/pagesize, because ··· 1300 1300 if (ret < 0) 1301 1301 goto out_unlock; 1302 1302 1303 - if (copy_mc_to_kernel(daddr, saddr, copy_len) == 0) 1304 - ret = iomap_length(iter); 1305 - else 1303 + if (copy_mc_to_kernel(daddr, saddr, copy_len) != 0) 1306 1304 ret = -EIO; 1307 1305 1308 1306 out_unlock: 1309 1307 dax_read_unlock(id); 1310 - return dax_mem2blk_err(ret); 1308 + if (ret < 0) 1309 + return dax_mem2blk_err(ret); 1310 + return iomap_iter_advance_full(iter); 1311 1311 } 1312 1312 1313 1313 int dax_file_unshare(struct inode *inode, loff_t pos, loff_t len, ··· 1326 1326 1327 1327 iter.len = min(len, size - pos); 1328 1328 while ((ret = iomap_iter(&iter, ops)) > 0) 1329 - iter.processed = dax_unshare_iter(&iter); 1329 + iter.status = dax_unshare_iter(&iter); 1330 1330 return ret; 1331 1331 } 1332 1332 EXPORT_SYMBOL_GPL(dax_file_unshare); ··· 1354 1354 return ret; 1355 1355 } 1356 1356 1357 - static s64 dax_zero_iter(struct iomap_iter *iter, bool *did_zero) 1357 + static int dax_zero_iter(struct iomap_iter *iter, bool *did_zero) 1358 1358 { 1359 1359 const struct iomap *iomap = &iter->iomap; 1360 1360 const struct iomap *srcmap = iomap_iter_srcmap(iter); 1361 - loff_t pos = iter->pos; 1362 1361 u64 length = iomap_length(iter); 1363 - s64 written = 0; 1362 + int ret; 1364 1363 1365 1364 /* already zeroed? we're done. */ 1366 1365 if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN) 1367 - return length; 1366 + return iomap_iter_advance(iter, &length); 1368 1367 1369 1368 /* 1370 1369 * invalidate the pages whose sharing state is to be changed ··· 1371 1372 */ 1372 1373 if (iomap->flags & IOMAP_F_SHARED) 1373 1374 invalidate_inode_pages2_range(iter->inode->i_mapping, 1374 - pos >> PAGE_SHIFT, 1375 - (pos + length - 1) >> PAGE_SHIFT); 1375 + iter->pos >> PAGE_SHIFT, 1376 + (iter->pos + length - 1) >> PAGE_SHIFT); 1376 1377 1377 1378 do { 1379 + loff_t pos = iter->pos; 1378 1380 unsigned offset = offset_in_page(pos); 1379 - unsigned size = min_t(u64, PAGE_SIZE - offset, length); 1380 1381 pgoff_t pgoff = dax_iomap_pgoff(iomap, pos); 1381 - long rc; 1382 1382 int id; 1383 1383 1384 + length = min_t(u64, PAGE_SIZE - offset, length); 1385 + 1384 1386 id = dax_read_lock(); 1385 - if (IS_ALIGNED(pos, PAGE_SIZE) && size == PAGE_SIZE) 1386 - rc = dax_zero_page_range(iomap->dax_dev, pgoff, 1); 1387 + if (IS_ALIGNED(pos, PAGE_SIZE) && length == PAGE_SIZE) 1388 + ret = dax_zero_page_range(iomap->dax_dev, pgoff, 1); 1387 1389 else 1388 - rc = dax_memzero(iter, pos, size); 1390 + ret = dax_memzero(iter, pos, length); 1389 1391 dax_read_unlock(id); 1390 1392 1391 - if (rc < 0) 1392 - return rc; 1393 - pos += size; 1394 - length -= size; 1395 - written += size; 1393 + if (ret < 0) 1394 + return ret; 1395 + 1396 + ret = iomap_iter_advance(iter, &length); 1397 + if (ret) 1398 + return ret; 1396 1399 } while (length > 0); 1397 1400 1398 1401 if (did_zero) 1399 1402 *did_zero = true; 1400 - return written; 1403 + return ret; 1401 1404 } 1402 1405 1403 1406 int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, ··· 1414 1413 int ret; 1415 1414 1416 1415 while ((ret = iomap_iter(&iter, ops)) > 0) 1417 - iter.processed = dax_zero_iter(&iter, did_zero); 1416 + iter.status = dax_zero_iter(&iter, did_zero); 1418 1417 return ret; 1419 1418 } 1420 1419 EXPORT_SYMBOL_GPL(dax_zero_range); ··· 1432 1431 } 1433 1432 EXPORT_SYMBOL_GPL(dax_truncate_page); 1434 1433 1435 - static loff_t dax_iomap_iter(const struct iomap_iter *iomi, 1436 - struct iov_iter *iter) 1434 + static int dax_iomap_iter(struct iomap_iter *iomi, struct iov_iter *iter) 1437 1435 { 1438 1436 const struct iomap *iomap = &iomi->iomap; 1439 1437 const struct iomap *srcmap = iomap_iter_srcmap(iomi); ··· 1451 1451 if (pos >= end) 1452 1452 return 0; 1453 1453 1454 - if (iomap->type == IOMAP_HOLE || iomap->type == IOMAP_UNWRITTEN) 1455 - return iov_iter_zero(min(length, end - pos), iter); 1454 + if (iomap->type == IOMAP_HOLE || iomap->type == IOMAP_UNWRITTEN) { 1455 + done = iov_iter_zero(min(length, end - pos), iter); 1456 + return iomap_iter_advance(iomi, &done); 1457 + } 1456 1458 } 1457 1459 1458 1460 /* ··· 1487 1485 } 1488 1486 1489 1487 id = dax_read_lock(); 1490 - while (pos < end) { 1488 + while ((pos = iomi->pos) < end) { 1491 1489 unsigned offset = pos & (PAGE_SIZE - 1); 1492 1490 const size_t size = ALIGN(length + offset, PAGE_SIZE); 1493 1491 pgoff_t pgoff = dax_iomap_pgoff(iomap, pos); ··· 1537 1535 xfer = dax_copy_to_iter(dax_dev, pgoff, kaddr, 1538 1536 map_len, iter); 1539 1537 1540 - pos += xfer; 1541 - length -= xfer; 1542 - done += xfer; 1543 - 1544 - if (xfer == 0) 1538 + length = xfer; 1539 + ret = iomap_iter_advance(iomi, &length); 1540 + if (!ret && xfer == 0) 1545 1541 ret = -EFAULT; 1546 1542 if (xfer < map_len) 1547 1543 break; 1548 1544 } 1549 1545 dax_read_unlock(id); 1550 1546 1551 - return done ? done : ret; 1547 + return ret; 1552 1548 } 1553 1549 1554 1550 /** ··· 1586 1586 iomi.flags |= IOMAP_NOWAIT; 1587 1587 1588 1588 while ((ret = iomap_iter(&iomi, ops)) > 0) 1589 - iomi.processed = dax_iomap_iter(&iomi, iter); 1589 + iomi.status = dax_iomap_iter(&iomi, iter); 1590 1590 1591 1591 done = iomi.pos - iocb->ki_pos; 1592 1592 iocb->ki_pos = iomi.pos; ··· 1757 1757 1758 1758 while ((error = iomap_iter(&iter, ops)) > 0) { 1759 1759 if (WARN_ON_ONCE(iomap_length(&iter) < PAGE_SIZE)) { 1760 - iter.processed = -EIO; /* fs corruption? */ 1760 + iter.status = -EIO; /* fs corruption? */ 1761 1761 continue; 1762 1762 } 1763 1763 ··· 1769 1769 ret |= VM_FAULT_MAJOR; 1770 1770 } 1771 1771 1772 - if (!(ret & VM_FAULT_ERROR)) 1773 - iter.processed = PAGE_SIZE; 1772 + if (!(ret & VM_FAULT_ERROR)) { 1773 + u64 length = PAGE_SIZE; 1774 + iter.status = iomap_iter_advance(&iter, &length); 1775 + } 1774 1776 } 1775 1777 1776 1778 if (iomap_errp) ··· 1885 1883 continue; /* actually breaks out of the loop */ 1886 1884 1887 1885 ret = dax_fault_iter(vmf, &iter, pfnp, &xas, &entry, true); 1888 - if (ret != VM_FAULT_FALLBACK) 1889 - iter.processed = PMD_SIZE; 1886 + if (ret != VM_FAULT_FALLBACK) { 1887 + u64 length = PMD_SIZE; 1888 + iter.status = iomap_iter_advance(&iter, &length); 1889 + } 1890 1890 } 1891 1891 1892 1892 unlock_entry: ··· 2003 1999 } 2004 2000 EXPORT_SYMBOL_GPL(dax_finish_sync_fault); 2005 2001 2006 - static loff_t dax_range_compare_iter(struct iomap_iter *it_src, 2002 + static int dax_range_compare_iter(struct iomap_iter *it_src, 2007 2003 struct iomap_iter *it_dest, u64 len, bool *same) 2008 2004 { 2009 2005 const struct iomap *smap = &it_src->iomap; 2010 2006 const struct iomap *dmap = &it_dest->iomap; 2011 2007 loff_t pos1 = it_src->pos, pos2 = it_dest->pos; 2008 + u64 dest_len; 2012 2009 void *saddr, *daddr; 2013 2010 int id, ret; 2014 2011 ··· 2017 2012 2018 2013 if (smap->type == IOMAP_HOLE && dmap->type == IOMAP_HOLE) { 2019 2014 *same = true; 2020 - return len; 2015 + goto advance; 2021 2016 } 2022 2017 2023 2018 if (smap->type == IOMAP_HOLE || dmap->type == IOMAP_HOLE) { ··· 2040 2035 if (!*same) 2041 2036 len = 0; 2042 2037 dax_read_unlock(id); 2043 - return len; 2038 + 2039 + advance: 2040 + dest_len = len; 2041 + ret = iomap_iter_advance(it_src, &len); 2042 + if (!ret) 2043 + ret = iomap_iter_advance(it_dest, &dest_len); 2044 + return ret; 2044 2045 2045 2046 out_unlock: 2046 2047 dax_read_unlock(id); ··· 2069 2058 .len = len, 2070 2059 .flags = IOMAP_DAX, 2071 2060 }; 2072 - int ret, compared = 0; 2061 + int ret, status; 2073 2062 2074 2063 while ((ret = iomap_iter(&src_iter, ops)) > 0 && 2075 2064 (ret = iomap_iter(&dst_iter, ops)) > 0) { 2076 - compared = dax_range_compare_iter(&src_iter, &dst_iter, 2065 + status = dax_range_compare_iter(&src_iter, &dst_iter, 2077 2066 min(src_iter.len, dst_iter.len), same); 2078 - if (compared < 0) 2067 + if (status < 0) 2079 2068 return ret; 2080 - src_iter.processed = dst_iter.processed = compared; 2069 + src_iter.status = dst_iter.status = status; 2081 2070 } 2082 2071 return ret; 2083 2072 }
+36 -42
fs/iomap/buffered-io.c
··· 362 362 pos >= i_size_read(iter->inode); 363 363 } 364 364 365 - static loff_t iomap_readpage_iter(const struct iomap_iter *iter, 366 - struct iomap_readpage_ctx *ctx, loff_t offset) 365 + static int iomap_readpage_iter(struct iomap_iter *iter, 366 + struct iomap_readpage_ctx *ctx) 367 367 { 368 368 const struct iomap *iomap = &iter->iomap; 369 - loff_t pos = iter->pos + offset; 370 - loff_t length = iomap_length(iter) - offset; 369 + loff_t pos = iter->pos; 370 + loff_t length = iomap_length(iter); 371 371 struct folio *folio = ctx->cur_folio; 372 372 struct iomap_folio_state *ifs; 373 - loff_t orig_pos = pos; 374 373 size_t poff, plen; 375 374 sector_t sector; 376 375 ··· 433 434 * we can skip trailing ones as they will be handled in the next 434 435 * iteration. 435 436 */ 436 - return pos - orig_pos + plen; 437 + length = pos - iter->pos + plen; 438 + return iomap_iter_advance(iter, &length); 437 439 } 438 440 439 - static loff_t iomap_read_folio_iter(const struct iomap_iter *iter, 441 + static int iomap_read_folio_iter(struct iomap_iter *iter, 440 442 struct iomap_readpage_ctx *ctx) 441 443 { 442 - struct folio *folio = ctx->cur_folio; 443 - size_t offset = offset_in_folio(folio, iter->pos); 444 - loff_t length = min_t(loff_t, folio_size(folio) - offset, 445 - iomap_length(iter)); 446 - loff_t done, ret; 444 + int ret; 447 445 448 - for (done = 0; done < length; done += ret) { 449 - ret = iomap_readpage_iter(iter, ctx, done); 450 - if (ret <= 0) 446 + while (iomap_length(iter)) { 447 + ret = iomap_readpage_iter(iter, ctx); 448 + if (ret) 451 449 return ret; 452 450 } 453 451 454 - return done; 452 + return 0; 455 453 } 456 454 457 455 int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops) ··· 466 470 trace_iomap_readpage(iter.inode, 1); 467 471 468 472 while ((ret = iomap_iter(&iter, ops)) > 0) 469 - iter.processed = iomap_read_folio_iter(&iter, &ctx); 473 + iter.status = iomap_read_folio_iter(&iter, &ctx); 470 474 471 475 if (ctx.bio) { 472 476 submit_bio(ctx.bio); ··· 485 489 } 486 490 EXPORT_SYMBOL_GPL(iomap_read_folio); 487 491 488 - static loff_t iomap_readahead_iter(const struct iomap_iter *iter, 492 + static int iomap_readahead_iter(struct iomap_iter *iter, 489 493 struct iomap_readpage_ctx *ctx) 490 494 { 491 - loff_t length = iomap_length(iter); 492 - loff_t done, ret; 495 + int ret; 493 496 494 - for (done = 0; done < length; done += ret) { 497 + while (iomap_length(iter)) { 495 498 if (ctx->cur_folio && 496 - offset_in_folio(ctx->cur_folio, iter->pos + done) == 0) { 499 + offset_in_folio(ctx->cur_folio, iter->pos) == 0) { 497 500 if (!ctx->cur_folio_in_bio) 498 501 folio_unlock(ctx->cur_folio); 499 502 ctx->cur_folio = NULL; ··· 501 506 ctx->cur_folio = readahead_folio(ctx->rac); 502 507 ctx->cur_folio_in_bio = false; 503 508 } 504 - ret = iomap_readpage_iter(iter, ctx, done); 505 - if (ret <= 0) 509 + ret = iomap_readpage_iter(iter, ctx); 510 + if (ret) 506 511 return ret; 507 512 } 508 513 509 - return done; 514 + return 0; 510 515 } 511 516 512 517 /** ··· 538 543 trace_iomap_readahead(rac->mapping->host, readahead_count(rac)); 539 544 540 545 while (iomap_iter(&iter, ops) > 0) 541 - iter.processed = iomap_readahead_iter(&iter, &ctx); 546 + iter.status = iomap_readahead_iter(&iter, &ctx); 542 547 543 548 if (ctx.bio) 544 549 submit_bio(ctx.bio); ··· 898 903 return __iomap_write_end(iter->inode, pos, len, copied, folio); 899 904 } 900 905 901 - static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i) 906 + static int iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i) 902 907 { 903 908 ssize_t total_written = 0; 904 - long status = 0; 909 + int status = 0; 905 910 struct address_space *mapping = iter->inode->i_mapping; 906 911 size_t chunk = mapping_max_folio_size(mapping); 907 912 unsigned int bdp_flags = (iter->flags & IOMAP_NOWAIT) ? BDP_ASYNC : 0; ··· 1021 1026 iter.flags |= IOMAP_NOWAIT; 1022 1027 1023 1028 while ((ret = iomap_iter(&iter, ops)) > 0) 1024 - iter.processed = iomap_write_iter(&iter, i); 1029 + iter.status = iomap_write_iter(&iter, i); 1025 1030 1026 1031 if (unlikely(iter.pos == iocb->ki_pos)) 1027 1032 return ret; ··· 1255 1260 } 1256 1261 EXPORT_SYMBOL_GPL(iomap_write_delalloc_release); 1257 1262 1258 - static loff_t iomap_unshare_iter(struct iomap_iter *iter) 1263 + static int iomap_unshare_iter(struct iomap_iter *iter) 1259 1264 { 1260 1265 struct iomap *iomap = &iter->iomap; 1261 1266 u64 bytes = iomap_length(iter); ··· 1315 1320 1316 1321 iter.len = min(len, size - pos); 1317 1322 while ((ret = iomap_iter(&iter, ops)) > 0) 1318 - iter.processed = iomap_unshare_iter(&iter); 1323 + iter.status = iomap_unshare_iter(&iter); 1319 1324 return ret; 1320 1325 } 1321 1326 EXPORT_SYMBOL_GPL(iomap_file_unshare); ··· 1334 1339 return filemap_write_and_wait_range(mapping, i->pos, end); 1335 1340 } 1336 1341 1337 - static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero) 1342 + static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero) 1338 1343 { 1339 1344 u64 bytes = iomap_length(iter); 1340 1345 int status; ··· 1408 1413 filemap_range_needs_writeback(mapping, pos, pos + plen - 1)) { 1409 1414 iter.len = plen; 1410 1415 while ((ret = iomap_iter(&iter, ops)) > 0) 1411 - iter.processed = iomap_zero_iter(&iter, did_zero); 1416 + iter.status = iomap_zero_iter(&iter, did_zero); 1412 1417 1413 1418 iter.len = len - (iter.pos - pos); 1414 1419 if (ret || !iter.len) ··· 1427 1432 1428 1433 if (srcmap->type == IOMAP_HOLE || 1429 1434 srcmap->type == IOMAP_UNWRITTEN) { 1430 - s64 proc; 1435 + s64 status; 1431 1436 1432 1437 if (range_dirty) { 1433 1438 range_dirty = false; 1434 - proc = iomap_zero_iter_flush_and_stale(&iter); 1439 + status = iomap_zero_iter_flush_and_stale(&iter); 1435 1440 } else { 1436 - u64 length = iomap_length(&iter); 1437 - proc = iomap_iter_advance(&iter, &length); 1441 + status = iomap_iter_advance_full(&iter); 1438 1442 } 1439 - iter.processed = proc; 1443 + iter.status = status; 1440 1444 continue; 1441 1445 } 1442 1446 1443 - iter.processed = iomap_zero_iter(&iter, did_zero); 1447 + iter.status = iomap_zero_iter(&iter, did_zero); 1444 1448 } 1445 1449 return ret; 1446 1450 } ··· 1460 1466 } 1461 1467 EXPORT_SYMBOL_GPL(iomap_truncate_page); 1462 1468 1463 - static loff_t iomap_folio_mkwrite_iter(struct iomap_iter *iter, 1469 + static int iomap_folio_mkwrite_iter(struct iomap_iter *iter, 1464 1470 struct folio *folio) 1465 1471 { 1466 1472 loff_t length = iomap_length(iter); ··· 1477 1483 folio_mark_dirty(folio); 1478 1484 } 1479 1485 1480 - return length; 1486 + return iomap_iter_advance(iter, &length); 1481 1487 } 1482 1488 1483 1489 vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops, ··· 1498 1504 iter.pos = folio_pos(folio); 1499 1505 iter.len = ret; 1500 1506 while ((ret = iomap_iter(&iter, ops)) > 0) 1501 - iter.processed = iomap_folio_mkwrite_iter(&iter, folio); 1507 + iter.status = iomap_folio_mkwrite_iter(&iter, folio); 1502 1508 1503 1509 if (ret < 0) 1504 1510 goto out_unlock;
+10 -14
fs/iomap/direct-io.c
··· 335 335 return opflags; 336 336 } 337 337 338 - static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter, 339 - struct iomap_dio *dio) 338 + static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio) 340 339 { 341 340 const struct iomap *iomap = &iter->iomap; 342 341 struct inode *inode = iter->inode; ··· 348 349 bool need_zeroout = false; 349 350 bool use_fua = false; 350 351 int nr_pages, ret = 0; 351 - size_t copied = 0; 352 + u64 copied = 0; 352 353 size_t orig_count; 353 354 354 355 if (atomic && length != fs_block_size) ··· 512 513 /* Undo iter limitation to current extent */ 513 514 iov_iter_reexpand(dio->submit.iter, orig_count - copied); 514 515 if (copied) 515 - return copied; 516 + return iomap_iter_advance(iter, &copied); 516 517 return ret; 517 518 } 518 519 519 - static loff_t iomap_dio_hole_iter(const struct iomap_iter *iter, 520 - struct iomap_dio *dio) 520 + static int iomap_dio_hole_iter(struct iomap_iter *iter, struct iomap_dio *dio) 521 521 { 522 522 loff_t length = iov_iter_zero(iomap_length(iter), dio->submit.iter); 523 523 524 524 dio->size += length; 525 525 if (!length) 526 526 return -EFAULT; 527 - return length; 527 + return iomap_iter_advance(iter, &length); 528 528 } 529 529 530 - static loff_t iomap_dio_inline_iter(const struct iomap_iter *iomi, 531 - struct iomap_dio *dio) 530 + static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio) 532 531 { 533 532 const struct iomap *iomap = &iomi->iomap; 534 533 struct iov_iter *iter = dio->submit.iter; 535 534 void *inline_data = iomap_inline_data(iomap, iomi->pos); 536 535 loff_t length = iomap_length(iomi); 537 536 loff_t pos = iomi->pos; 538 - size_t copied; 537 + u64 copied; 539 538 540 539 if (WARN_ON_ONCE(!iomap_inline_data_valid(iomap))) 541 540 return -EIO; ··· 555 558 dio->size += copied; 556 559 if (!copied) 557 560 return -EFAULT; 558 - return copied; 561 + return iomap_iter_advance(iomi, &copied); 559 562 } 560 563 561 - static loff_t iomap_dio_iter(const struct iomap_iter *iter, 562 - struct iomap_dio *dio) 564 + static int iomap_dio_iter(struct iomap_iter *iter, struct iomap_dio *dio) 563 565 { 564 566 switch (iter->iomap.type) { 565 567 case IOMAP_HOLE: ··· 742 746 743 747 blk_start_plug(&plug); 744 748 while ((ret = iomap_iter(&iomi, ops)) > 0) { 745 - iomi.processed = iomap_dio_iter(&iomi, dio); 749 + iomi.status = iomap_dio_iter(&iomi, dio); 746 750 747 751 /* 748 752 * We can only poll for single bio I/Os.
+10 -11
fs/iomap/fiemap.c
··· 39 39 iomap->length, flags); 40 40 } 41 41 42 - static loff_t iomap_fiemap_iter(const struct iomap_iter *iter, 42 + static int iomap_fiemap_iter(struct iomap_iter *iter, 43 43 struct fiemap_extent_info *fi, struct iomap *prev) 44 44 { 45 45 int ret; 46 46 47 47 if (iter->iomap.type == IOMAP_HOLE) 48 - return iomap_length(iter); 48 + goto advance; 49 49 50 50 ret = iomap_to_fiemap(fi, prev, 0); 51 51 *prev = iter->iomap; 52 - switch (ret) { 53 - case 0: /* success */ 54 - return iomap_length(iter); 55 - case 1: /* extent array full */ 56 - return 0; 57 - default: /* error */ 52 + if (ret < 0) 58 53 return ret; 59 - } 54 + if (ret == 1) /* extent array full */ 55 + return 0; 56 + 57 + advance: 58 + return iomap_iter_advance_full(iter); 60 59 } 61 60 62 61 int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, ··· 77 78 return ret; 78 79 79 80 while ((ret = iomap_iter(&iter, ops)) > 0) 80 - iter.processed = iomap_fiemap_iter(&iter, fi, &prev); 81 + iter.status = iomap_fiemap_iter(&iter, fi, &prev); 81 82 82 83 if (prev.type != IOMAP_HOLE) { 83 84 ret = iomap_to_fiemap(fi, &prev, FIEMAP_EXTENT_LAST); ··· 113 114 while ((ret = iomap_iter(&iter, ops)) > 0) { 114 115 if (iter.iomap.type == IOMAP_MAPPED) 115 116 bno = iomap_sector(&iter.iomap, iter.pos) >> blkshift; 116 - /* leave iter.processed unset to abort loop */ 117 + /* leave iter.status unset to abort loop */ 117 118 } 118 119 if (ret) 119 120 return 0;
+17 -26
fs/iomap/iter.c
··· 9 9 10 10 static inline void iomap_iter_reset_iomap(struct iomap_iter *iter) 11 11 { 12 - iter->processed = 0; 12 + iter->status = 0; 13 13 memset(&iter->iomap, 0, sizeof(iter->iomap)); 14 14 memset(&iter->srcmap, 0, sizeof(iter->srcmap)); 15 15 } ··· 54 54 * function must be called in a loop that continues as long it returns a 55 55 * positive value. If 0 or a negative value is returned, the caller must not 56 56 * return to the loop body. Within a loop body, there are two ways to break out 57 - * of the loop body: leave @iter.processed unchanged, or set it to a negative 57 + * of the loop body: leave @iter.status unchanged, or set it to a negative 58 58 * errno. 59 59 */ 60 60 int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops) 61 61 { 62 62 bool stale = iter->iomap.flags & IOMAP_F_STALE; 63 - ssize_t advanced = iter->processed > 0 ? iter->processed : 0; 64 - u64 olen = iter->len; 65 - s64 processed; 63 + ssize_t advanced; 64 + u64 olen; 66 65 int ret; 67 66 68 67 trace_iomap_iter(iter, ops, _RET_IP_); ··· 70 71 goto begin; 71 72 72 73 /* 73 - * If iter.processed is zero, the op may still have advanced the iter 74 - * itself. Calculate the advanced and original length bytes based on how 75 - * far pos has advanced for ->iomap_end(). 74 + * Calculate how far the iter was advanced and the original length bytes 75 + * for ->iomap_end(). 76 76 */ 77 - if (!advanced) { 78 - advanced = iter->pos - iter->iter_start_pos; 79 - olen += advanced; 80 - } 77 + advanced = iter->pos - iter->iter_start_pos; 78 + olen = iter->len + advanced; 81 79 82 80 if (ops->iomap_end) { 83 81 ret = ops->iomap_end(iter->inode, iter->iter_start_pos, ··· 85 89 return ret; 86 90 } 87 91 88 - processed = iter->processed; 89 - if (processed < 0) { 90 - iomap_iter_reset_iomap(iter); 91 - return processed; 92 - } 92 + /* detect old return semantics where this would advance */ 93 + if (WARN_ON_ONCE(iter->status > 0)) 94 + iter->status = -EIO; 93 95 94 96 /* 95 - * Advance the iter and clear state from the previous iteration. This 96 - * passes iter->processed because that reflects the bytes processed but 97 - * not yet advanced by the iter handler. 98 - * 99 97 * Use iter->len to determine whether to continue onto the next mapping. 100 - * Explicitly terminate in the case where the current iter has not 98 + * Explicitly terminate on error status or if the current iter has not 101 99 * advanced at all (i.e. no work was done for some reason) unless the 102 100 * mapping has been marked stale and needs to be reprocessed. 103 101 */ 104 - ret = iomap_iter_advance(iter, &processed); 105 - if (!ret && iter->len > 0) 106 - ret = 1; 107 - if (ret > 0 && !advanced && !stale) 102 + if (iter->status < 0) 103 + ret = iter->status; 104 + else if (iter->len == 0 || (!advanced && !stale)) 108 105 ret = 0; 106 + else 107 + ret = 1; 109 108 iomap_iter_reset_iomap(iter); 110 109 if (ret <= 0) 111 110 return ret;
+8 -8
fs/iomap/seek.c
··· 10 10 #include <linux/pagemap.h> 11 11 #include <linux/pagevec.h> 12 12 13 - static loff_t iomap_seek_hole_iter(const struct iomap_iter *iter, 13 + static int iomap_seek_hole_iter(struct iomap_iter *iter, 14 14 loff_t *hole_pos) 15 15 { 16 16 loff_t length = iomap_length(iter); ··· 20 20 *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, 21 21 iter->pos, iter->pos + length, SEEK_HOLE); 22 22 if (*hole_pos == iter->pos + length) 23 - return length; 23 + return iomap_iter_advance(iter, &length); 24 24 return 0; 25 25 case IOMAP_HOLE: 26 26 *hole_pos = iter->pos; 27 27 return 0; 28 28 default: 29 - return length; 29 + return iomap_iter_advance(iter, &length); 30 30 } 31 31 } 32 32 ··· 47 47 48 48 iter.len = size - pos; 49 49 while ((ret = iomap_iter(&iter, ops)) > 0) 50 - iter.processed = iomap_seek_hole_iter(&iter, &pos); 50 + iter.status = iomap_seek_hole_iter(&iter, &pos); 51 51 if (ret < 0) 52 52 return ret; 53 53 if (iter.len) /* found hole before EOF */ ··· 56 56 } 57 57 EXPORT_SYMBOL_GPL(iomap_seek_hole); 58 58 59 - static loff_t iomap_seek_data_iter(const struct iomap_iter *iter, 59 + static int iomap_seek_data_iter(struct iomap_iter *iter, 60 60 loff_t *hole_pos) 61 61 { 62 62 loff_t length = iomap_length(iter); 63 63 64 64 switch (iter->iomap.type) { 65 65 case IOMAP_HOLE: 66 - return length; 66 + return iomap_iter_advance(iter, &length); 67 67 case IOMAP_UNWRITTEN: 68 68 *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, 69 69 iter->pos, iter->pos + length, SEEK_DATA); 70 70 if (*hole_pos < 0) 71 - return length; 71 + return iomap_iter_advance(iter, &length); 72 72 return 0; 73 73 default: 74 74 *hole_pos = iter->pos; ··· 93 93 94 94 iter.len = size - pos; 95 95 while ((ret = iomap_iter(&iter, ops)) > 0) 96 - iter.processed = iomap_seek_data_iter(&iter, &pos); 96 + iter.status = iomap_seek_data_iter(&iter, &pos); 97 97 if (ret < 0) 98 98 return ret; 99 99 if (iter.len) /* found data before EOF */
+4 -3
fs/iomap/swapfile.c
··· 94 94 * swap only cares about contiguous page-aligned physical extents and makes no 95 95 * distinction between written and unwritten extents. 96 96 */ 97 - static loff_t iomap_swapfile_iter(const struct iomap_iter *iter, 97 + static int iomap_swapfile_iter(struct iomap_iter *iter, 98 98 struct iomap *iomap, struct iomap_swapfile_info *isi) 99 99 { 100 100 switch (iomap->type) { ··· 132 132 return error; 133 133 memcpy(&isi->iomap, iomap, sizeof(isi->iomap)); 134 134 } 135 - return iomap_length(iter); 135 + 136 + return iomap_iter_advance_full(iter); 136 137 } 137 138 138 139 /* ··· 167 166 return ret; 168 167 169 168 while ((ret = iomap_iter(&iter, ops)) > 0) 170 - iter.processed = iomap_swapfile_iter(&iter, &iter.iomap, &isi); 169 + iter.status = iomap_swapfile_iter(&iter, &iter.iomap, &isi); 171 170 if (ret < 0) 172 171 return ret; 173 172
+4 -4
fs/iomap/trace.h
··· 207 207 __field(u64, ino) 208 208 __field(loff_t, pos) 209 209 __field(u64, length) 210 - __field(s64, processed) 210 + __field(int, status) 211 211 __field(unsigned int, flags) 212 212 __field(const void *, ops) 213 213 __field(unsigned long, caller) ··· 217 217 __entry->ino = iter->inode->i_ino; 218 218 __entry->pos = iter->pos; 219 219 __entry->length = iomap_length(iter); 220 - __entry->processed = iter->processed; 220 + __entry->status = iter->status; 221 221 __entry->flags = iter->flags; 222 222 __entry->ops = ops; 223 223 __entry->caller = caller; 224 224 ), 225 - TP_printk("dev %d:%d ino 0x%llx pos 0x%llx length 0x%llx processed %lld flags %s (0x%x) ops %ps caller %pS", 225 + TP_printk("dev %d:%d ino 0x%llx pos 0x%llx length 0x%llx status %d flags %s (0x%x) ops %ps caller %pS", 226 226 MAJOR(__entry->dev), MINOR(__entry->dev), 227 227 __entry->ino, 228 228 __entry->pos, 229 229 __entry->length, 230 - __entry->processed, 230 + __entry->status, 231 231 __print_flags(__entry->flags, "|", IOMAP_FLAGS_STRINGS), 232 232 __entry->flags, 233 233 __entry->ops,
+13 -4
include/linux/iomap.h
··· 220 220 * It is updated at the same time as @pos. 221 221 * @iter_start_pos: The original start pos for the current iomap. Used for 222 222 * incremental iter advance. 223 - * @processed: The number of bytes the most recent iteration needs iomap_iter() 224 - * to advance the iter, zero if the iter was already advanced, or a 225 - * negative errno for an error during the operation. 223 + * @status: Status of the most recent iteration. Zero on success or a negative 224 + * errno on error. 226 225 * @flags: Zero or more of the iomap_begin flags above. 227 226 * @iomap: Map describing the I/O iteration 228 227 * @srcmap: Source map for COW operations ··· 231 232 loff_t pos; 232 233 u64 len; 233 234 loff_t iter_start_pos; 234 - s64 processed; 235 + int status; 235 236 unsigned flags; 236 237 struct iomap iomap; 237 238 struct iomap srcmap; ··· 269 270 static inline u64 iomap_length(const struct iomap_iter *iter) 270 271 { 271 272 return iomap_length_trim(iter, iter->pos, iter->len); 273 + } 274 + 275 + /** 276 + * iomap_iter_advance_full - advance by the full length of current map 277 + */ 278 + static inline int iomap_iter_advance_full(struct iomap_iter *iter) 279 + { 280 + u64 length = iomap_length(iter); 281 + 282 + return iomap_iter_advance(iter, &length); 272 283 } 273 284 274 285 /**