Skip to content

Commit f8eaf79

Browse files
joannekoongbrauner
authored andcommitted
iomap: simplify ->read_folio_range() error handling for reads
Instead of requiring that the caller calls iomap_finish_folio_read() even if the ->read_folio_range() callback returns an error, account for this internally in iomap instead, which makes the interface simpler and makes it match writeback's ->read_folio_range() error handling expectations. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20251111193658.3495942-6-joannelkoong@gmail.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 6b1fd22 commit f8eaf79

4 files changed

Lines changed: 41 additions & 44 deletions

File tree

Documentation/filesystems/iomap/operations.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,9 @@ These ``struct kiocb`` flags are significant for buffered I/O with iomap:
149149
iomap calls these functions:
150150

151151
- ``read_folio_range``: Called to read in the range. This must be provided
152-
by the caller. The caller is responsible for calling
153-
iomap_finish_folio_read() after reading in the folio range. This should be
154-
done even if an error is encountered during the read. This returns 0 on
155-
success or a negative error on failure.
152+
by the caller. If this succeeds, iomap_finish_folio_read() must be called
153+
after the range is read in, regardless of whether the read succeeded or
154+
failed.
156155

157156
- ``submit_read``: Submit any pending read requests. This function is
158157
optional.

fs/fuse/file.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -922,21 +922,15 @@ static int fuse_iomap_read_folio_range_async(const struct iomap_iter *iter,
922922

923923
if (ctx->rac) {
924924
ret = fuse_handle_readahead(folio, ctx->rac, data, pos, len);
925-
/*
926-
* If fuse_handle_readahead was successful, fuse_readpages_end
927-
* will do the iomap_finish_folio_read, else we need to call it
928-
* here
929-
*/
930-
if (ret)
931-
iomap_finish_folio_read(folio, off, len, ret);
932925
} else {
933926
/*
934927
* for non-readahead read requests, do reads synchronously
935928
* since it's not guaranteed that the server can handle
936929
* out-of-order reads
937930
*/
938931
ret = fuse_do_readfolio(file, folio, off, len);
939-
iomap_finish_folio_read(folio, off, len, ret);
932+
if (!ret)
933+
iomap_finish_folio_read(folio, off, len, ret);
940934
}
941935
return ret;
942936
}

fs/iomap/buffered-io.c

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ static void iomap_read_init(struct folio *folio)
398398
* has already finished reading in the entire folio.
399399
*/
400400
spin_lock_irq(&ifs->state_lock);
401-
ifs->read_bytes_pending += len + 1;
401+
WARN_ON_ONCE(ifs->read_bytes_pending != 0);
402+
ifs->read_bytes_pending = len + 1;
402403
spin_unlock_irq(&ifs->state_lock);
403404
}
404405
}
@@ -414,43 +415,47 @@ static void iomap_read_init(struct folio *folio)
414415
*/
415416
static void iomap_read_end(struct folio *folio, size_t bytes_submitted)
416417
{
417-
struct iomap_folio_state *ifs;
418-
419-
/*
420-
* If there are no bytes submitted, this means we are responsible for
421-
* unlocking the folio here, since no IO helper has taken ownership of
422-
* it.
423-
*/
424-
if (!bytes_submitted) {
425-
folio_unlock(folio);
426-
return;
427-
}
418+
struct iomap_folio_state *ifs = folio->private;
428419

429-
ifs = folio->private;
430420
if (ifs) {
431421
bool end_read, uptodate;
432-
/*
433-
* Subtract any bytes that were initially accounted to
434-
* read_bytes_pending but skipped for IO.
435-
* The +1 accounts for the bias we added in iomap_read_init().
436-
*/
437-
size_t bytes_not_submitted = folio_size(folio) + 1 -
438-
bytes_submitted;
439422

440423
spin_lock_irq(&ifs->state_lock);
441-
ifs->read_bytes_pending -= bytes_not_submitted;
442-
/*
443-
* If !ifs->read_bytes_pending, this means all pending reads
444-
* by the IO helper have already completed, which means we need
445-
* to end the folio read here. If ifs->read_bytes_pending != 0,
446-
* the IO helper will end the folio read.
447-
*/
448-
end_read = !ifs->read_bytes_pending;
424+
if (!ifs->read_bytes_pending) {
425+
WARN_ON_ONCE(bytes_submitted);
426+
end_read = true;
427+
} else {
428+
/*
429+
* Subtract any bytes that were initially accounted to
430+
* read_bytes_pending but skipped for IO. The +1
431+
* accounts for the bias we added in iomap_read_init().
432+
*/
433+
size_t bytes_not_submitted = folio_size(folio) + 1 -
434+
bytes_submitted;
435+
ifs->read_bytes_pending -= bytes_not_submitted;
436+
/*
437+
* If !ifs->read_bytes_pending, this means all pending
438+
* reads by the IO helper have already completed, which
439+
* means we need to end the folio read here. If
440+
* ifs->read_bytes_pending != 0, the IO helper will end
441+
* the folio read.
442+
*/
443+
end_read = !ifs->read_bytes_pending;
444+
}
449445
if (end_read)
450446
uptodate = ifs_is_fully_uptodate(folio, ifs);
451447
spin_unlock_irq(&ifs->state_lock);
452448
if (end_read)
453449
folio_end_read(folio, uptodate);
450+
} else if (!bytes_submitted) {
451+
/*
452+
* If there were no bytes submitted, this means we are
453+
* responsible for unlocking the folio here, since no IO helper
454+
* has taken ownership of it. If there were bytes submitted,
455+
* then the IO helper will end the read via
456+
* iomap_finish_folio_read().
457+
*/
458+
folio_unlock(folio);
454459
}
455460
}
456461

@@ -498,10 +503,10 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
498503
} else {
499504
if (!*bytes_submitted)
500505
iomap_read_init(folio);
501-
*bytes_submitted += plen;
502506
ret = ctx->ops->read_folio_range(iter, ctx, plen);
503507
if (ret)
504508
return ret;
509+
*bytes_submitted += plen;
505510
}
506511

507512
ret = iomap_iter_advance(iter, plen);

include/linux/iomap.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,8 @@ struct iomap_read_ops {
495495
/*
496496
* Read in a folio range.
497497
*
498-
* The caller is responsible for calling iomap_finish_folio_read() after
499-
* reading in the folio range. This should be done even if an error is
500-
* encountered during the read.
498+
* If this succeeds, iomap_finish_folio_read() must be called after the
499+
* range is read in, regardless of whether the read succeeded or failed.
501500
*
502501
* Returns 0 on success or a negative error on failure.
503502
*/

0 commit comments

Comments
 (0)