res_counter: Merge res_counter_charge and res_counter_charge_nofail
authorFrederic Weisbecker <fweisbec@gmail.com>
Tue, 24 Apr 2012 23:11:35 +0000 (01:11 +0200)
committerTejun Heo <tj@kernel.org>
Fri, 27 Apr 2012 21:36:45 +0000 (14:36 -0700)
These two functions do almost the same thing and duplicate some code.
Merge their implementation into a single common function.
res_counter_charge_locked() takes one more parameter but it doesn't seem
to be used outside res_counter.c yet anyway.

There is no (intended) change in the behaviour.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Glauber Costa <glommer@parallels.com>
Acked-by: Kirill A. Shutemov <kirill@shutemov.name>
Cc: Li Zefan <lizefan@huawei.com>
Documentation/cgroups/resource_counter.txt
include/linux/res_counter.h
kernel/res_counter.c

index 95b24d7..f3c4ec3 100644 (file)
@@ -77,11 +77,11 @@ to work with it.
        where the charging failed.
 
  d. int res_counter_charge_locked
-                       (struct res_counter *rc, unsigned long val)
+                       (struct res_counter *rc, unsigned long val, bool force)
 
        The same as res_counter_charge(), but it must not acquire/release the
        res_counter->lock internally (it must be called with res_counter->lock
-       held).
+       held). The force parameter indicates whether we can bypass the limit.
 
  e. void res_counter_uncharge[_locked]
                        (struct res_counter *rc, unsigned long val)
index da81af0..fb20189 100644 (file)
@@ -116,7 +116,7 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent);
  */
 
 int __must_check res_counter_charge_locked(struct res_counter *counter,
-               unsigned long val);
+                                          unsigned long val, bool force);
 int __must_check res_counter_charge(struct res_counter *counter,
                unsigned long val, struct res_counter **limit_fail_at);
 int __must_check res_counter_charge_nofail(struct res_counter *counter,
index d508363..07a2992 100644 (file)
@@ -22,75 +22,70 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent)
        counter->parent = parent;
 }
 
-int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
+int res_counter_charge_locked(struct res_counter *counter, unsigned long val,
+                             bool force)
 {
+       int ret = 0;
+
        if (counter->usage + val > counter->limit) {
                counter->failcnt++;
-               return -ENOMEM;
+               ret = -ENOMEM;
+               if (!force)
+                       return ret;
        }
 
        counter->usage += val;
-       if (counter->usage > counter->max_usage)
+       if (!force && counter->usage > counter->max_usage)
                counter->max_usage = counter->usage;
-       return 0;
+       return ret;
 }
 
-int res_counter_charge(struct res_counter *counter, unsigned long val,
-                       struct res_counter **limit_fail_at)
+static int __res_counter_charge(struct res_counter *counter, unsigned long val,
+                               struct res_counter **limit_fail_at, bool force)
 {
-       int ret;
+       int ret, r;
        unsigned long flags;
        struct res_counter *c, *u;
 
+       r = ret = 0;
        *limit_fail_at = NULL;
        local_irq_save(flags);
        for (c = counter; c != NULL; c = c->parent) {
                spin_lock(&c->lock);
-               ret = res_counter_charge_locked(c, val);
+               r = res_counter_charge_locked(c, val, force);
                spin_unlock(&c->lock);
-               if (ret < 0) {
+               if (r < 0 && !ret) {
+                       ret = r;
                        *limit_fail_at = c;
-                       goto undo;
+                       if (!force)
+                               break;
                }
        }
-       ret = 0;
-       goto done;
-undo:
-       for (u = counter; u != c; u = u->parent) {
-               spin_lock(&u->lock);
-               res_counter_uncharge_locked(u, val);
-               spin_unlock(&u->lock);
+
+       if (ret < 0 && !force) {
+               for (u = counter; u != c; u = u->parent) {
+                       spin_lock(&u->lock);
+                       res_counter_uncharge_locked(u, val);
+                       spin_unlock(&u->lock);
+               }
        }
-done:
        local_irq_restore(flags);
+
        return ret;
 }
 
+int res_counter_charge(struct res_counter *counter, unsigned long val,
+                       struct res_counter **limit_fail_at)
+{
+       return __res_counter_charge(counter, val, limit_fail_at, false);
+}
+
 int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
                              struct res_counter **limit_fail_at)
 {
-       int ret, r;
-       unsigned long flags;
-       struct res_counter *c;
-
-       r = ret = 0;
-       *limit_fail_at = NULL;
-       local_irq_save(flags);
-       for (c = counter; c != NULL; c = c->parent) {
-               spin_lock(&c->lock);
-               r = res_counter_charge_locked(c, val);
-               if (r)
-                       c->usage += val;
-               spin_unlock(&c->lock);
-               if (r < 0 && ret == 0) {
-                       *limit_fail_at = c;
-                       ret = r;
-               }
-       }
-       local_irq_restore(flags);
-
-       return ret;
+       return __res_counter_charge(counter, val, limit_fail_at, true);
 }
+
 void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 {
        if (WARN_ON(counter->usage < val))