diff options
author | Brian Foster <bfoster@redhat.com> | 2023-08-14 16:49:42 +0200 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 23:10:11 +0200 |
commit | 8c9b0f7bdc4183573d57f0442693d99cc9758617 (patch) | |
tree | cefa2eeb55d171b36a7994cf27e4e8511d298b14 /fs/bcachefs/fs-io-pagecache.c | |
parent | bcachefs: Fix bkey format calculation (diff) | |
download | linux-8c9b0f7bdc4183573d57f0442693d99cc9758617.tar.xz linux-8c9b0f7bdc4183573d57f0442693d99cc9758617.zip |
bcachefs: fix up wonky error handling in bch2_seek_pagecache_hole()
The folio_hole_offset() helper returns a mix of bool and int types.
The latter is to support a possible -EAGAIN error code when using
nonblocking locks. This is not only confusing, but the only caller
also essentially ignores errors outside of stopping the range
iteration. This means an -EAGAIN error can't return directly from
folio_hole_offset() and may be lost via bch2_clamp_data_hole().
Fix up the error handling and make it more readable.
__filemap_get_folio() returns -ENOENT instead of NULL when no folio
exists, so reuse the same error code in folio_hole_offset(). Fix up
bch2_seek_pagecache_hole() to return the current offset on -ENOENT,
but otherwise return unexpected error code up to the caller.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to '')
-rw-r--r-- | fs/bcachefs/fs-io-pagecache.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/bcachefs/fs-io-pagecache.c b/fs/bcachefs/fs-io-pagecache.c index 2c1ef13d9bcd..1e60eead2981 100644 --- a/fs/bcachefs/fs-io-pagecache.c +++ b/fs/bcachefs/fs-io-pagecache.c @@ -698,20 +698,26 @@ loff_t bch2_seek_pagecache_data(struct inode *vinode, return end_offset; } +/* + * Search for a hole in a folio. + * + * The filemap layer returns -ENOENT if no folio exists, so reuse the same error + * code to indicate a pagecache hole exists at the returned offset. Otherwise + * return 0 if the folio is filled with data, or an error code. This function + * can return -EAGAIN if nonblock is specified. + */ static int folio_hole_offset(struct address_space *mapping, loff_t *offset, unsigned min_replicas, bool nonblock) { struct folio *folio; struct bch_folio *s; unsigned i, sectors; - bool ret = true; + int ret = -ENOENT; folio = __filemap_get_folio(mapping, *offset >> PAGE_SHIFT, FGP_LOCK|(nonblock ? FGP_NOWAIT : 0), 0); - if (folio == ERR_PTR(-EAGAIN)) - return -EAGAIN; - if (IS_ERR_OR_NULL(folio)) - return true; + if (IS_ERR(folio)) + return PTR_ERR(folio); s = bch2_folio(folio); if (!s) @@ -727,7 +733,7 @@ static int folio_hole_offset(struct address_space *mapping, loff_t *offset, } *offset = folio_end_pos(folio); - ret = false; + ret = 0; unlock: folio_unlock(folio); folio_put(folio); @@ -742,11 +748,13 @@ loff_t bch2_seek_pagecache_hole(struct inode *vinode, { struct address_space *mapping = vinode->i_mapping; loff_t offset = start_offset; + loff_t ret = 0; - while (offset < end_offset && - !folio_hole_offset(mapping, &offset, min_replicas, nonblock)) - ; + while (!ret && offset < end_offset) + ret = folio_hole_offset(mapping, &offset, min_replicas, nonblock); + if (ret && ret != -ENOENT) + return ret; return min(offset, end_offset); } |