/*
 * Infrastructure for statistic tracing (histogram output).
 *
 * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com>
 *
 * Based on the code from trace_branch.c which is
 * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
 *
 */


#include <linux/list.h>
#include <linux/debugfs.h>
#include "trace_stat.h"
#include "trace.h"


/* List of stat entries from a tracer */
struct trace_stat_list {
	struct list_head	list;
	void			*stat;
};

/* A stat session is the stats output in one file */
struct tracer_stat_session {
	struct list_head	session_list;
	struct tracer_stat	*ts;
	struct list_head	stat_list;
	struct mutex		stat_mutex;
	struct dentry		*file;
};

/* All of the sessions currently in use. Each stat file embed one session */
static LIST_HEAD(all_stat_sessions);
static DEFINE_MUTEX(all_stat_sessions_mutex);

/* The root directory for all stat files */
static struct dentry		*stat_dir;


static void reset_stat_session(struct tracer_stat_session *session)
{
	struct trace_stat_list *node, *next;

	list_for_each_entry_safe(node, next, &session->stat_list, list)
		kfree(node);

	INIT_LIST_HEAD(&session->stat_list);
}

static void destroy_session(struct tracer_stat_session *session)
{
	debugfs_remove(session->file);
	reset_stat_session(session);
	mutex_destroy(&session->stat_mutex);
	kfree(session);
}

/*
 * For tracers that don't provide a stat_cmp callback.
 * This one will force an immediate insertion on tail of
 * the list.
 */
static int dummy_cmp(void *p1, void *p2)
{
	return 1;
}

/*
 * Initialize the stat list at each trace_stat file opening.
 * All of these copies and sorting are required on all opening
 * since the stats could have changed between two file sessions.
 */
static int stat_seq_init(struct tracer_stat_session *session)
{
	struct trace_stat_list *iter_entry, *new_entry;
	struct tracer_stat *ts = session->ts;
	void *stat;
	int ret = 0;
	int i;

	mutex_lock(&session->stat_mutex);
	reset_stat_session(session);

	if (!ts->stat_cmp)
		ts->stat_cmp = dummy_cmp;

	stat = ts->stat_start(ts);
	if (!stat)
		goto exit;

	/*
	 * The first entry. Actually this is the second, but the first
	 * one (the stat_list head) is pointless.
	 */
	new_entry = kmalloc(sizeof(struct trace_stat_list), GFP_KERNEL);
	if (!new_entry) {
		ret = -ENOMEM;
		goto exit;
	}

	INIT_LIST_HEAD(&new_entry->list);

	list_add(&new_entry->list, &session->stat_list);

	new_entry->stat = stat;

	/*
	 * Iterate over the tracer stat entries and store them in a sorted
	 * list.
	 */
	for (i = 1; ; i++) {
		stat = ts->stat_next(stat, i);

		/* End of insertion */
		if (!stat)
			break;

		new_entry = kmalloc(sizeof(struct trace_stat_list), GFP_KERNEL);
		if (!new_entry) {
			ret = -ENOMEM;
			goto exit_free_list;
		}

		INIT_LIST_HEAD(&new_entry->list);
		new_entry->stat = stat;

		list_for_each_entry_reverse(iter_entry, &session->stat_list,
				list) {

			/* Insertion with a descendent sorting */
			if (ts->stat_cmp(iter_entry->stat,
					new_entry->stat) >= 0) {

				list_add(&new_entry->list, &iter_entry->list);
				break;
			}
		}

		/* The current larger value */
		if (list_empty(&new_entry->list))
			list_add(&new_entry->list, &session->stat_list);
	}
exit:
	mutex_unlock(&session->stat_mutex);
	return ret;

exit_free_list:
	reset_stat_session(session);
	mutex_unlock(&session->stat_mutex);
	return ret;
}


static void *stat_seq_start(struct seq_file *s, loff_t *pos)
{
	struct tracer_stat_session *session = s->private;

	/* Prevent from tracer switch or stat_list modification */
	mutex_lock(&session->stat_mutex);

	/* If we are in the beginning of the file, print the headers */
	if (!*pos && session->ts->stat_headers)
		return SEQ_START_TOKEN;

	return seq_list_start(&session->stat_list, *pos);
}

static void *stat_seq_next(struct seq_file *s, void *p, loff_t *pos)
{
	struct tracer_stat_session *session = s->private;

	if (p == SEQ_START_TOKEN)
		return seq_list_start(&session->stat_list, *pos);

	return seq_list_next(p, &session->stat_list, pos);
}

static void stat_seq_stop(struct seq_file *s, void *p)
{
	struct tracer_stat_session *session = s->private;
	mutex_unlock(&session->stat_mutex);
}

static int stat_seq_show(struct seq_file *s, void *v)
{
	struct tracer_stat_session *session = s->private;
	struct trace_stat_list *l = list_entry(v, struct trace_stat_list, list);

	if (v == SEQ_START_TOKEN)
		return session->ts->stat_headers(s);

	return session->ts->stat_show(s, l->stat);
}

static const struct seq_operations trace_stat_seq_ops = {
	.start		= stat_seq_start,
	.next		= stat_seq_next,
	.stop		= stat_seq_stop,
	.show		= stat_seq_show
};

/* The session stat is refilled and resorted at each stat file opening */
static int tracing_stat_open(struct inode *inode, struct file *file)
{
	int ret;

	struct tracer_stat_session *session = inode->i_private;

	ret = seq_open(file, &trace_stat_seq_ops);
	if (!ret) {
		struct seq_file *m = file->private_data;
		m->private = session;
		ret = stat_seq_init(session);
	}

	return ret;
}

/*
 * Avoid consuming memory with our now useless list.
 */
static int tracing_stat_release(struct inode *i, struct file *f)
{
	struct tracer_stat_session *session = i->i_private;

	mutex_lock(&session->stat_mutex);
	reset_stat_session(session);
	mutex_unlock(&session->stat_mutex);

	return 0;
}

static const struct file_operations tracing_stat_fops = {
	.open		= tracing_stat_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= tracing_stat_release
};

static int tracing_stat_init(void)
{
	struct dentry *d_tracing;

	d_tracing = tracing_init_dentry();

	stat_dir = debugfs_create_dir("trace_stat", d_tracing);
	if (!stat_dir)
		pr_warning("Could not create debugfs "
			   "'trace_stat' entry\n");
	return 0;
}

static int init_stat_file(struct tracer_stat_session *session)
{
	if (!stat_dir && tracing_stat_init())
		return -ENODEV;

	session->file = debugfs_create_file(session->ts->name, 0644,
					    stat_dir,
					    session, &tracing_stat_fops);
	if (!session->file)
		return -ENOMEM;
	return 0;
}

int register_stat_tracer(struct tracer_stat *trace)
{
	struct tracer_stat_session *session, *node, *tmp;
	int ret;

	if (!trace)
		return -EINVAL;

	if (!trace->stat_start || !trace->stat_next || !trace->stat_show)
		return -EINVAL;

	/* Already registered? */
	mutex_lock(&all_stat_sessions_mutex);
	list_for_each_entry_safe(node, tmp, &all_stat_sessions, session_list) {
		if (node->ts == trace) {
			mutex_unlock(&all_stat_sessions_mutex);
			return -EINVAL;
		}
	}
	mutex_unlock(&all_stat_sessions_mutex);

	/* Init the session */
	session = kmalloc(sizeof(struct tracer_stat_session), GFP_KERNEL);
	if (!session)
		return -ENOMEM;

	session->ts = trace;
	INIT_LIST_HEAD(&session->session_list);
	INIT_LIST_HEAD(&session->stat_list);
	mutex_init(&session->stat_mutex);
	session->file = NULL;

	ret = init_stat_file(session);
	if (ret) {
		destroy_session(session);
		return ret;
	}

	/* Register */
	mutex_lock(&all_stat_sessions_mutex);
	list_add_tail(&session->session_list, &all_stat_sessions);
	mutex_unlock(&all_stat_sessions_mutex);

	return 0;
}

void unregister_stat_tracer(struct tracer_stat *trace)
{
	struct tracer_stat_session *node, *tmp;

	mutex_lock(&all_stat_sessions_mutex);
	list_for_each_entry_safe(node, tmp, &all_stat_sessions, session_list) {
		if (node->ts == trace) {
			list_del(&node->session_list);
			destroy_session(node);
			break;
		}
	}
	mutex_unlock(&all_stat_sessions_mutex);
}
