LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_state,
TP_PROTO(struct lttng_session *session,
struct task_struct *p,
- int type, int mode, int submode, int status),
- TP_ARGS(session, p, type, mode, submode, status),
+ int type, int mode, int submode, int status,
+ struct files_struct *files),
+ TP_ARGS(session, p, type, mode, submode, status, files),
TP_FIELDS(
ctf_integer(pid_t, tid, p->pid)
ctf_integer(pid_t, pid, p->tgid)
ctf_integer(int, submode, submode)
ctf_integer(int, status, status)
ctf_integer(unsigned int, cpu, task_cpu(p))
+ ctf_integer_hex(struct files_struct *, file_table_address, files)
)
)
LTTNG_TRACEPOINT_EVENT(lttng_statedump_file_descriptor,
TP_PROTO(struct lttng_session *session,
- struct task_struct *p, int fd, const char *filename,
+ struct files_struct *files,
+ int fd, const char *filename,
unsigned int flags, fmode_t fmode),
- TP_ARGS(session, p, fd, filename, flags, fmode),
+ TP_ARGS(session, files, fd, filename, flags, fmode),
TP_FIELDS(
- ctf_integer(pid_t, pid, p->tgid)
+ ctf_integer_hex(struct files_struct *, file_table_address, files)
ctf_integer(int, fd, fd)
ctf_integer_oct(unsigned int, flags, flags)
ctf_integer_hex(fmode_t, fmode, fmode)
struct lttng_fd_ctx {
char *page;
struct lttng_session *session;
- struct task_struct *p;
struct files_struct *files;
};
/* Make sure we give at least some info */
spin_lock(&dentry->d_lock);
- trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd,
- dentry->d_name.name, flags, file->f_mode);
+ trace_lttng_statedump_file_descriptor(ctx->session,
+ ctx->files, fd, dentry->d_name.name, flags,
+ file->f_mode);
spin_unlock(&dentry->d_lock);
goto end;
}
- trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd, s,
- flags, file->f_mode);
+ trace_lttng_statedump_file_descriptor(ctx->session,
+ ctx->files, fd, s, flags, file->f_mode);
end:
return 0;
}
+/* Called with task lock held. */
static
-void lttng_enumerate_task_fd(struct lttng_session *session,
- struct task_struct *p, char *tmp)
+void lttng_enumerate_files(struct lttng_session *session,
+ struct files_struct *files,
+ char *tmp)
{
- struct lttng_fd_ctx ctx = { .page = tmp, .session = session, .p = p };
- struct files_struct *files;
+ struct lttng_fd_ctx ctx = { .page = tmp, .session = session, .files = files, };
- task_lock(p);
- files = p->files;
- if (!files)
- goto end;
- ctx.files = files;
lttng_iterate_fd(files, 0, lttng_dump_one_fd, &ctx);
-end:
- task_unlock(p);
-}
-
-static
-int lttng_enumerate_file_descriptors(struct lttng_session *session)
-{
- struct task_struct *p;
- char *tmp;
-
- tmp = (char *) __get_free_page(GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
-
- /* Enumerate active file descriptors */
- rcu_read_lock();
- for_each_process(p)
- lttng_enumerate_task_fd(session, p, tmp);
- rcu_read_unlock();
- free_page((unsigned long) tmp);
- return 0;
}
#ifdef LTTNG_HAVE_STATEDUMP_CPU_TOPOLOGY
int lttng_enumerate_process_states(struct lttng_session *session)
{
struct task_struct *g, *p;
+ char *tmp;
+
+ tmp = (char *) __get_free_page(GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
rcu_read_lock();
for_each_process(g) {
+ struct files_struct *prev_files = NULL;
+
p = g;
do {
enum lttng_execution_mode mode =
LTTNG_UNKNOWN;
enum lttng_process_status status;
enum lttng_thread_type type;
+ struct files_struct *files;
task_lock(p);
if (p->exit_state == EXIT_ZOMBIE)
type = LTTNG_USER_THREAD;
else
type = LTTNG_KERNEL_THREAD;
+ files = p->files;
trace_lttng_statedump_process_state(session,
- p, type, mode, submode, status);
+ p, type, mode, submode, status, files);
lttng_statedump_process_ns(session,
p, type, mode, submode, status);
+ /*
+ * As an optimisation for the common case, do not
+ * repeat information for the same files_struct in
+ * two consecutive threads. This is the common case
+ * for threads sharing the same fd table. RCU guarantees
+ * that the same files_struct pointer is not re-used
+ * throughout processes/threads iteration.
+ */
+ if (files && files != prev_files) {
+ lttng_enumerate_files(session, files, tmp);
+ prev_files = files;
+ }
task_unlock(p);
} while_each_thread(g, p);
}
rcu_read_unlock();
+ free_page((unsigned long) tmp);
+
return 0;
}
trace_lttng_statedump_start(session);
ret = lttng_enumerate_process_states(session);
- if (ret)
- return ret;
- ret = lttng_enumerate_file_descriptors(session);
if (ret)
return ret;
/*