Implement listing of pid tracker content
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 28 Jan 2015 14:48:56 +0000 (09:48 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 31 Mar 2015 18:34:02 +0000 (14:34 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
lttng-abi.c
lttng-abi.h
lttng-events.c
lttng-events.h
lttng-tracker-pid.c

index f3d98fc1fd561fc4244854bcc4d3396bdfbcbabf..81d813c512892bdb3d0ddef33ae45abad8a452ef 100644 (file)
@@ -510,6 +510,8 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return lttng_session_track_pid(session, (int) arg);
        case LTTNG_KERNEL_SESSION_UNTRACK_PID:
                return lttng_session_untrack_pid(session, (int) arg);
+       case LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS:
+               return lttng_session_list_tracker_pids(session);
        default:
                return -ENOIOCTLCMD;
        }
index bcea06e33b1cf3f2cb916711ca127b9d31e212b6..275c3496e867382dc2c55781e0f74524a763f752 100644 (file)
@@ -189,6 +189,7 @@ struct lttng_kernel_context {
        _IOR(0xF6, 0x58, int32_t)
 #define LTTNG_KERNEL_SESSION_UNTRACK_PID       \
        _IOR(0xF6, 0x59, int32_t)
+#define LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS _IO(0xF6, 0x58)
 
 /* Channel FD ioctl */
 #define LTTNG_KERNEL_STREAM                    _IO(0xF6, 0x62)
index 8a48c6b5dc6f094132b24ed7640415a6cbd74ae1..d7efd425e88c9b2ed109ee11d12fbf919f67eba3 100644 (file)
 #include <linux/jiffies.h>
 #include <linux/utsname.h>
 #include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
+#include "wrapper/file.h"
 #include "wrapper/uuid.h"
 #include "wrapper/vmalloc.h"   /* for wrapper_vmalloc_sync_all() */
 #include "wrapper/random.h"
@@ -660,6 +664,163 @@ unlock:
        return ret;
 }
 
+static
+void *pid_list_start(struct seq_file *m, loff_t *pos)
+{
+       struct lttng_session *session = m->private;
+       struct lttng_pid_tracker *lpf;
+       struct lttng_pid_hash_node *e;
+       int iter = 0, i;
+
+       mutex_lock(&sessions_mutex);
+       lpf = session->pid_tracker;
+       if (lpf) {
+               for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) {
+                       struct hlist_head *head = &lpf->pid_hash[i];
+
+                       hlist_for_each_entry(e, head, hlist) {
+                               if (iter++ >= *pos)
+                                       return e;
+                       }
+               }
+       } else {
+               /* PID tracker disabled. */
+               if (iter >= *pos && iter == 0) {
+                       return session; /* empty tracker */
+               }
+               iter++;
+       }
+       /* End of list */
+       return NULL;
+}
+
+/* Called with sessions_mutex held. */
+static
+void *pid_list_next(struct seq_file *m, void *p, loff_t *ppos)
+{
+       struct lttng_session *session = m->private;
+       struct lttng_pid_tracker *lpf;
+       struct lttng_pid_hash_node *e;
+       int iter = 0, i;
+
+       (*ppos)++;
+       lpf = session->pid_tracker;
+       if (lpf) {
+               for (i = 0; i < LTTNG_PID_TABLE_SIZE; i++) {
+                       struct hlist_head *head = &lpf->pid_hash[i];
+
+                       hlist_for_each_entry(e, head, hlist) {
+                               if (iter++ >= *ppos)
+                                       return e;
+                       }
+               }
+       } else {
+               /* PID tracker disabled. */
+               if (iter >= *ppos && iter == 0)
+                       return session; /* empty tracker */
+               iter++;
+       }
+
+       /* End of list */
+       return NULL;
+}
+
+static
+void pid_list_stop(struct seq_file *m, void *p)
+{
+       mutex_unlock(&sessions_mutex);
+}
+
+static
+int pid_list_show(struct seq_file *m, void *p)
+{
+       int pid;
+
+       if (p == m->private) {
+               /* Tracker disabled. */
+               pid = -1;
+       } else {
+               const struct lttng_pid_hash_node *e = p;
+
+               pid = lttng_pid_tracker_get_node_pid(e);
+       }
+       seq_printf(m,   "process { pid = %d; };\n", pid);
+       return 0;
+}
+
+static
+const struct seq_operations lttng_tracker_pids_list_seq_ops = {
+       .start = pid_list_start,
+       .next = pid_list_next,
+       .stop = pid_list_stop,
+       .show = pid_list_show,
+};
+
+static
+int lttng_tracker_pids_list_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &lttng_tracker_pids_list_seq_ops);
+}
+
+static
+int lttng_tracker_pids_list_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *m = file->private_data;
+       struct lttng_session *session = m->private;
+       int ret;
+
+       WARN_ON_ONCE(!session);
+       ret = seq_release(inode, file);
+       if (!ret && session)
+               fput(session->file);
+       return ret;
+}
+
+const struct file_operations lttng_tracker_pids_list_fops = {
+       .owner = THIS_MODULE,
+       .open = lttng_tracker_pids_list_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = lttng_tracker_pids_list_release,
+};
+
+int lttng_session_list_tracker_pids(struct lttng_session *session)
+{
+       struct file *tracker_pids_list_file;
+       struct seq_file *m;
+       int file_fd, ret;
+
+       file_fd = lttng_get_unused_fd();
+       if (file_fd < 0) {
+               ret = file_fd;
+               goto fd_error;
+       }
+
+       tracker_pids_list_file = anon_inode_getfile("[lttng_tracker_pids_list]",
+                                         &lttng_tracker_pids_list_fops,
+                                         NULL, O_RDWR);
+       if (IS_ERR(tracker_pids_list_file)) {
+               ret = PTR_ERR(tracker_pids_list_file);
+               goto file_error;
+       }
+       ret = lttng_tracker_pids_list_fops.open(NULL, tracker_pids_list_file);
+       if (ret < 0)
+               goto open_error;
+       m = tracker_pids_list_file->private_data;
+       m->private = session;
+       fd_install(file_fd, tracker_pids_list_file);
+       atomic_long_inc(&session->file->f_count);
+
+       return file_fd;
+
+open_error:
+       fput(tracker_pids_list_file);
+file_error:
+       put_unused_fd(file_fd);
+fd_error:
+       return ret;
+}
+
 /*
  * Serialize at most one packet worth of metadata into a metadata
  * channel.
index 7d3314590384906fbd95b2406f593c59d1806cd0..d761360c7757009971ad9f6b8a5a0c0f3c0f561c 100644 (file)
@@ -336,6 +336,11 @@ struct lttng_pid_tracker {
        struct hlist_head pid_hash[LTTNG_PID_TABLE_SIZE];
 };
 
+struct lttng_pid_hash_node {
+       struct hlist_node hlist;
+       int pid;
+};
+
 struct lttng_session {
        int active;                     /* Is trace session active ? */
        int been_active;                /* Has trace session been active ? */
@@ -412,6 +417,7 @@ void lttng_probes_exit(void);
 int lttng_metadata_output_channel(struct lttng_metadata_stream *stream,
                struct channel *chan);
 
+int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node);
 struct lttng_pid_tracker *lttng_pid_tracker_create(void);
 void lttng_pid_tracker_destroy(struct lttng_pid_tracker *lpf);
 bool lttng_pid_tracker_lookup(struct lttng_pid_tracker *lpf, int pid);
@@ -421,6 +427,8 @@ int lttng_pid_tracker_del(struct lttng_pid_tracker *lpf, int pid);
 int lttng_session_track_pid(struct lttng_session *session, int pid);
 int lttng_session_untrack_pid(struct lttng_session *session, int pid);
 
+int lttng_session_list_tracker_pids(struct lttng_session *session);
+
 #if defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
 int lttng_syscalls_register(struct lttng_channel *chan, void *filter);
 int lttng_syscalls_unregister(struct lttng_channel *chan);
index f8f0a51dcc1e738727286b69e28f343ac43476e1..a62ec4e459343ea9ea615f58e78651dd7697a9e9 100644 (file)
  * sessions_mutex across calls to create, destroy, add, and del
  * functions of this API.
  */
-struct lttng_pid_hash_node {
-       struct hlist_node hlist;
-       int pid;
-};
+int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node *node)
+{
+       return node->pid;
+}
 
 /*
  * Lookup performed from RCU read-side critical section (RCU sched),
This page took 0.031614 seconds and 4 git commands to generate.