[PATCH RESEND] bcache: Release the cache kobject when cache_alloc() fails
From: Wentao Liang
Date: Tue Nov 03 2026 - 05:02:02 EST
cache_alloc() initializes ca->kobj with kobject_init(), which takes the
initial reference on the kobject, and takes a reference on the bcache
module. The object is released later by bch_cache_release(), which also
drops the block device, puts the super block folio, frees ca and drops
the module reference.
When one of the allocations in cache_alloc() fails, the function frees
only the buffers it managed to allocate and returns an error.
register_cache() then only calls fput() on the block device and returns,
so the reference taken by kobject_init() is never dropped: ca is leaked
together with the super block folio and the module reference. The
comment on that path still claims that ca->kobj is not initialized, but
kobject_init() is the first thing cache_alloc() does.
Put ca->kobj on that path so that bch_cache_release() runs and releases
everything. bch_cache_release() frees ca->buckets and ca->prio_buckets
as well, so clear those pointers in cache_alloc() after freeing them, and
drop the module_put() from the error path because the module reference is
now released by bch_cache_release(). Skip the bucket page free in
bch_cache_release() when cache_alloc() failed before allocating them.
Fixes: cafe56359144 ("bcache: A block layer cache")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: DeepSeek-V4.1-Flash and OpenAI Codex
Signed-off-by: Wentao Liang <vulab@xxxxxxxxxxx>
---
drivers/md/bcache/super.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 97d9adb0bf96..5d4975873c2e 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -2221,7 +2221,9 @@ void bch_cache_release(struct kobject *kobj)
ca->set->cache = NULL;
}
- free_pages((unsigned long) ca->disk_buckets, ilog2(meta_bucket_pages(&ca->sb)));
+ if (ca->disk_buckets)
+ free_pages((unsigned long) ca->disk_buckets,
+ ilog2(meta_bucket_pages(&ca->sb)));
kfree(ca->prio_buckets);
vfree(ca->buckets);
@@ -2364,8 +2366,10 @@ static int cache_alloc(struct cache *ca)
err_disk_buckets_alloc:
kfree(ca->prio_buckets);
+ ca->prio_buckets = NULL;
err_prio_buckets_alloc:
vfree(ca->buckets);
+ ca->buckets = NULL;
err_buckets_alloc:
free_heap(&ca->heap);
err_heap_alloc:
@@ -2380,7 +2384,10 @@ static int cache_alloc(struct cache *ca)
free_fifo(&ca->free[RESERVE_BTREE]);
err_btree_alloc:
err_free:
- module_put(THIS_MODULE);
+ /*
+ * The module reference taken above is dropped by
+ * bch_cache_release() when the caller puts ca->kobj.
+ */
if (err)
pr_notice("error %pg: %s\n", ca->bdev, err);
return ret;
@@ -2408,13 +2415,12 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
err = "cache_alloc(): unknown error";
pr_notice("error %pg: %s\n", file_bdev(bdev_file), err);
/*
- * If we failed here, it means ca->kobj is not initialized yet,
- * kobject_put() won't be called and there is no chance to
- * call fput() to bdev in bch_cache_release(). So
- * we explicitly call fput() on the block device here.
+ * cache_alloc() has already released the buffers it
+ * allocated, so go through out: to drop the reference
+ * taken by kobject_init(); bch_cache_release() then frees
+ * ca and drops the block device and the super block folio.
*/
- fput(bdev_file);
- return ret;
+ goto out;
}
if (kobject_add(&ca->kobj, bdev_kobj(file_bdev(bdev_file)), "bcache")) {
--
2.34.1