diff options
author | Christoph Hellwig <hch@lst.de> | 2023-02-09 06:35:23 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2023-02-09 08:11:11 -0700 |
commit | dcb52201435197c56154ff7c8cb139284d254bda (patch) | |
tree | 729c4c8733af24b27dacf8bf2f4ef570e6b94dd7 /block | |
parent | c43332fe028c252a2a28e46be70a530f64fc3c9d (diff) | |
download | linux-rpi-dcb52201435197c56154ff7c8cb139284d254bda.tar.gz linux-rpi-dcb52201435197c56154ff7c8cb139284d254bda.tar.bz2 linux-rpi-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')
-rw-r--r-- | block/blk-cgroup.c | 27 |
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); } /* |