Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-microblaze.git] / block / blk-cgroup.c
index 031114d..4221a15 100644 (file)
@@ -1016,6 +1016,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)) {
@@ -1023,14 +1025,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);