summaryrefslogtreecommitdiff
path: root/block/blk-cgroup.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2023-02-09 06:35:23 +0100
committerJens Axboe <axboe@kernel.dk>2023-02-09 08:11:11 -0700
commitdcb52201435197c56154ff7c8cb139284d254bda (patch)
tree729c4c8733af24b27dacf8bf2f4ef570e6b94dd7 /block/blk-cgroup.c
parentc43332fe028c252a2a28e46be70a530f64fc3c9d (diff)
downloadlwn-dcb52201435197c56154ff7c8cb139284d254bda.tar.gz
lwn-dcb52201435197c56154ff7c8cb139284d254bda.zip
Revert "blk-cgroup: simplify blkg freeing from initialization failure paths"
It turns out this was too soon. blkg_conf_prep does to funky locking games with the queue lock for this to work properly. This reverts commit 27b642b07a4a5eb44dffa94a5171ce468bdc46f9. Reported-by: Dan Carpenter <error27@gmail.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20230209053523.437927-1-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-cgroup.c')
-rw-r--r--block/blk-cgroup.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index d8fe607138b9..935028912e7a 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -114,8 +114,10 @@ static bool blkcg_policy_enabled(struct gendisk *disk,
return pol && test_bit(pol->plid, disk->blkcg_pols);
}
-static void blkg_free(struct blkcg_gq *blkg)
+static void blkg_free_workfn(struct work_struct *work)
{
+ struct blkcg_gq *blkg = container_of(work, struct blkcg_gq,
+ free_work);
int i;
/*
@@ -140,9 +142,23 @@ static void blkg_free(struct blkcg_gq *blkg)
kfree(blkg);
}
-static void blkg_free_workfn(struct work_struct *work)
+/**
+ * blkg_free - free a blkg
+ * @blkg: blkg to free
+ *
+ * Free @blkg which may be partially allocated.
+ */
+static void blkg_free(struct blkcg_gq *blkg)
{
- blkg_free(container_of(work, struct blkcg_gq, free_work));
+ if (!blkg)
+ return;
+
+ /*
+ * Both ->pd_free_fn() and request queue's release handler may
+ * sleep, so free us by scheduling one work func
+ */
+ INIT_WORK(&blkg->free_work, blkg_free_workfn);
+ schedule_work(&blkg->free_work);
}
static void __blkg_release(struct rcu_head *rcu)
@@ -153,10 +169,7 @@ static void __blkg_release(struct rcu_head *rcu)
/* release the blkcg and parent blkg refs this blkg has been holding */
css_put(&blkg->blkcg->css);
-
- /* ->pd_free_fn() may sleep, so free from a work queue */
- INIT_WORK(&blkg->free_work, blkg_free_workfn);
- schedule_work(&blkg->free_work);
+ blkg_free(blkg);
}
/*