aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Menage <menage@google.com>2008-07-25 04:47:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:36 -0400
commit856c13aa1ff6136c1968414fdea5938ea9d5ebf2 (patch)
treedeee908f253c77cbcb868a915e45bfb2ed99383c
parentf92523e3a7861f5dbd76021e0719a35fe8771f2d (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.h11
-rw-r--r--kernel/res_counter.c48
-rw-r--r--mm/memcontrol.c24
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);
63ssize_t res_counter_read(struct res_counter *counter, int member, 63ssize_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));
66ssize_t res_counter_write(struct res_counter *counter, int member, 66
67 const char __user *buf, size_t nbytes, loff_t *pos, 67typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
68 int (*write_strategy)(char *buf, unsigned long long *val)); 68
69int res_counter_memparse_write_strategy(const char *buf,
70 unsigned long long *res);
71
72int 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
17void res_counter_init(struct res_counter *counter) 18void 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
105ssize_t res_counter_write(struct res_counter *counter, int member, 106int 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; 119int 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;
141out_free:
142 kfree(buf);
143out:
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
841static 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
854static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) 841static 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
860static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, 847static 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
869static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) 855static 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 {