From: Eric Sandeen <sandeen@redhat.com>
To: linux-xfs@vger.kernel.org
Cc: djwong@kernel.org, aalbersh@kernel.org,
Eric Sandeen <sandeen@redhat.com>
Subject: [PATCH 2/3] libxfs: Return -ENOMEM on actual cache node allocation failures
Date: Fri, 25 Sep 2026 14:41:44 -0500 [thread overview]
Message-ID: <20260925194535.397036-3-sandeen@redhat.com> (raw)
In-Reply-To: <20260925194535.397036-1-sandeen@redhat.com>
Today, if we get an underlying ENOMEM from an actual cache node
allocation attempt, it's indistinguishable from "current cache size
is filled" and we'll keep doubling cache size to no avail until the
size itself overflows.
This patch differentiates "no node returned" between the "cache full;
grow it" case and the "underlying allocation actually got ENOMEM" case
so that the caller can do the right thing, and return true ENOMEM
up the stack for callers to handle.
Finally, actually check this returned error at the cache_node_get
callsite (in __cache_lookup).
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
libxfs/cache.c | 22 ++++++++++++++++------
libxfs/rdwr.c | 9 ++++-----
2 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/libxfs/cache.c b/libxfs/cache.c
index a6dabf92..60bfcdc5 100644
--- a/libxfs/cache.c
+++ b/libxfs/cache.c
@@ -285,7 +285,8 @@ cache_shake(
* Allocate a new hash node (updating atomic counter in the process),
* unless doing so will push us over the maximum cache size.
* Return 1 with nodep set on success.
- * Return 0 and NULL nodep otherwise (cache full, or alloc failure)
+ * Return 0 and NULL nodep if the cache is full (caller should shake/expand).
+ * Return -ENOMEM and NULL nodep if the underlying allocation failed.
*/
static int
cache_node_allocate(
@@ -315,7 +316,7 @@ cache_node_allocate(
cache->c_count--;
pthread_mutex_unlock(&cache->c_mutex);
*nodep = NULL;
- return 0;
+ return -ENOMEM;
}
pthread_mutex_init(&node->cn_mutex, NULL);
list_head_init(&node->cn_mru);
@@ -373,8 +374,8 @@ __cache_node_purge(
* hit, in which case this will all be over quickly and painlessly.
* Otherwise, we allocate a new node, taking care not to expand the
* cache beyond the requested maximum size (shrink it if it would).
- * Returns zero if hit in cache, one if a new node was allocated. A node
- * is always returned.
+ * Returns zero if hit in cache, one if a new node was allocated. Returns
+ * -ENOMEM if allocation fails after cache shaking is exhausted.
*/
int
cache_node_get(
@@ -391,6 +392,7 @@ cache_node_get(
unsigned int hashidx;
int priority = 0;
int purged = 0;
+ int error = 0;
hashidx = cache->hash(key, cache->c_hashsize, cache->c_hashshift);
hash = cache->c_hash + hashidx;
@@ -464,8 +466,8 @@ next_object:
/*
* not found, allocate a new entry
*/
- cache_node_allocate(cache, key, &node);
- if (node)
+ error = cache_node_allocate(cache, key, &node);
+ if (error > 0)
break;
priority = cache_shake(cache, priority, false);
@@ -475,6 +477,14 @@ next_object:
* If we exceed CACHE_MAX_PRIORITY all slots are full; grow it.
*/
if (priority > CACHE_MAX_PRIORITY) {
+ /*
+ * We've shaken every priority level. If the last
+ * attempt failed with a real ENOMEM rather than a
+ * full cache, neither shaking nor growing can help;
+ * return the error to the caller.
+ */
+ if (error < 0)
+ return error;
priority = 0;
cache_expand(cache);
}
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 90f2d566..d8ba832e 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -411,17 +411,16 @@ __cache_lookup(
struct cache_node *cn = NULL;
struct cache *bcache = key->buftarg->bcache;
struct xfs_buf *bp;
+ int ret;
*bpp = NULL;
- cache_node_get(bcache, key, &cn);
- if (!cn)
- return -ENOMEM;
+ ret = cache_node_get(bcache, key, &cn);
+ if (ret < 0)
+ return ret;
bp = container_of(cn, struct xfs_buf, b_node);
if (use_xfs_buf_lock) {
- int ret;
-
ret = pthread_mutex_trylock(&bp->b_lock);
if (ret) {
ASSERT(ret == EAGAIN);
--
2.55.0
next prev parent reply other threads:[~2026-09-25 19:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 19:41 [PATCH 0/3 V3] libxfs: better cache allocation error handling Eric Sandeen
2026-09-25 19:41 ` [PATCH 1/3] libxfs: change cache_node_allocate function signature Eric Sandeen
2026-09-25 22:56 ` Darrick J. Wong
2026-09-25 19:41 ` Eric Sandeen [this message]
2026-09-25 22:58 ` [PATCH 2/3] libxfs: Return -ENOMEM on actual cache node allocation failures Darrick J. Wong
2026-09-28 15:07 ` Eric Sandeen
2026-09-25 19:41 ` [PATCH 3/3] libxfs: do not allow cache growth to overflow Eric Sandeen
2026-09-25 22:59 ` Darrick J. Wong
2026-09-28 8:16 ` [PATCH 0/3 V3] libxfs: better cache allocation error handling Christoph Hellwig
2026-09-28 15:05 ` Eric Sandeen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925194535.397036-3-sandeen@redhat.com \
--to=sandeen@redhat.com \
--cc=aalbersh@kernel.org \
--cc=djwong@kernel.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox