Merge tag 'for-5.12/block-2021-02-17' of git://git.kernel.dk/linux-block
[sfrench/cifs-2.6.git] / block / blk-cgroup.c
index f26a8415172a3bdc8ae825203a5a80a1018be426..a317c03d40f6e1ff6a1f4aa5b7f0f214665e63b7 100644 (file)
@@ -1014,6 +1014,8 @@ static void blkcg_css_offline(struct cgroup_subsys_state *css)
  */
 void blkcg_destroy_blkgs(struct blkcg *blkcg)
 {
+       might_sleep();
+
        spin_lock_irq(&blkcg->lock);
 
        while (!hlist_empty(&blkcg->blkg_list)) {
@@ -1021,14 +1023,20 @@ void blkcg_destroy_blkgs(struct blkcg *blkcg)
                                                struct blkcg_gq, blkcg_node);
                struct request_queue *q = blkg->q;
 
-               if (spin_trylock(&q->queue_lock)) {
-                       blkg_destroy(blkg);
-                       spin_unlock(&q->queue_lock);
-               } else {
+               if (need_resched() || !spin_trylock(&q->queue_lock)) {
+                       /*
+                        * Given that the system can accumulate a huge number
+                        * of blkgs in pathological cases, check to see if we
+                        * need to rescheduling to avoid softlockup.
+                        */
                        spin_unlock_irq(&blkcg->lock);
-                       cpu_relax();
+                       cond_resched();
                        spin_lock_irq(&blkcg->lock);
+                       continue;
                }
+
+               blkg_destroy(blkg);
+               spin_unlock(&q->queue_lock);
        }
 
        spin_unlock_irq(&blkcg->lock);