diff options
-rw-r--r-- | include/linux/cgroup.h | 14 | ||||
-rw-r--r-- | kernel/cgroup.c | 35 |
2 files changed, 49 insertions, 0 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 88a734edccbc..f5379455bb59 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -205,6 +205,13 @@ struct cftype { | |||
205 | * subsystem, followed by a period */ | 205 | * subsystem, followed by a period */ |
206 | char name[MAX_CFTYPE_NAME]; | 206 | char name[MAX_CFTYPE_NAME]; |
207 | int private; | 207 | int private; |
208 | |||
209 | /* | ||
210 | * If non-zero, defines the maximum length of string that can | ||
211 | * be passed to write_string; defaults to 64 | ||
212 | */ | ||
213 | size_t max_write_len; | ||
214 | |||
208 | int (*open)(struct inode *inode, struct file *file); | 215 | int (*open)(struct inode *inode, struct file *file); |
209 | ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, | 216 | ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, |
210 | struct file *file, | 217 | struct file *file, |
@@ -249,6 +256,13 @@ struct cftype { | |||
249 | int (*write_s64)(struct cgroup *cgrp, struct cftype *cft, s64 val); | 256 | int (*write_s64)(struct cgroup *cgrp, struct cftype *cft, s64 val); |
250 | 257 | ||
251 | /* | 258 | /* |
259 | * write_string() is passed a nul-terminated kernelspace | ||
260 | * buffer of maximum length determined by max_write_len. | ||
261 | * Returns 0 or -ve error code. | ||
262 | */ | ||
263 | int (*write_string)(struct cgroup *cgrp, struct cftype *cft, | ||
264 | const char *buffer); | ||
265 | /* | ||
252 | * trigger() callback can be used to get some kick from the | 266 | * trigger() callback can be used to get some kick from the |
253 | * userspace, when the actual string written is not important | 267 | * userspace, when the actual string written is not important |
254 | * at all. The private field can be used to determine the | 268 | * at all. The private field can be used to determine the |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 70d083c6fb6b..3a99cc2df860 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1363,6 +1363,39 @@ static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, | |||
1363 | return retval; | 1363 | return retval; |
1364 | } | 1364 | } |
1365 | 1365 | ||
1366 | static ssize_t cgroup_write_string(struct cgroup *cgrp, struct cftype *cft, | ||
1367 | struct file *file, | ||
1368 | const char __user *userbuf, | ||
1369 | size_t nbytes, loff_t *unused_ppos) | ||
1370 | { | ||
1371 | char local_buffer[64]; | ||
1372 | int retval = 0; | ||
1373 | size_t max_bytes = cft->max_write_len; | ||
1374 | char *buffer = local_buffer; | ||
1375 | |||
1376 | if (!max_bytes) | ||
1377 | max_bytes = sizeof(local_buffer) - 1; | ||
1378 | if (nbytes >= max_bytes) | ||
1379 | return -E2BIG; | ||
1380 | /* Allocate a dynamic buffer if we need one */ | ||
1381 | if (nbytes >= sizeof(local_buffer)) { | ||
1382 | buffer = kmalloc(nbytes + 1, GFP_KERNEL); | ||
1383 | if (buffer == NULL) | ||
1384 | return -ENOMEM; | ||
1385 | } | ||
1386 | if (nbytes && copy_from_user(buffer, userbuf, nbytes)) | ||
1387 | return -EFAULT; | ||
1388 | |||
1389 | buffer[nbytes] = 0; /* nul-terminate */ | ||
1390 | strstrip(buffer); | ||
1391 | retval = cft->write_string(cgrp, cft, buffer); | ||
1392 | if (!retval) | ||
1393 | retval = nbytes; | ||
1394 | if (buffer != local_buffer) | ||
1395 | kfree(buffer); | ||
1396 | return retval; | ||
1397 | } | ||
1398 | |||
1366 | static ssize_t cgroup_common_file_write(struct cgroup *cgrp, | 1399 | static ssize_t cgroup_common_file_write(struct cgroup *cgrp, |
1367 | struct cftype *cft, | 1400 | struct cftype *cft, |
1368 | struct file *file, | 1401 | struct file *file, |
@@ -1440,6 +1473,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | |||
1440 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); | 1473 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); |
1441 | if (cft->write_u64 || cft->write_s64) | 1474 | if (cft->write_u64 || cft->write_s64) |
1442 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); | 1475 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); |
1476 | if (cft->write_string) | ||
1477 | return cgroup_write_string(cgrp, cft, file, buf, nbytes, ppos); | ||
1443 | if (cft->trigger) { | 1478 | if (cft->trigger) { |
1444 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); | 1479 | int ret = cft->trigger(cgrp, (unsigned int)cft->private); |
1445 | return ret ? ret : nbytes; | 1480 | return ret ? ret : nbytes; |