aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 57afdde871ac..693bcc03188b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1492,6 +1492,46 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf,
1492 return -EINVAL; 1492 return -EINVAL;
1493} 1493}
1494 1494
1495/*
1496 * seqfile ops/methods for returning structured data. Currently just
1497 * supports string->u64 maps, but can be extended in future.
1498 */
1499
1500struct cgroup_seqfile_state {
1501 struct cftype *cft;
1502 struct cgroup *cgroup;
1503};
1504
1505static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
1506{
1507 struct seq_file *sf = cb->state;
1508 return seq_printf(sf, "%s %llu\n", key, (unsigned long long)value);
1509}
1510
1511static int cgroup_seqfile_show(struct seq_file *m, void *arg)
1512{
1513 struct cgroup_seqfile_state *state = m->private;
1514 struct cftype *cft = state->cft;
1515 struct cgroup_map_cb cb = {
1516 .fill = cgroup_map_add,
1517 .state = m,
1518 };
1519 return cft->read_map(state->cgroup, cft, &cb);
1520}
1521
1522int cgroup_seqfile_release(struct inode *inode, struct file *file)
1523{
1524 struct seq_file *seq = file->private_data;
1525 kfree(seq->private);
1526 return single_release(inode, file);
1527}
1528
1529static struct file_operations cgroup_seqfile_operations = {
1530 .read = seq_read,
1531 .llseek = seq_lseek,
1532 .release = cgroup_seqfile_release,
1533};
1534
1495static int cgroup_file_open(struct inode *inode, struct file *file) 1535static int cgroup_file_open(struct inode *inode, struct file *file)
1496{ 1536{
1497 int err; 1537 int err;
@@ -1504,7 +1544,18 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
1504 cft = __d_cft(file->f_dentry); 1544 cft = __d_cft(file->f_dentry);
1505 if (!cft) 1545 if (!cft)
1506 return -ENODEV; 1546 return -ENODEV;
1507 if (cft->open) 1547 if (cft->read_map) {
1548 struct cgroup_seqfile_state *state =
1549 kzalloc(sizeof(*state), GFP_USER);
1550 if (!state)
1551 return -ENOMEM;
1552 state->cft = cft;
1553 state->cgroup = __d_cgrp(file->f_dentry->d_parent);
1554 file->f_op = &cgroup_seqfile_operations;
1555 err = single_open(file, cgroup_seqfile_show, state);
1556 if (err < 0)
1557 kfree(state);
1558 } else if (cft->open)
1508 err = cft->open(inode, file); 1559 err = cft->open(inode, file);
1509 else 1560 else
1510 err = 0; 1561 err = 0;