From 8c9b0f7bdc4183573d57f0442693d99cc9758617 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Mon, 14 Aug 2023 10:49:42 -0400 Subject: [PATCH] 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 Signed-off-by: Kent Overstreet --- fs/bcachefs/fs-io-pagecache.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/bcachefs/fs-io-pagecache.c b/fs/bcachefs/fs-io-pagecache.c index 2c1ef13d9bcdb..1e60eead29815 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); } -- 2.30.2