diff options
author | Paul Menage <menage@google.com> | 2008-07-25 04:46:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:35 -0400 |
commit | db3b14978abc02041046ed8353f0899cb58ffffc (patch) | |
tree | 355ba027c6354bd13bcbb5318e8478b3de4599e9 /kernel/cgroup.c | |
parent | ce16b49d37e748574f7fabc2726268d542d0aa1a (diff) |
cgroup files: add write_string cgroup control file method
This patch adds a write_string() method for cgroups control files. The
semantics are that a buffer is copied from userspace to kernelspace
and the handler function invoked on that buffer. The buffer is
guaranteed to be nul-terminated, and no longer than max_write_len
(defaulting to 64 bytes if unspecified). Later patches will convert
existing raw file write handlers in control group subsystems to use
this method.
Signed-off-by: Paul Menage <menage@google.com>
Cc: Paul Jackson <pj@sgi.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Balbir Singh <balbir@in.ibm.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 35 |
1 files changed, 35 insertions, 0 deletions
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; |