Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Paul Menage and committed by
Linus Torvalds
856c13aa f92523e3

+34 -49
+8 -3
include/linux/res_counter.h
··· 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
+21 -27
kernel/res_counter.c
··· 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 { ··· 103 102 return *res_counter_member(counter, member); 104 103 } 105 104 106 - ssize_t res_counter_write(struct res_counter *counter, int member, 107 - const char __user *userbuf, size_t nbytes, loff_t *pos, 108 - int (*write_strategy)(char *st_buf, unsigned long long *val)) 105 + int res_counter_memparse_write_strategy(const char *buf, 106 + unsigned long long *res) 109 107 { 110 - int ret; 111 - char *buf, *end; 108 + char *end; 109 + /* FIXME - make memparse() take const char* args */ 110 + *res = memparse((char *)buf, &end); 111 + if (*end != '\0') 112 + return -EINVAL; 113 + 114 + *res = PAGE_ALIGN(*res); 115 + return 0; 116 + } 117 + 118 + int res_counter_write(struct res_counter *counter, int member, 119 + const char *buf, write_strategy_fn write_strategy) 120 + { 121 + char *end; 112 122 unsigned long flags; 113 123 unsigned long long tmp, *val; 114 124 115 - buf = kmalloc(nbytes + 1, GFP_KERNEL); 116 - ret = -ENOMEM; 117 - if (buf == NULL) 118 - goto out; 119 - 120 - buf[nbytes] = '\0'; 121 - ret = -EFAULT; 122 - if (copy_from_user(buf, userbuf, nbytes)) 123 - goto out_free; 124 - 125 - ret = -EINVAL; 126 - 127 - strstrip(buf); 128 125 if (write_strategy) { 129 - if (write_strategy(buf, &tmp)) { 130 - goto out_free; 131 - } 126 + if (write_strategy(buf, &tmp)) 127 + return -EINVAL; 132 128 } else { 133 129 tmp = simple_strtoull(buf, &end, 10); 134 130 if (*end != '\0') 135 - goto out_free; 131 + return -EINVAL; 136 132 } 137 133 spin_lock_irqsave(&counter->lock, flags); 138 134 val = res_counter_member(counter, member); 139 135 *val = tmp; 140 136 spin_unlock_irqrestore(&counter->lock, flags); 141 - ret = nbytes; 142 - out_free: 143 - kfree(buf); 144 - out: 145 - return ret; 137 + return 0; 146 138 }
+5 -19
mm/memcontrol.c
··· 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) ··· 926 940 { 927 941 .name = "limit_in_bytes", 928 942 .private = RES_LIMIT, 929 - .write = mem_cgroup_write, 943 + .write_string = mem_cgroup_write, 930 944 .read_u64 = mem_cgroup_read, 931 945 }, 932 946 {