diff options
Diffstat (limited to 'kernel/res_counter.c')
| -rw-r--r-- | kernel/res_counter.c | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/kernel/res_counter.c b/kernel/res_counter.c index d3c61b4ebef2..f275c8eca772 100644 --- a/kernel/res_counter.c +++ b/kernel/res_counter.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <linux/res_counter.h> | 14 | #include <linux/res_counter.h> |
| 15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
| 16 | #include <linux/mm.h> | ||
| 16 | 17 | ||
| 17 | void res_counter_init(struct res_counter *counter) | 18 | void res_counter_init(struct res_counter *counter) |
| 18 | { | 19 | { |
| @@ -102,44 +103,37 @@ u64 res_counter_read_u64(struct res_counter *counter, int member) | |||
| 102 | return *res_counter_member(counter, member); | 103 | return *res_counter_member(counter, member); |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 105 | ssize_t res_counter_write(struct res_counter *counter, int member, | 106 | int res_counter_memparse_write_strategy(const char *buf, |
| 106 | const char __user *userbuf, size_t nbytes, loff_t *pos, | 107 | unsigned long long *res) |
| 107 | int (*write_strategy)(char *st_buf, unsigned long long *val)) | ||
| 108 | { | 108 | { |
| 109 | int ret; | 109 | char *end; |
| 110 | char *buf, *end; | 110 | /* FIXME - make memparse() take const char* args */ |
| 111 | unsigned long flags; | 111 | *res = memparse((char *)buf, &end); |
| 112 | unsigned long long tmp, *val; | 112 | if (*end != '\0') |
| 113 | 113 | return -EINVAL; | |
| 114 | buf = kmalloc(nbytes + 1, GFP_KERNEL); | ||
| 115 | ret = -ENOMEM; | ||
| 116 | if (buf == NULL) | ||
| 117 | goto out; | ||
| 118 | 114 | ||
| 119 | buf[nbytes] = '\0'; | 115 | *res = PAGE_ALIGN(*res); |
| 120 | ret = -EFAULT; | 116 | return 0; |
| 121 | if (copy_from_user(buf, userbuf, nbytes)) | 117 | } |
| 122 | goto out_free; | ||
| 123 | 118 | ||
| 124 | ret = -EINVAL; | 119 | int res_counter_write(struct res_counter *counter, int member, |
| 120 | const char *buf, write_strategy_fn write_strategy) | ||
| 121 | { | ||
| 122 | char *end; | ||
| 123 | unsigned long flags; | ||
| 124 | unsigned long long tmp, *val; | ||
| 125 | 125 | ||
| 126 | strstrip(buf); | ||
| 127 | if (write_strategy) { | 126 | if (write_strategy) { |
| 128 | if (write_strategy(buf, &tmp)) { | 127 | if (write_strategy(buf, &tmp)) |
| 129 | goto out_free; | 128 | return -EINVAL; |
| 130 | } | ||
| 131 | } else { | 129 | } else { |
| 132 | tmp = simple_strtoull(buf, &end, 10); | 130 | tmp = simple_strtoull(buf, &end, 10); |
| 133 | if (*end != '\0') | 131 | if (*end != '\0') |
| 134 | goto out_free; | 132 | return -EINVAL; |
| 135 | } | 133 | } |
| 136 | spin_lock_irqsave(&counter->lock, flags); | 134 | spin_lock_irqsave(&counter->lock, flags); |
| 137 | val = res_counter_member(counter, member); | 135 | val = res_counter_member(counter, member); |
| 138 | *val = tmp; | 136 | *val = tmp; |
| 139 | spin_unlock_irqrestore(&counter->lock, flags); | 137 | spin_unlock_irqrestore(&counter->lock, flags); |
| 140 | ret = nbytes; | 138 | return 0; |
| 141 | out_free: | ||
| 142 | kfree(buf); | ||
| 143 | out: | ||
| 144 | return ret; | ||
| 145 | } | 139 | } |
