Skip to content

Commit

Permalink
cpuset: convert away from cftype->read()
Browse files Browse the repository at this point in the history
In preparation of conversion to kernfs, cgroup file handling is being
consolidated so that it can be easily mapped to the seq_file based
interface of kernfs.

All users of cftype->read() can be easily served, usually better, by
seq_file and other methods.  Rename cpuset_common_file_read() to
cpuset_common_read_seq_string() and convert it to use
read_seq_string() interface instead.  This not only simplifies the
code but also makes it more versatile.  Before, the file couldn't
output if the result is longer than PAGE_SIZE.  After the conversion,
seq_file automatically grows the buffer until the output can fit.

This patch doesn't make any visible behavior changes except for being
able to handle output larger than PAGE_SIZE.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
  • Loading branch information
htejun committed Dec 5, 2013
1 parent 44ffc75 commit 51ffe41
Showing 1 changed file with 24 additions and 47 deletions.
71 changes: 24 additions & 47 deletions kernel/cpuset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1731,66 +1731,43 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css,
* used, list of ranges of sequential numbers, is variable length,
* and since these maps can change value dynamically, one could read
* gibberish by doing partial reads while a list was changing.
* A single large read to a buffer that crosses a page boundary is
* ok, because the result being copied to user land is not recomputed
* across a page fault.
*/

static size_t cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
{
size_t count;

mutex_lock(&callback_mutex);
count = cpulist_scnprintf(page, PAGE_SIZE, cs->cpus_allowed);
mutex_unlock(&callback_mutex);

return count;
}

static size_t cpuset_sprintf_memlist(char *page, struct cpuset *cs)
{
size_t count;

mutex_lock(&callback_mutex);
count = nodelist_scnprintf(page, PAGE_SIZE, cs->mems_allowed);
mutex_unlock(&callback_mutex);

return count;
}

static ssize_t cpuset_common_file_read(struct cgroup_subsys_state *css,
struct cftype *cft, struct file *file,
char __user *buf, size_t nbytes,
loff_t *ppos)
static int cpuset_common_read_seq_string(struct cgroup_subsys_state *css,
struct cftype *cft,
struct seq_file *sf)
{
struct cpuset *cs = css_cs(css);
cpuset_filetype_t type = cft->private;
char *page;
ssize_t retval = 0;
char *s;
ssize_t count;
char *buf, *s;
int ret = 0;

if (!(page = (char *)__get_free_page(GFP_TEMPORARY)))
return -ENOMEM;
count = seq_get_buf(sf, &buf);
s = buf;

s = page;
mutex_lock(&callback_mutex);

switch (type) {
case FILE_CPULIST:
s += cpuset_sprintf_cpulist(s, cs);
s += cpulist_scnprintf(s, count, cs->cpus_allowed);
break;
case FILE_MEMLIST:
s += cpuset_sprintf_memlist(s, cs);
s += nodelist_scnprintf(s, count, cs->mems_allowed);
break;
default:
retval = -EINVAL;
goto out;
ret = -EINVAL;
goto out_unlock;
}
*s++ = '\n';

retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
out:
free_page((unsigned long)page);
return retval;
if (s < buf + count - 1) {
*s++ = '\n';
seq_commit(sf, s - buf);
} else {
seq_commit(sf, -1);
}
out_unlock:
mutex_unlock(&callback_mutex);
return ret;
}

static u64 cpuset_read_u64(struct cgroup_subsys_state *css, struct cftype *cft)
Expand Down Expand Up @@ -1847,15 +1824,15 @@ static s64 cpuset_read_s64(struct cgroup_subsys_state *css, struct cftype *cft)
static struct cftype files[] = {
{
.name = "cpus",
.read = cpuset_common_file_read,
.read_seq_string = cpuset_common_read_seq_string,
.write_string = cpuset_write_resmask,
.max_write_len = (100U + 6 * NR_CPUS),
.private = FILE_CPULIST,
},

{
.name = "mems",
.read = cpuset_common_file_read,
.read_seq_string = cpuset_common_read_seq_string,
.write_string = cpuset_write_resmask,
.max_write_len = (100U + 6 * MAX_NUMNODES),
.private = FILE_MEMLIST,
Expand Down

0 comments on commit 51ffe41

Please sign in to comment.