#include <linux/inetdevice.h>
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/fdtable.h>
#include <linux/swap.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/device.h>
-#include "lttng-events.h"
-#include "lttng-tracer.h"
-#include "wrapper/irqdesc.h"
-#include "wrapper/spinlock.h"
-#include "wrapper/fdtable.h"
-#include "wrapper/nsproxy.h"
-#include "wrapper/irq.h"
-#include "wrapper/tracepoint.h"
-#include "wrapper/genhd.h"
+#include <lttng-events.h>
+#include <lttng-tracer.h>
+#include <wrapper/irqdesc.h>
+#include <wrapper/spinlock.h>
+#include <wrapper/fdtable.h>
+#include <wrapper/irq.h>
+#include <wrapper/tracepoint.h>
+#include <wrapper/genhd.h>
+#include <wrapper/file.h>
+#include <wrapper/fdtable.h>
#ifdef CONFIG_LTTNG_HAS_LIST_IRQ
#include <linux/irq.h>
/* Define the tracepoints, but do not build the probes */
#define CREATE_TRACE_POINTS
-#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module
+#define TRACE_INCLUDE_PATH instrumentation/events/lttng-module
#define TRACE_INCLUDE_FILE lttng-statedump
-#include "instrumentation/events/lttng-module/lttng-statedump.h"
+#define LTTNG_INSTRUMENTATION
+#include <instrumentation/events/lttng-module/lttng-statedump.h>
DEFINE_TRACE(lttng_statedump_block_device);
DEFINE_TRACE(lttng_statedump_end);
char *page;
struct lttng_session *session;
struct task_struct *p;
- struct fdtable *fdt;
+ struct files_struct *files;
};
/*
const struct lttng_fd_ctx *ctx = p;
const char *s = d_path(&file->f_path, ctx->page, PAGE_SIZE);
unsigned int flags = file->f_flags;
+ struct fdtable *fdt;
/*
* We don't expose kernel internal flags, only userspace-visible
* flags.
*/
flags &= ~FMODE_NONOTIFY;
- if (test_bit(fd, ctx->fdt->close_on_exec))
+ fdt = files_fdtable(ctx->files);
+ /*
+ * We need to check here again whether fd is within the fdt
+ * max_fds range, because we might be seeing a different
+ * files_fdtable() than iterate_fd(), assuming only RCU is
+ * protecting the read. In reality, iterate_fd() holds
+ * file_lock, which should ensure the fdt does not change while
+ * the lock is taken, but we are not aware whether this is
+ * guaranteed or not, so play safe.
+ */
+ if (fd < fdt->max_fds && lttng_close_on_exec(fd, fdt))
flags |= O_CLOEXEC;
if (IS_ERR(s)) {
struct dentry *dentry = file->f_path.dentry;
struct task_struct *p, char *tmp)
{
struct lttng_fd_ctx ctx = { .page = tmp, .session = session, .p = p };
+ struct files_struct *files;
task_lock(p);
- ctx.fdt = files_fdtable(p->files);
- lttng_iterate_fd(p->files, 0, lttng_dump_one_fd, &ctx);
+ files = p->files;
+ if (!files)
+ goto end;
+ ctx.files = files;
+ lttng_iterate_fd(files, 0, lttng_dump_one_fd, &ctx);
+end:
task_unlock(p);
}
int lttng_enumerate_file_descriptors(struct lttng_session *session)
{
struct task_struct *p;
- char *tmp = (char *) __get_free_page(GFP_KERNEL);
+ char *tmp;
+
+ tmp = (char *) __get_free_page(GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
/* Enumerate active file descriptors */
rcu_read_lock();
down_read(&mm->mmap_sem);
while (map) {
if (map->vm_file)
- ino = map->vm_file->f_dentry->d_inode->i_ino;
+ ino = map->vm_file->lttng_f_dentry->d_inode->i_ino;
else
ino = 0;
trace_lttng_statedump_vm_map(session, p, map, ino);
#endif
static
-void lttng_list_interrupts(struct lttng_session *session)
+int lttng_list_interrupts(struct lttng_session *session)
{
unsigned int irq;
unsigned long flags = 0;
wrapper_desc_spin_unlock(&desc->lock);
local_irq_restore(flags);
}
+ return 0;
#undef irq_to_desc
}
#else
static inline
-void lttng_list_interrupts(struct lttng_session *session)
+int lttng_list_interrupts(struct lttng_session *session)
{
+ return 0;
}
#endif
+/*
+ * Called with task lock held.
+ */
static
void lttng_statedump_process_ns(struct lttng_session *session,
struct task_struct *p,
enum lttng_execution_submode submode,
enum lttng_process_status status)
{
- struct nsproxy *proxy;
struct pid_namespace *pid_ns;
- rcu_read_lock();
- proxy = task_nsproxy(p);
- if (proxy) {
- pid_ns = lttng_get_proxy_pid_ns(proxy);
- do {
- trace_lttng_statedump_process_state(session,
- p, type, mode, submode, status, pid_ns);
- pid_ns = pid_ns->parent;
- } while (pid_ns);
- } else {
+ pid_ns = task_active_pid_ns(p);
+ do {
trace_lttng_statedump_process_state(session,
- p, type, mode, submode, status, NULL);
- }
- rcu_read_unlock();
+ p, type, mode, submode, status, pid_ns);
+ pid_ns = pid_ns ? pid_ns->parent : NULL;
+ } while (pid_ns);
}
static
static
int do_lttng_statedump(struct lttng_session *session)
{
- int cpu;
+ int cpu, ret;
trace_lttng_statedump_start(session);
- lttng_enumerate_process_states(session);
- lttng_enumerate_file_descriptors(session);
- /* FIXME lttng_enumerate_vm_maps(session); */
- lttng_list_interrupts(session);
- lttng_enumerate_network_ip_interface(session);
- lttng_enumerate_block_devices(session);
+ ret = lttng_enumerate_process_states(session);
+ if (ret)
+ return ret;
+ ret = lttng_enumerate_file_descriptors(session);
+ if (ret)
+ return ret;
+ /*
+ * FIXME
+ * ret = lttng_enumerate_vm_maps(session);
+ * if (ret)
+ * return ret;
+ */
+ ret = lttng_list_interrupts(session);
+ if (ret)
+ return ret;
+ ret = lttng_enumerate_network_ip_interface(session);
+ if (ret)
+ return ret;
+ ret = lttng_enumerate_block_devices(session);
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOSYS:
+ printk(KERN_WARNING "LTTng: block device enumeration is not supported by kernel\n");
+ break;
+ default:
+ return ret;
+ }
/* TODO lttng_dump_idt_table(session); */
/* TODO lttng_dump_softirq_vec(session); */