misc: tizen-inform-reboot: Remove force_uaccess begin and end func
[platform/kernel/linux-rpi.git] / block / blk-iocost.c
index c2d6bc8..069193d 100644 (file)
@@ -1440,16 +1440,17 @@ static int iocg_wake_fn(struct wait_queue_entry *wq_entry, unsigned mode,
                return -1;
 
        iocg_commit_bio(ctx->iocg, wait->bio, wait->abs_cost, cost);
+       wait->committed = true;
 
        /*
         * autoremove_wake_function() removes the wait entry only when it
-        * actually changed the task state.  We want the wait always
-        * removed.  Remove explicitly and use default_wake_function().
+        * actually changed the task state. We want the wait always removed.
+        * Remove explicitly and use default_wake_function(). Note that the
+        * order of operations is important as finish_wait() tests whether
+        * @wq_entry is removed without grabbing the lock.
         */
-       list_del_init(&wq_entry->entry);
-       wait->committed = true;
-
        default_wake_function(wq_entry, mode, flags, key);
+       list_del_init_careful(&wq_entry->entry);
        return 0;
 }
 
@@ -2310,11 +2311,28 @@ static void ioc_timer_fn(struct timer_list *timer)
                        hwm = current_hweight_max(iocg);
                        new_hwi = hweight_after_donation(iocg, old_hwi, hwm,
                                                         usage, &now);
-                       if (new_hwi < hwm) {
+                       /*
+                        * Donation calculation assumes hweight_after_donation
+                        * to be positive, a condition that a donor w/ hwa < 2
+                        * can't meet. Don't bother with donation if hwa is
+                        * below 2. It's not gonna make a meaningful difference
+                        * anyway.
+                        */
+                       if (new_hwi < hwm && hwa >= 2) {
                                iocg->hweight_donating = hwa;
                                iocg->hweight_after_donation = new_hwi;
                                list_add(&iocg->surplus_list, &surpluses);
-                       } else {
+                       } else if (!iocg->abs_vdebt) {
+                               /*
+                                * @iocg doesn't have enough to donate. Reset
+                                * its inuse to active.
+                                *
+                                * Don't reset debtors as their inuse's are
+                                * owned by debt handling. This shouldn't affect
+                                * donation calculuation in any meaningful way
+                                * as @iocg doesn't have a meaningful amount of
+                                * share anyway.
+                                */
                                TRACE_IOCG_PATH(inuse_shortage, iocg, &now,
                                                iocg->inuse, iocg->active,
                                                iocg->hweight_inuse, new_hwi);
@@ -2875,15 +2893,21 @@ static int blk_iocost_init(struct request_queue *q)
         * called before policy activation completion, can't assume that the
         * target bio has an iocg associated and need to test for NULL iocg.
         */
-       rq_qos_add(q, rqos);
+       ret = rq_qos_add(q, rqos);
+       if (ret)
+               goto err_free_ioc;
+
        ret = blkcg_activate_policy(q, &blkcg_policy_iocost);
-       if (ret) {
-               rq_qos_del(q, rqos);
-               free_percpu(ioc->pcpu_stat);
-               kfree(ioc);
-               return ret;
-       }
+       if (ret)
+               goto err_del_qos;
        return 0;
+
+err_del_qos:
+       rq_qos_del(q, rqos);
+err_free_ioc:
+       free_percpu(ioc->pcpu_stat);
+       kfree(ioc);
+       return ret;
 }
 
 static struct blkcg_policy_data *ioc_cpd_alloc(gfp_t gfp)
@@ -2987,34 +3011,29 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
        kfree(iocg);
 }
 
-static size_t ioc_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
+static bool ioc_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
 {
        struct ioc_gq *iocg = pd_to_iocg(pd);
        struct ioc *ioc = iocg->ioc;
-       size_t pos = 0;
 
        if (!ioc->enabled)
-               return 0;
+               return false;
 
        if (iocg->level == 0) {
                unsigned vp10k = DIV64_U64_ROUND_CLOSEST(
                        ioc->vtime_base_rate * 10000,
                        VTIME_PER_USEC);
-               pos += scnprintf(buf + pos, size - pos, " cost.vrate=%u.%02u",
-                                 vp10k / 100, vp10k % 100);
+               seq_printf(s, " cost.vrate=%u.%02u", vp10k / 100, vp10k % 100);
        }
 
-       pos += scnprintf(buf + pos, size - pos, " cost.usage=%llu",
-                        iocg->last_stat.usage_us);
+       seq_printf(s, " cost.usage=%llu", iocg->last_stat.usage_us);
 
        if (blkcg_debug_stats)
-               pos += scnprintf(buf + pos, size - pos,
-                                " cost.wait=%llu cost.indebt=%llu cost.indelay=%llu",
-                                iocg->last_stat.wait_us,
-                                iocg->last_stat.indebt_us,
-                                iocg->last_stat.indelay_us);
-
-       return pos;
+               seq_printf(s, " cost.wait=%llu cost.indebt=%llu cost.indelay=%llu",
+                       iocg->last_stat.wait_us,
+                       iocg->last_stat.indebt_us,
+                       iocg->last_stat.indelay_us);
+       return true;
 }
 
 static u64 ioc_weight_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
@@ -3060,19 +3079,19 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
                if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX)
                        return -EINVAL;
 
-               spin_lock(&blkcg->lock);
+               spin_lock_irq(&blkcg->lock);
                iocc->dfl_weight = v * WEIGHT_ONE;
                hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
                        struct ioc_gq *iocg = blkg_to_iocg(blkg);
 
                        if (iocg) {
-                               spin_lock_irq(&iocg->ioc->lock);
+                               spin_lock(&iocg->ioc->lock);
                                ioc_now(iocg->ioc, &now);
                                weight_updated(iocg, &now);
-                               spin_unlock_irq(&iocg->ioc->lock);
+                               spin_unlock(&iocg->ioc->lock);
                        }
                }
-               spin_unlock(&blkcg->lock);
+               spin_unlock_irq(&blkcg->lock);
 
                return nbytes;
        }