aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohn stultz <johnstul@us.ibm.com>2009-12-14 21:00:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:24 -0500
commit4614a696bd1c3a9af3a08f0e5874830a85b889d4 (patch)
tree0b363d89ce612ab8557d49ab8b0f49b8520ffa66
parent7e1e0ef22c9ba9f797d7c4448feee722584bba5c (diff)
procfs: allow threads to rename siblings via /proc/pid/tasks/tid/comm
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>
-rw-r--r--Documentation/filesystems/proc.txt9
-rw-r--r--fs/exec.c9
-rw-r--r--fs/proc/base.c68
3 files changed, 86 insertions, 0 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 94b9f2056f4c..220cc6376ef8 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -38,6 +38,7 @@ Table of Contents
38 3.3 /proc/<pid>/io - Display the IO accounting fields 38 3.3 /proc/<pid>/io - Display the IO accounting fields
39 3.4 /proc/<pid>/coredump_filter - Core dump filtering settings 39 3.4 /proc/<pid>/coredump_filter - Core dump filtering settings
40 3.5 /proc/<pid>/mountinfo - Information about mounts 40 3.5 /proc/<pid>/mountinfo - Information about mounts
41 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
41 42
42 43
43------------------------------------------------------------------------------ 44------------------------------------------------------------------------------
@@ -1409,3 +1410,11 @@ For more information on mount propagation see:
1409 1410
1410 Documentation/filesystems/sharedsubtree.txt 1411 Documentation/filesystems/sharedsubtree.txt
1411 1412
1413
14143.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm
1415--------------------------------------------------------
1416These files provide a method to access a tasks comm value. It also allows for
1417a task to set its own or one of its thread siblings comm value. The comm value
1418is limited in size compared to the cmdline value, so writing anything longer
1419then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
1420comm value.
diff --git a/fs/exec.c b/fs/exec.c
index c0c636e34f60..623a5cc3076a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -923,6 +923,15 @@ char *get_task_comm(char *buf, struct task_struct *tsk)
923void set_task_comm(struct task_struct *tsk, char *buf) 923void set_task_comm(struct task_struct *tsk, char *buf)
924{ 924{
925 task_lock(tsk); 925 task_lock(tsk);
926
927 /*
928 * Threads may access current->comm without holding
929 * the task lock, so write the string carefully.
930 * Readers without a lock may see incomplete new
931 * names but are safe from non-terminating string reads.
932 */
933 memset(tsk->comm, 0, TASK_COMM_LEN);
934 wmb();
926 strlcpy(tsk->comm, buf, sizeof(tsk->comm)); 935 strlcpy(tsk->comm, buf, sizeof(tsk->comm));
927 task_unlock(tsk); 936 task_unlock(tsk);
928 perf_event_comm(tsk); 937 perf_event_comm(tsk);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index af643b5aefe8..4df4a464a919 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1265,6 +1265,72 @@ static const struct file_operations proc_pid_sched_operations = {
1265 1265
1266#endif 1266#endif
1267 1267
1268static ssize_t comm_write(struct file *file, const char __user *buf,
1269 size_t count, loff_t *offset)
1270{
1271 struct inode *inode = file->f_path.dentry->d_inode;
1272 struct task_struct *p;
1273 char buffer[TASK_COMM_LEN];
1274
1275 memset(buffer, 0, sizeof(buffer));
1276 if (count > sizeof(buffer) - 1)
1277 count = sizeof(buffer) - 1;
1278 if (copy_from_user(buffer, buf, count))
1279 return -EFAULT;
1280
1281 p = get_proc_task(inode);
1282 if (!p)
1283 return -ESRCH;
1284
1285 if (same_thread_group(current, p))
1286 set_task_comm(p, buffer);
1287 else
1288 count = -EINVAL;
1289
1290 put_task_struct(p);
1291
1292 return count;
1293}
1294
1295static int comm_show(struct seq_file *m, void *v)
1296{
1297 struct inode *inode = m->private;
1298 struct task_struct *p;
1299
1300 p = get_proc_task(inode);
1301 if (!p)
1302 return -ESRCH;
1303
1304 task_lock(p);
1305 seq_printf(m, "%s\n", p->comm);
1306 task_unlock(p);
1307
1308 put_task_struct(p);
1309
1310 return 0;
1311}
1312
1313static int comm_open(struct inode *inode, struct file *filp)
1314{
1315 int ret;
1316
1317 ret = single_open(filp, comm_show, NULL);
1318 if (!ret) {
1319 struct seq_file *m = filp->private_data;
1320
1321 m->private = inode;
1322 }
1323 return ret;
1324}
1325
1326static const struct file_operations proc_pid_set_comm_operations = {
1327 .open = comm_open,
1328 .read = seq_read,
1329 .write = comm_write,
1330 .llseek = seq_lseek,
1331 .release = single_release,
1332};
1333
1268/* 1334/*
1269 * We added or removed a vma mapping the executable. The vmas are only mapped 1335 * We added or removed a vma mapping the executable. The vmas are only mapped
1270 * during exec and are not mapped with the mmap system call. 1336 * during exec and are not mapped with the mmap system call.
@@ -2504,6 +2570,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2504#ifdef CONFIG_SCHED_DEBUG 2570#ifdef CONFIG_SCHED_DEBUG
2505 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), 2571 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
2506#endif 2572#endif
2573 REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
2507#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 2574#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
2508 INF("syscall", S_IRUSR, proc_pid_syscall), 2575 INF("syscall", S_IRUSR, proc_pid_syscall),
2509#endif 2576#endif
@@ -2838,6 +2905,7 @@ static const struct pid_entry tid_base_stuff[] = {
2838#ifdef CONFIG_SCHED_DEBUG 2905#ifdef CONFIG_SCHED_DEBUG
2839 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), 2906 REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
2840#endif 2907#endif
2908 REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
2841#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 2909#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
2842 INF("syscall", S_IRUSR, proc_pid_syscall), 2910 INF("syscall", S_IRUSR, proc_pid_syscall),
2843#endif 2911#endif