diff options
-rw-r--r-- | include/linux/cgroup.h | 8 | ||||
-rw-r--r-- | kernel/cgroup.c | 38 |
2 files changed, 36 insertions, 10 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index b40fd5ee9a76..785a01cfb49d 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -216,6 +216,10 @@ struct cftype { | |||
216 | */ | 216 | */ |
217 | u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft); | 217 | u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft); |
218 | /* | 218 | /* |
219 | * read_s64() is a signed version of read_u64() | ||
220 | */ | ||
221 | s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft); | ||
222 | /* | ||
219 | * read_map() is used for defining a map of key/value | 223 | * read_map() is used for defining a map of key/value |
220 | * pairs. It should call cb->fill(cb, key, value) for each | 224 | * pairs. It should call cb->fill(cb, key, value) for each |
221 | * entry. The key/value pairs (and their ordering) should not | 225 | * entry. The key/value pairs (and their ordering) should not |
@@ -234,6 +238,10 @@ struct cftype { | |||
234 | * userspace. Use in place of write(); return 0 or error. | 238 | * userspace. Use in place of write(); return 0 or error. |
235 | */ | 239 | */ |
236 | int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val); | 240 | int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val); |
241 | /* | ||
242 | * write_s64() is a signed version of write_u64() | ||
243 | */ | ||
244 | int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val); | ||
237 | 245 | ||
238 | int (*release) (struct inode *inode, struct file *file); | 246 | int (*release) (struct inode *inode, struct file *file); |
239 | }; | 247 | }; |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b5ef0c4772f7..bd6122ccc0ba 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1299,14 +1299,13 @@ enum cgroup_filetype { | |||
1299 | FILE_RELEASE_AGENT, | 1299 | FILE_RELEASE_AGENT, |
1300 | }; | 1300 | }; |
1301 | 1301 | ||
1302 | static ssize_t cgroup_write_u64(struct cgroup *cgrp, struct cftype *cft, | 1302 | static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft, |
1303 | struct file *file, | 1303 | struct file *file, |
1304 | const char __user *userbuf, | 1304 | const char __user *userbuf, |
1305 | size_t nbytes, loff_t *unused_ppos) | 1305 | size_t nbytes, loff_t *unused_ppos) |
1306 | { | 1306 | { |
1307 | char buffer[64]; | 1307 | char buffer[64]; |
1308 | int retval = 0; | 1308 | int retval = 0; |
1309 | u64 val; | ||
1310 | char *end; | 1309 | char *end; |
1311 | 1310 | ||
1312 | if (!nbytes) | 1311 | if (!nbytes) |
@@ -1318,12 +1317,17 @@ static ssize_t cgroup_write_u64(struct cgroup *cgrp, struct cftype *cft, | |||
1318 | 1317 | ||
1319 | buffer[nbytes] = 0; /* nul-terminate */ | 1318 | buffer[nbytes] = 0; /* nul-terminate */ |
1320 | strstrip(buffer); | 1319 | strstrip(buffer); |
1321 | val = simple_strtoull(buffer, &end, 0); | 1320 | if (cft->write_u64) { |
1322 | if (*end) | 1321 | u64 val = simple_strtoull(buffer, &end, 0); |
1323 | return -EINVAL; | 1322 | if (*end) |
1324 | 1323 | return -EINVAL; | |
1325 | /* Pass to subsystem */ | 1324 | retval = cft->write_u64(cgrp, cft, val); |
1326 | retval = cft->write_u64(cgrp, cft, val); | 1325 | } else { |
1326 | s64 val = simple_strtoll(buffer, &end, 0); | ||
1327 | if (*end) | ||
1328 | return -EINVAL; | ||
1329 | retval = cft->write_s64(cgrp, cft, val); | ||
1330 | } | ||
1327 | if (!retval) | 1331 | if (!retval) |
1328 | retval = nbytes; | 1332 | retval = nbytes; |
1329 | return retval; | 1333 | return retval; |
@@ -1404,8 +1408,8 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf, | |||
1404 | return -ENODEV; | 1408 | return -ENODEV; |
1405 | if (cft->write) | 1409 | if (cft->write) |
1406 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); | 1410 | return cft->write(cgrp, cft, file, buf, nbytes, ppos); |
1407 | if (cft->write_u64) | 1411 | if (cft->write_u64 || cft->write_s64) |
1408 | return cgroup_write_u64(cgrp, cft, file, buf, nbytes, ppos); | 1412 | return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos); |
1409 | return -EINVAL; | 1413 | return -EINVAL; |
1410 | } | 1414 | } |
1411 | 1415 | ||
@@ -1421,6 +1425,18 @@ static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft, | |||
1421 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); | 1425 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); |
1422 | } | 1426 | } |
1423 | 1427 | ||
1428 | static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft, | ||
1429 | struct file *file, | ||
1430 | char __user *buf, size_t nbytes, | ||
1431 | loff_t *ppos) | ||
1432 | { | ||
1433 | char tmp[64]; | ||
1434 | s64 val = cft->read_s64(cgrp, cft); | ||
1435 | int len = sprintf(tmp, "%lld\n", (long long) val); | ||
1436 | |||
1437 | return simple_read_from_buffer(buf, nbytes, ppos, tmp, len); | ||
1438 | } | ||
1439 | |||
1424 | static ssize_t cgroup_common_file_read(struct cgroup *cgrp, | 1440 | static ssize_t cgroup_common_file_read(struct cgroup *cgrp, |
1425 | struct cftype *cft, | 1441 | struct cftype *cft, |
1426 | struct file *file, | 1442 | struct file *file, |
@@ -1477,6 +1493,8 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf, | |||
1477 | return cft->read(cgrp, cft, file, buf, nbytes, ppos); | 1493 | return cft->read(cgrp, cft, file, buf, nbytes, ppos); |
1478 | if (cft->read_u64) | 1494 | if (cft->read_u64) |
1479 | return cgroup_read_u64(cgrp, cft, file, buf, nbytes, ppos); | 1495 | return cgroup_read_u64(cgrp, cft, file, buf, nbytes, ppos); |
1496 | if (cft->read_s64) | ||
1497 | return cgroup_read_s64(cgrp, cft, file, buf, nbytes, ppos); | ||
1480 | return -EINVAL; | 1498 | return -EINVAL; |
1481 | } | 1499 | } |
1482 | 1500 | ||