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: 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>
This commit is contained in:
parent
c4c27fbdda
commit
4d8438f044
@ -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);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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)
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res_counter_charge(struct res_counter *counter, unsigned long val,
|
|
||||||
struct res_counter **limit_fail_at)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned long flags;
|
|
||||||
struct res_counter *c, *u;
|
|
||||||
|
|
||||||
*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);
|
|
||||||
spin_unlock(&c->lock);
|
|
||||||
if (ret < 0) {
|
|
||||||
*limit_fail_at = c;
|
|
||||||
goto undo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
local_irq_restore(flags);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res_counter_charge_nofail(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, r;
|
int ret, r;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct res_counter *c;
|
struct res_counter *c, *u;
|
||||||
|
|
||||||
r = ret = 0;
|
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);
|
||||||
r = res_counter_charge_locked(c, val);
|
r = res_counter_charge_locked(c, val, force);
|
||||||
if (r)
|
|
||||||
c->usage += val;
|
|
||||||
spin_unlock(&c->lock);
|
spin_unlock(&c->lock);
|
||||||
if (r < 0 && ret == 0) {
|
if (r < 0 && !ret) {
|
||||||
*limit_fail_at = c;
|
|
||||||
ret = r;
|
ret = r;
|
||||||
|
*limit_fail_at = c;
|
||||||
|
if (!force)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,
|
||||||
|
struct res_counter **limit_fail_at)
|
||||||
|
{
|
||||||
|
return __res_counter_charge(counter, val, limit_fail_at, true);
|
||||||
|
}
|
||||||
|
|
||||||
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))
|
||||||
|
Loading…
Reference in New Issue
Block a user