diff options
| author | Paul Menage <menage@google.com> | 2008-07-25 04:47:04 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:36 -0400 |
| commit | 856c13aa1ff6136c1968414fdea5938ea9d5ebf2 (patch) | |
| tree | deee908f253c77cbcb868a915e45bfb2ed99383c | |
| parent | f92523e3a7861f5dbd76021e0719a35fe8771f2d (diff) | |
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>
| -rw-r--r-- | include/linux/res_counter.h | 11 | ||||
| -rw-r--r-- | kernel/res_counter.c | 48 | ||||
| -rw-r--r-- | mm/memcontrol.c | 24 |
3 files changed, 34 insertions, 49 deletions
diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index 125660e7793f..290205dfe094 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h | |||
| @@ -63,9 +63,14 @@ u64 res_counter_read_u64(struct res_counter *counter, int member); | |||
| 63 | ssize_t res_counter_read(struct res_counter *counter, int member, | 63 | ssize_t res_counter_read(struct res_counter *counter, int member, |
| 64 | const char __user *buf, size_t nbytes, loff_t *pos, | 64 | const char __user *buf, size_t nbytes, loff_t *pos, |
| 65 | int (*read_strategy)(unsigned long long val, char *s)); | 65 | int (*read_strategy)(unsigned long long val, char *s)); |
| 66 | ssize_t res_counter_write(struct res_counter *counter, int member, | 66 | |
| 67 | const char __user *buf, size_t nbytes, loff_t *pos, | 67 | typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val); |
| 68 | int (*write_strategy)(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 | * the field descriptors. one for each member of res_counter | 76 | * the field descriptors. one for each member of res_counter |
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 | } |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e46451e1d9b7..7385d58fb061 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -838,32 +838,18 @@ out: | |||
| 838 | return ret; | 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 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) | 841 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) |
| 855 | { | 842 | { |
| 856 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, | 843 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, |
| 857 | cft->private); | 844 | cft->private); |
| 858 | } | 845 | } |
| 859 | 846 | ||
| 860 | static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | 847 | static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, |
| 861 | struct file *file, const char __user *userbuf, | 848 | const char *buffer) |
| 862 | size_t nbytes, loff_t *ppos) | ||
| 863 | { | 849 | { |
| 864 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, | 850 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, |
| 865 | cft->private, userbuf, nbytes, ppos, | 851 | cft->private, buffer, |
| 866 | mem_cgroup_write_strategy); | 852 | res_counter_memparse_write_strategy); |
| 867 | } | 853 | } |
| 868 | 854 | ||
| 869 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) | 855 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) |
| @@ -940,7 +926,7 @@ static struct cftype mem_cgroup_files[] = { | |||
| 940 | { | 926 | { |
| 941 | .name = "limit_in_bytes", | 927 | .name = "limit_in_bytes", |
| 942 | .private = RES_LIMIT, | 928 | .private = RES_LIMIT, |
| 943 | .write = mem_cgroup_write, | 929 | .write_string = mem_cgroup_write, |
| 944 | .read_u64 = mem_cgroup_read, | 930 | .read_u64 = mem_cgroup_read, |
| 945 | }, | 931 | }, |
| 946 | { | 932 | { |
