X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Fres_counter.c;h=d3c61b4ebef238c110ae3994e0d0fdc078fabfc8;hb=61d6cc54896811086b51fa78d440311974a09b3a;hp=722c484b068bc855c65813f3082a10c6d7fb72b3;hpb=e552b6617067ab785256dcec5ca29eeea981aacb;p=pandora-kernel.git diff --git a/kernel/res_counter.c b/kernel/res_counter.c index 722c484b068b..d3c61b4ebef2 100644 --- a/kernel/res_counter.c +++ b/kernel/res_counter.c @@ -10,13 +10,14 @@ #include #include #include +#include #include #include void res_counter_init(struct res_counter *counter) { spin_lock_init(&counter->lock); - counter->limit = (unsigned long)LONG_MAX; + counter->limit = (unsigned long long)LLONG_MAX; } int res_counter_charge_locked(struct res_counter *counter, unsigned long val) @@ -27,6 +28,8 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val) } counter->usage += val; + if (counter->usage > counter->max_usage) + counter->max_usage = counter->usage; return 0; } @@ -59,12 +62,14 @@ void res_counter_uncharge(struct res_counter *counter, unsigned long val) } -static inline unsigned long *res_counter_member(struct res_counter *counter, - int member) +static inline unsigned long long * +res_counter_member(struct res_counter *counter, int member) { switch (member) { case RES_USAGE: return &counter->usage; + case RES_MAX_USAGE: + return &counter->max_usage; case RES_LIMIT: return &counter->limit; case RES_FAILCNT: @@ -76,24 +81,35 @@ static inline unsigned long *res_counter_member(struct res_counter *counter, } ssize_t res_counter_read(struct res_counter *counter, int member, - const char __user *userbuf, size_t nbytes, loff_t *pos) + const char __user *userbuf, size_t nbytes, loff_t *pos, + int (*read_strategy)(unsigned long long val, char *st_buf)) { - unsigned long *val; + unsigned long long *val; char buf[64], *s; s = buf; val = res_counter_member(counter, member); - s += sprintf(s, "%lu\n", *val); + if (read_strategy) + s += read_strategy(*val, s); + else + s += sprintf(s, "%llu\n", *val); return simple_read_from_buffer((void __user *)userbuf, nbytes, pos, buf, s - buf); } +u64 res_counter_read_u64(struct res_counter *counter, int member) +{ + return *res_counter_member(counter, member); +} + ssize_t res_counter_write(struct res_counter *counter, int member, - const char __user *userbuf, size_t nbytes, loff_t *pos) + const char __user *userbuf, size_t nbytes, loff_t *pos, + int (*write_strategy)(char *st_buf, unsigned long long *val)) { int ret; char *buf, *end; - unsigned long tmp, *val; + unsigned long flags; + unsigned long long tmp, *val; buf = kmalloc(nbytes + 1, GFP_KERNEL); ret = -ENOMEM; @@ -106,12 +122,21 @@ ssize_t res_counter_write(struct res_counter *counter, int member, goto out_free; ret = -EINVAL; - tmp = simple_strtoul(buf, &end, 10); - if (*end != '\0') - goto out_free; + strstrip(buf); + if (write_strategy) { + if (write_strategy(buf, &tmp)) { + goto out_free; + } + } else { + tmp = simple_strtoull(buf, &end, 10); + if (*end != '\0') + goto out_free; + } + spin_lock_irqsave(&counter->lock, flags); val = res_counter_member(counter, member); *val = tmp; + spin_unlock_irqrestore(&counter->lock, flags); ret = nbytes; out_free: kfree(buf);