OSDN Git Service

Revert "blk-cgroup: simplify blkg freeing from initialization failure paths"
authorChristoph Hellwig <hch@lst.de>
Thu, 9 Feb 2023 05:35:23 +0000 (06:35 +0100)
committerJens Axboe <axboe@kernel.dk>
Thu, 9 Feb 2023 15:11:11 +0000 (08:11 -0700)
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>
block/blk-cgroup.c

index d8fe607..9350289 100644 (file)
@@ -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);
 }
 
 /*