Commit 4d8438f0 authored by Frederic Weisbecker's avatar Frederic Weisbecker Committed by Tejun Heo

res_counter: Merge res_counter_charge and res_counter_charge_nofail

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: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: default avatarGlauber Costa <glommer@parallels.com>
Acked-by: default avatarKirill A. Shutemov <kirill@shutemov.name>
Cc: Li Zefan <lizefan@huawei.com>
parent c4c27fbd
...@@ -77,11 +77,11 @@ to work with it. ...@@ -77,11 +77,11 @@ to work with it.
where the charging failed. where the charging failed.
d. int res_counter_charge_locked 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 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 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] e. void res_counter_uncharge[_locked]
(struct res_counter *rc, unsigned long val) (struct res_counter *rc, unsigned long val)
......
...@@ -116,7 +116,7 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent); ...@@ -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, 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, int __must_check res_counter_charge(struct res_counter *counter,
unsigned long val, struct res_counter **limit_fail_at); unsigned long val, struct res_counter **limit_fail_at);
int __must_check res_counter_charge_nofail(struct res_counter *counter, int __must_check res_counter_charge_nofail(struct res_counter *counter,
......
...@@ -22,75 +22,70 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent) ...@@ -22,75 +22,70 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent)
counter->parent = 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) { if (counter->usage + val > counter->limit) {
counter->failcnt++; counter->failcnt++;
return -ENOMEM; ret = -ENOMEM;
if (!force)
return ret;
} }
counter->usage += val; counter->usage += val;
if (counter->usage > counter->max_usage) if (!force && counter->usage > counter->max_usage)
counter->max_usage = counter->usage; counter->max_usage = counter->usage;
return 0; return ret;
} }
int res_counter_charge(struct res_counter *counter, unsigned long val, static int __res_counter_charge(struct res_counter *counter, unsigned long val,
struct res_counter **limit_fail_at) struct res_counter **limit_fail_at, bool force)
{ {
int ret; int ret, r;
unsigned long flags; unsigned long flags;
struct res_counter *c, *u; struct res_counter *c, *u;
r = ret = 0;
*limit_fail_at = NULL; *limit_fail_at = NULL;
local_irq_save(flags); local_irq_save(flags);
for (c = counter; c != NULL; c = c->parent) { for (c = counter; c != NULL; c = c->parent) {
spin_lock(&c->lock); spin_lock(&c->lock);
ret = res_counter_charge_locked(c, val); r = res_counter_charge_locked(c, val, force);
spin_unlock(&c->lock); spin_unlock(&c->lock);
if (ret < 0) { if (r < 0 && !ret) {
ret = r;
*limit_fail_at = c; *limit_fail_at = c;
goto undo; if (!force)
break;
} }
} }
ret = 0;
goto done; if (ret < 0 && !force) {
undo: for (u = counter; u != c; u = u->parent) {
for (u = counter; u != c; u = u->parent) { spin_lock(&u->lock);
spin_lock(&u->lock); res_counter_uncharge_locked(u, val);
res_counter_uncharge_locked(u, val); spin_unlock(&u->lock);
spin_unlock(&u->lock); }
} }
done:
local_irq_restore(flags); local_irq_restore(flags);
return ret; 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, int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
struct res_counter **limit_fail_at) struct res_counter **limit_fail_at)
{ {
int ret, r; return __res_counter_charge(counter, val, limit_fail_at, true);
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;
} }
void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val) void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
{ {
if (WARN_ON(counter->usage < val)) if (WARN_ON(counter->usage < val))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment