aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h8
-rw-r--r--kernel/cgroup.c38
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
1302static ssize_t cgroup_write_u64(struct cgroup *cgrp, struct cftype *cft, 1302static 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
1428static 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
1424static ssize_t cgroup_common_file_read(struct cgroup *cgrp, 1440static 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