aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@parallels.com>2013-03-11 05:12:45 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-04-17 14:51:01 -0400
commit48f6a7a511ef8823fdff39afee0320092d43a8a0 (patch)
tree0ecdea997c4cbf8a5b8f76eed1bbb06fc4661c2b /fs/proc
parent5ed67f05f66c41e39880a6d61358438a25f9fee5 (diff)
posix-timers: Introduce /proc/PID/timers file
Currently kernel doesn't provide any API for getting info about what posix timers are configured by processes. It's implied, that a process which configured some timers, knows what it did. However, for external tools it's impossible to get this information. In particular, this is critical for checkpoint-restore project to have this info. Introduce a per-pid proc file with information about posix timers. Since these timers are shared between threads, this file is present on tgid level only, no such thing in tid subdirs. The file format is expected to be the "/proc/<pid>/smaps"-like, i.e. each timer will occupy seveal lines to allow for future extending. Each new timer entry starts with the ID: <number> line which is added by this patch. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Matthew Helsley <matt.helsley@gmail.com> Link: http://lkml.kernel.org/r/513DA00D.6070009@parallels.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 69078c7cef1f..01def9f8aa74 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -86,6 +86,7 @@
86#include <linux/fs_struct.h> 86#include <linux/fs_struct.h>
87#include <linux/slab.h> 87#include <linux/slab.h>
88#include <linux/flex_array.h> 88#include <linux/flex_array.h>
89#include <linux/posix-timers.h>
89#ifdef CONFIG_HARDWALL 90#ifdef CONFIG_HARDWALL
90#include <asm/hardwall.h> 91#include <asm/hardwall.h>
91#endif 92#endif
@@ -2013,6 +2014,85 @@ static const struct file_operations proc_map_files_operations = {
2013 .llseek = default_llseek, 2014 .llseek = default_llseek,
2014}; 2015};
2015 2016
2017struct timers_private {
2018 struct pid *pid;
2019 struct task_struct *task;
2020 struct sighand_struct *sighand;
2021 unsigned long flags;
2022};
2023
2024static void *timers_start(struct seq_file *m, loff_t *pos)
2025{
2026 struct timers_private *tp = m->private;
2027
2028 tp->task = get_pid_task(tp->pid, PIDTYPE_PID);
2029 if (!tp->task)
2030 return ERR_PTR(-ESRCH);
2031
2032 tp->sighand = lock_task_sighand(tp->task, &tp->flags);
2033 if (!tp->sighand)
2034 return ERR_PTR(-ESRCH);
2035
2036 return seq_list_start(&tp->task->signal->posix_timers, *pos);
2037}
2038
2039static void *timers_next(struct seq_file *m, void *v, loff_t *pos)
2040{
2041 struct timers_private *tp = m->private;
2042 return seq_list_next(v, &tp->task->signal->posix_timers, pos);
2043}
2044
2045static void timers_stop(struct seq_file *m, void *v)
2046{
2047 struct timers_private *tp = m->private;
2048
2049 if (tp->sighand) {
2050 unlock_task_sighand(tp->task, &tp->flags);
2051 tp->sighand = NULL;
2052 }
2053
2054 if (tp->task) {
2055 put_task_struct(tp->task);
2056 tp->task = NULL;
2057 }
2058}
2059
2060static int show_timer(struct seq_file *m, void *v)
2061{
2062 struct k_itimer *timer;
2063
2064 timer = list_entry((struct list_head *)v, struct k_itimer, list);
2065 seq_printf(m, "ID: %d\n", timer->it_id);
2066
2067 return 0;
2068}
2069
2070static const struct seq_operations proc_timers_seq_ops = {
2071 .start = timers_start,
2072 .next = timers_next,
2073 .stop = timers_stop,
2074 .show = show_timer,
2075};
2076
2077static int proc_timers_open(struct inode *inode, struct file *file)
2078{
2079 struct timers_private *tp;
2080
2081 tp = __seq_open_private(file, &proc_timers_seq_ops,
2082 sizeof(struct timers_private));
2083 if (!tp)
2084 return -ENOMEM;
2085
2086 tp->pid = proc_pid(inode);
2087 return 0;
2088}
2089
2090static const struct file_operations proc_timers_operations = {
2091 .open = proc_timers_open,
2092 .read = seq_read,
2093 .llseek = seq_lseek,
2094 .release = seq_release_private,
2095};
2016#endif /* CONFIG_CHECKPOINT_RESTORE */ 2096#endif /* CONFIG_CHECKPOINT_RESTORE */
2017 2097
2018static struct dentry *proc_pident_instantiate(struct inode *dir, 2098static struct dentry *proc_pident_instantiate(struct inode *dir,
@@ -2583,6 +2663,9 @@ static const struct pid_entry tgid_base_stuff[] = {
2583 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), 2663 REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations),
2584 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), 2664 REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
2585#endif 2665#endif
2666#ifdef CONFIG_CHECKPOINT_RESTORE
2667 REG("timers", S_IRUGO, proc_timers_operations),
2668#endif
2586}; 2669};
2587 2670
2588static int proc_tgid_base_readdir(struct file * filp, 2671static int proc_tgid_base_readdir(struct file * filp,