Commit 856c13aa1ff6136c1968414fdea5938ea9d5ebf2
Committed by
Linus Torvalds
1 parent
f92523e3a7
Exists in
master
and in
20 other branches
cgroup files: convert res_counter_write() to be a cgroups write_string() handler
Currently res_counter_write() is a raw file handler even though it's ultimately taking a number, since in some cases it wants to pre-process the string when converting it to a number. This patch converts res_counter_write() from a raw file handler to a write_string() handler; this allows some of the boilerplate copying/locking/checking to be removed, and simplies the cleanup path, since these functions are now performed by the cgroups framework. [lizf@cn.fujitsu.com: build fix] Signed-off-by: Paul Menage <menage@google.com> Cc: Paul Jackson <pj@sgi.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Serge Hallyn <serue@us.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 34 additions and 49 deletions Side-by-side Diff
include/linux/res_counter.h
... | ... | @@ -63,9 +63,14 @@ |
63 | 63 | ssize_t res_counter_read(struct res_counter *counter, int member, |
64 | 64 | const char __user *buf, size_t nbytes, loff_t *pos, |
65 | 65 | int (*read_strategy)(unsigned long long val, char *s)); |
66 | -ssize_t res_counter_write(struct res_counter *counter, int member, | |
67 | - const char __user *buf, size_t nbytes, loff_t *pos, | |
68 | - int (*write_strategy)(char *buf, unsigned long long *val)); | |
66 | + | |
67 | +typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val); | |
68 | + | |
69 | +int res_counter_memparse_write_strategy(const char *buf, | |
70 | + unsigned long long *res); | |
71 | + | |
72 | +int res_counter_write(struct res_counter *counter, int member, | |
73 | + const char *buffer, write_strategy_fn write_strategy); | |
69 | 74 | |
70 | 75 | /* |
71 | 76 | * the field descriptors. one for each member of res_counter |
kernel/res_counter.c
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | #include <linux/slab.h> |
14 | 14 | #include <linux/res_counter.h> |
15 | 15 | #include <linux/uaccess.h> |
16 | +#include <linux/mm.h> | |
16 | 17 | |
17 | 18 | void res_counter_init(struct res_counter *counter) |
18 | 19 | { |
19 | 20 | |
20 | 21 | |
21 | 22 | |
22 | 23 | |
23 | 24 | |
... | ... | @@ -102,45 +103,38 @@ |
102 | 103 | return *res_counter_member(counter, member); |
103 | 104 | } |
104 | 105 | |
105 | -ssize_t res_counter_write(struct res_counter *counter, int member, | |
106 | - const char __user *userbuf, size_t nbytes, loff_t *pos, | |
107 | - int (*write_strategy)(char *st_buf, unsigned long long *val)) | |
106 | +int res_counter_memparse_write_strategy(const char *buf, | |
107 | + unsigned long long *res) | |
108 | 108 | { |
109 | - int ret; | |
110 | - char *buf, *end; | |
109 | + char *end; | |
110 | + /* FIXME - make memparse() take const char* args */ | |
111 | + *res = memparse((char *)buf, &end); | |
112 | + if (*end != '\0') | |
113 | + return -EINVAL; | |
114 | + | |
115 | + *res = PAGE_ALIGN(*res); | |
116 | + return 0; | |
117 | +} | |
118 | + | |
119 | +int res_counter_write(struct res_counter *counter, int member, | |
120 | + const char *buf, write_strategy_fn write_strategy) | |
121 | +{ | |
122 | + char *end; | |
111 | 123 | unsigned long flags; |
112 | 124 | unsigned long long tmp, *val; |
113 | 125 | |
114 | - buf = kmalloc(nbytes + 1, GFP_KERNEL); | |
115 | - ret = -ENOMEM; | |
116 | - if (buf == NULL) | |
117 | - goto out; | |
118 | - | |
119 | - buf[nbytes] = '\0'; | |
120 | - ret = -EFAULT; | |
121 | - if (copy_from_user(buf, userbuf, nbytes)) | |
122 | - goto out_free; | |
123 | - | |
124 | - ret = -EINVAL; | |
125 | - | |
126 | - strstrip(buf); | |
127 | 126 | if (write_strategy) { |
128 | - if (write_strategy(buf, &tmp)) { | |
129 | - goto out_free; | |
130 | - } | |
127 | + if (write_strategy(buf, &tmp)) | |
128 | + return -EINVAL; | |
131 | 129 | } else { |
132 | 130 | tmp = simple_strtoull(buf, &end, 10); |
133 | 131 | if (*end != '\0') |
134 | - goto out_free; | |
132 | + return -EINVAL; | |
135 | 133 | } |
136 | 134 | spin_lock_irqsave(&counter->lock, flags); |
137 | 135 | val = res_counter_member(counter, member); |
138 | 136 | *val = tmp; |
139 | 137 | spin_unlock_irqrestore(&counter->lock, flags); |
140 | - ret = nbytes; | |
141 | -out_free: | |
142 | - kfree(buf); | |
143 | -out: | |
144 | - return ret; | |
138 | + return 0; | |
145 | 139 | } |
mm/memcontrol.c
... | ... | @@ -838,32 +838,18 @@ |
838 | 838 | return ret; |
839 | 839 | } |
840 | 840 | |
841 | -static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp) | |
842 | -{ | |
843 | - *tmp = memparse(buf, &buf); | |
844 | - if (*buf != '\0') | |
845 | - return -EINVAL; | |
846 | - | |
847 | - /* | |
848 | - * Round up the value to the closest page size | |
849 | - */ | |
850 | - *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT; | |
851 | - return 0; | |
852 | -} | |
853 | - | |
854 | 841 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) |
855 | 842 | { |
856 | 843 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, |
857 | 844 | cft->private); |
858 | 845 | } |
859 | 846 | |
860 | -static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | |
861 | - struct file *file, const char __user *userbuf, | |
862 | - size_t nbytes, loff_t *ppos) | |
847 | +static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | |
848 | + const char *buffer) | |
863 | 849 | { |
864 | 850 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, |
865 | - cft->private, userbuf, nbytes, ppos, | |
866 | - mem_cgroup_write_strategy); | |
851 | + cft->private, buffer, | |
852 | + res_counter_memparse_write_strategy); | |
867 | 853 | } |
868 | 854 | |
869 | 855 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) |
... | ... | @@ -940,7 +926,7 @@ |
940 | 926 | { |
941 | 927 | .name = "limit_in_bytes", |
942 | 928 | .private = RES_LIMIT, |
943 | - .write = mem_cgroup_write, | |
929 | + .write_string = mem_cgroup_write, | |
944 | 930 | .read_u64 = mem_cgroup_read, |
945 | 931 | }, |
946 | 932 | { |