UPSTREAM: dt-bindings: rockchip-thermal: fix the misleading description
[firefly-linux-kernel-4.4.55.git] / mm / backing-dev.c
index 8ed2ffd963c53b910f91e1b60b04c56385a3129f..9ef80bf441b37ffed8eaed66383261859ebd3623 100644 (file)
@@ -825,6 +825,20 @@ int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
 }
 EXPORT_SYMBOL(bdi_register_dev);
 
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
+{
+       int rc;
+
+       rc = bdi_register(bdi, NULL, "%u:%u", MAJOR(owner->devt),
+                       MINOR(owner->devt));
+       if (rc)
+               return rc;
+       bdi->owner = owner;
+       get_device(owner);
+       return 0;
+}
+EXPORT_SYMBOL(bdi_register_owner);
+
 /*
  * Remove bdi from bdi_list, and ensure that it is no longer visible
  */
@@ -849,6 +863,11 @@ void bdi_unregister(struct backing_dev_info *bdi)
                device_unregister(bdi->dev);
                bdi->dev = NULL;
        }
+
+       if (bdi->owner) {
+               put_device(bdi->owner);
+               bdi->owner = NULL;
+       }
 }
 
 void bdi_exit(struct backing_dev_info *bdi)
@@ -957,8 +976,9 @@ EXPORT_SYMBOL(congestion_wait);
  * jiffies for either a BDI to exit congestion of the given @sync queue
  * or a write to complete.
  *
- * In the absence of zone congestion, cond_resched() is called to yield
- * the processor if necessary but otherwise does not sleep.
+ * In the absence of zone congestion, a short sleep or a cond_resched is
+ * performed to yield the processor and to allow other subsystems to make
+ * a forward progress.
  *
  * The return value is 0 if the sleep is for the full timeout. Otherwise,
  * it is the number of jiffies that were still remaining when the function
@@ -978,7 +998,19 @@ long wait_iff_congested(struct zone *zone, int sync, long timeout)
         */
        if (atomic_read(&nr_wb_congested[sync]) == 0 ||
            !test_bit(ZONE_CONGESTED, &zone->flags)) {
-               cond_resched();
+
+               /*
+                * Memory allocation/reclaim might be called from a WQ
+                * context and the current implementation of the WQ
+                * concurrency control doesn't recognize that a particular
+                * WQ is congested if the worker thread is looping without
+                * ever sleeping. Therefore we have to do a short sleep
+                * here rather than calling cond_resched().
+                */
+               if (current->flags & PF_WQ_WORKER)
+                       schedule_timeout_uninterruptible(1);
+               else
+                       cond_resched();
 
                /* In case we scheduled, work out time remaining */
                ret = timeout - (jiffies - start);