summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2023-08-14 10:49:42 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-08-14 12:28:45 -0400
commit8af6a023de5eac32af8f73b7f59807213d5d5b78 (patch)
tree5e578759d7184b9e947d7abfae96c33d7a117c45
parent2ff2b9ebbace8073e7c6a9290dc2da7705beda96 (diff)
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>
-rw-r--r--fs/bcachefs/fs-io-pagecache.c26
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);
}