Skip to content

Commit

Permalink
procfs: allow threads to rename siblings via /proc/pid/tasks/tid/comm
Browse files Browse the repository at this point in the history
Setting a thread's comm to be something unique is a very useful ability
and is helpful for debugging complicated threaded applications.  However
currently the only way to set a thread name is for the thread to name
itself via the PR_SET_NAME prctl.

However, there may be situations where it would be advantageous for a
thread dispatcher to be naming the threads its managing, rather then
having the threads self-describe themselves.  This sort of behavior is
available on other systems via the pthread_setname_np() interface.

This patch exports a task's comm via proc/pid/comm and
proc/pid/task/tid/comm interfaces, and allows thread siblings to write to
these values.

[akpm@linux-foundation.org: cleanups]
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Mike Fulton <fultonm@ca.ibm.com>
Cc: Sean Foley <Sean_Foley@ca.ibm.com>
Cc: Darren Hart <dvhltc@us.ibm.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
john stultz authored and Linus Torvalds committed Dec 15, 2009
1 parent 7e1e0ef commit 4614a69
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Table of Contents
3.3 /proc/<pid>/io - Display the IO accounting fields
3.4 /proc/<pid>/coredump_filter - Core dump filtering settings
3.5 /proc/<pid>/mountinfo - Information about mounts
3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm


------------------------------------------------------------------------------
Expand Down Expand Up @@ -1409,3 +1410,11 @@ For more information on mount propagation see:

Documentation/filesystems/sharedsubtree.txt


3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
--------------------------------------------------------
These files provide a method to access a tasks comm value. It also allows for
a task to set its own or one of its thread siblings comm value. The comm value
is limited in size compared to the cmdline value, so writing anything longer
then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
comm value.
9 changes: 9 additions & 0 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,15 @@ char *get_task_comm(char *buf, struct task_struct *tsk)
void set_task_comm(struct task_struct *tsk, char *buf)
{
task_lock(tsk);

/*
* Threads may access current->comm without holding
* the task lock, so write the string carefully.
* Readers without a lock may see incomplete new
* names but are safe from non-terminating string reads.
*/
memset(tsk->comm, 0, TASK_COMM_LEN);
wmb();
strlcpy(tsk->comm, buf, sizeof(tsk->comm));
task_unlock(tsk);
perf_event_comm(tsk);
Expand Down
68 changes: 68 additions & 0 deletions fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,72 @@ static const struct file_operations proc_pid_sched_operations = {

#endif

static ssize_t comm_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct task_struct *p;
char buffer[TASK_COMM_LEN];

memset(buffer, 0, sizeof(buffer));
if (count > sizeof(buffer) - 1)
count = sizeof(buffer) - 1;
if (copy_from_user(buffer, buf, count))
return -EFAULT;

p = get_proc_task(inode);
if (!p)
return -ESRCH;

if (same_thread_group(current, p))
set_task_comm(p, buffer);
else
count = -EINVAL;

put_task_struct(p);

return count;
}

static int comm_show(struct seq_file *m, void *v)
{
struct inode *inode = m->private;
struct task_struct *p;

p = get_proc_task(inode);
if (!p)
return -ESRCH;

task_lock(p);
seq_printf(m, "%s\n", p->comm);
task_unlock(p);

put_task_struct(p);

return 0;
}

static int comm_open(struct inode *inode, struct file *filp)
{
int ret;

ret = single_open(filp, comm_show, NULL);
if (!ret) {
struct seq_file *m = filp->private_data;

m->private = inode;
}
return ret;
}

static const struct file_operations proc_pid_set_comm_operations = {
.open = comm_open,
.read = seq_read,
.write = comm_write,
.llseek = seq_lseek,
.release = single_release,
};

/*
* We added or removed a vma mapping the executable. The vmas are only mapped
* during exec and are not mapped with the mmap system call.
Expand Down Expand Up @@ -2504,6 +2570,7 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
INF("syscall", S_IRUSR, proc_pid_syscall),
#endif
Expand Down Expand Up @@ -2838,6 +2905,7 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
INF("syscall", S_IRUSR, proc_pid_syscall),
#endif
Expand Down

0 comments on commit 4614a69

Please sign in to comment.