2008-01-04 07:04:09

by cheng renquan

[permalink] [raw]
Subject: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

this adds a read-write /proc/<pid>/smp_affinity entry,
just like what /proc/irq/<irq>/smp_affinity does,
so now we can get and set the affinity of tasks by procfs,
this is especially useful used in shell scripts.

this also adds a read-write /proc/<pid>/tasks/<tid>/smp_affinity
for the same purpose.

Cc: Eli M Dow <[email protected]>
Signed-off-by: Denis Cheng <[email protected]>
---
fs/proc/base.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 7411bfb..ca0cbc2 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1083,6 +1083,57 @@ static const struct file_operations proc_pid_sched_operations = {

#endif

+#ifdef CONFIG_SMP
+static ssize_t smp_affinity_read(struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ cpumask_t mask;
+ char *page;
+ ssize_t length;
+ pid_t pid = pid_nr(proc_pid(file->f_dentry->d_inode));
+
+ length = sched_getaffinity(pid, &mask);
+ if (length < 0)
+ return length;
+
+ if (count > PROC_BLOCK_SIZE)
+ count = PROC_BLOCK_SIZE;
+
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+ return -ENOMEM;
+
+ length = cpumask_scnprintf(page, count, mask);
+ length += sprintf(page + length, "\n");
+ length = simple_read_from_buffer(buf, count, ppos, page, length);
+ free_page((unsigned long) page);
+
+ return length;
+}
+
+static ssize_t smp_affinity_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ cpumask_t mask;
+ int ret;
+ pid_t pid = pid_nr(proc_pid(file->f_dentry->d_inode));
+
+ ret = cpumask_parse_user(buf, count, mask);
+ if (ret < 0)
+ return ret;
+ ret = sched_setaffinity(pid, mask);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations proc_smp_affinity_operations = {
+ .read = smp_affinity_read,
+ .write = smp_affinity_write,
+};
+#endif
+
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -2230,6 +2281,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
+#ifdef CONFIG_SMP
+ REG("smp_affinity", S_IRUGO|S_IWUSR, smp_affinity),
+#endif
#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
@@ -2555,6 +2609,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
+#ifdef CONFIG_SMP
+ REG("smp_affinity", S_IRUGO|S_IWUSR, smp_affinity),
+#endif
#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
--
1.5.3.5


2008-01-04 07:39:41

by Paul Jackson

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

Could you also update the file 'Documentation/filesystems/proc.txt' as
part of this patch? It should document /proc/<pid>/* files. Thanks.

(Don't tell anyone that this file doesn't mention /proc/<pid>/cpuset ;).

--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.940.382.4214

2008-01-04 07:54:35

by Paul Jackson

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

Denis wrote:
> + length += sprintf(page + length, "\n");

Could that overrun the 'page' buffer by one byte?

--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.940.382.4214

2008-01-04 15:39:09

by cheng renquan

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

>From d2be88406fdc1d28a7cf0b1a13ca761d625820a5 Mon Sep 17 00:00:00 2001
From: Denis Cheng <[email protected]>
Date: Fri, 4 Jan 2008 14:50:54 +0800
Subject: [PATCH] PROC_FS: get and set the smp affinity of tasks by
read-write /proc/<pid>/smp_affinity

this adds a read-write /proc/<pid>/smp_affinity entry,
just like what /proc/irq/<irq>/smp_affinity does,
so now we can get and set the affinity of tasks by procfs,
this is especially useful used in shell scripts.

this also adds a read-write /proc/<pid>/tasks/<tid>/smp_affinity
for the same purpose.

Cc: Eli M Dow <[email protected]>
Signed-off-by: Denis Cheng <[email protected]>
---
length check copied from kernel/irq/proc.c, now 'page' buffer couldn't
be overrun,

Another way, although Documentation/filesystems/proc.txt is heavily outdated,
I'll add introduction of smp_affinity.

fs/proc/base.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 7411bfb..d768d66 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1083,6 +1083,65 @@ static const struct file_operations
proc_pid_sched_operations = {

#endif

+#ifdef CONFIG_SMP
+static ssize_t smp_affinity_read(struct file *file,
+ char __user *buf, size_t count, loff_t *ppos)
+{
+ cpumask_t mask;
+ char *page;
+ ssize_t length;
+ pid_t pid = pid_nr(proc_pid(file->f_dentry->d_inode));
+
+ length = sched_getaffinity(pid, &mask);
+ if (length < 0)
+ return length;
+
+ if (count > PROC_BLOCK_SIZE)
+ count = PROC_BLOCK_SIZE;
+
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page) {
+ length = -ENOMEM;
+ goto out;
+ }
+
+ length = cpumask_scnprintf(page, count, mask);
+ if (count - length < 2) {
+ length = -EINVAL;
+ goto out_free_page;
+ }
+ length += sprintf(page + length, "\n");
+ length = simple_read_from_buffer(buf, count, ppos, page, length);
+
+out_free_page:
+ free_page((unsigned long)page);
+out:
+ return length;
+}
+
+static ssize_t smp_affinity_write(struct file *file,
+ const char __user *buf, size_t count, loff_t *ppos)
+{
+ cpumask_t mask;
+ int ret;
+ pid_t pid = pid_nr(proc_pid(file->f_dentry->d_inode));
+
+ ret = cpumask_parse_user(buf, count, mask);
+ if (ret < 0)
+ return ret;
+ ret = sched_setaffinity(pid, mask);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations proc_smp_affinity_operations = {
+ .read = smp_affinity_read,
+ .write = smp_affinity_write,
+};
+#endif
+
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -2230,6 +2289,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
+#ifdef CONFIG_SMP
+ REG("smp_affinity", S_IRUGO|S_IWUSR, smp_affinity),
+#endif
#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
@@ -2555,6 +2617,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
INF("schedstat", S_IRUGO, pid_schedstat),
#endif
+#ifdef CONFIG_SMP
+ REG("smp_affinity", S_IRUGO|S_IWUSR, smp_affinity),
+#endif
#ifdef CONFIG_PROC_PID_CPUSET
REG("cpuset", S_IRUGO, cpuset),
#endif
--
1.5.3.5

2008-01-04 19:13:59

by Paul Jackson

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

rael wrote:
> length check copied from kernel/irq/proc.c, now 'page' buffer couldn't
> be overrun,

Thanks.

> although Documentation/filesystems/proc.txt is heavily outdated,
> I'll add introduction of smp_affinity.

Good - my usual benchmark for documentation is that at least one place
in the code or associated documentation clearly describes things.

My main concern in this patch was that there were zero instances of
documentation of this new /proc file. The patch should include a text
explanation of this feature, and put it somewhere.

Documentation/filesystems/proc.txt looked like a reasonable place, but
I don't really care where, nor do I lose as much sleep as I should when
some documentation is incomplete or stale. Just so long as everything
is clearly explained somewhere.

--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.940.382.4214

2008-01-10 00:34:18

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

On Fri, 4 Jan 2008 15:03:41 +0800
Denis Cheng <[email protected]> wrote:

> this adds a read-write /proc/<pid>/smp_affinity entry,
> just like what /proc/irq/<irq>/smp_affinity does,
> so now we can get and set the affinity of tasks by procfs,
> this is especially useful used in shell scripts.
>
> this also adds a read-write /proc/<pid>/tasks/<tid>/smp_affinity
> for the same purpose.

Why not use /usr/bin/taskset?

2008-01-10 02:25:37

by cheng renquan

[permalink] [raw]
Subject: Re: [PATCH] PROC_FS: get and set the smp affinity of tasks by read-write /proc/<pid>/smp_affinity

On Jan 10, 2008 8:33 AM, Andrew Morton <[email protected]> wrote:
> On Fri, 4 Jan 2008 15:03:41 +0800
> Denis Cheng <[email protected]> wrote:
>
> > this adds a read-write /proc/<pid>/smp_affinity entry,
> > just like what /proc/irq/<irq>/smp_affinity does,
> > so now we can get and set the affinity of tasks by procfs,
> > this is especially useful used in shell scripts.
> >
> > this also adds a read-write /proc/<pid>/tasks/<tid>/smp_affinity
> > for the same purpose.
>
> Why not use /usr/bin/taskset?
I know /usr/bin/tasklet is another way to set smp affinity of a task,
it uses the sched_{set,get}affinity system call binary interface, but
add a /proc/<pid>/smp_affinity could give a new choice; and this keeps
consistency with /proc/irq/<irq>/smp_affinity, will be familiar to
most people.

Another way, the sysctl system call binary interface has been marked
deprecated recently, only /proc/sys/ operating interface left; I
wonder this this would be a tendency of virtual filesystem interface
to replace binary interface? In my opinion, vfs text interface is
always better than system call binary interface.

>

--
Denis Cheng