Viewing: kfilnd_debugfs.c

// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright 2022 Hewlett Packard Enterprise Development LP
 */

/*
 * This file is part of Lustre, http://www.lustre.org/
 *
 * kfilnd device implementation.
 */

#include "kfilnd.h"
#include "kfilnd_dev.h"

#define TIME_MAX 0xFFFFFFFFFFFF
static s64 get_ave_duration(struct kfilnd_tn_duration_stat *stat)
{
	s64 duration;

	if (!atomic_read(&stat->accumulated_count))
		return 0;

	duration = atomic64_read(&stat->accumulated_duration) /
		atomic_read(&stat->accumulated_count);

	return min_t(s64, duration, TIME_MAX);
}

static s64 get_min_duration(struct kfilnd_tn_duration_stat *stat)
{
	s64 min;

	min = atomic64_read(&stat->min_duration);
	if (min == MIN_DURATION_RESET)
		return 0;
	return min;
}

static void seq_print_tn_state_stats(struct seq_file *s, struct kfilnd_dev *dev,
				     bool initiator)
{
	struct kfilnd_tn_state_data_size_duration_stats *state_stats;
	unsigned int data_size;

	if (initiator)
		state_stats = &dev->initiator_state_stats;
	else
		state_stats = &dev->target_state_stats;

	seq_printf(s, "%-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s %-20s\n",
		   "MSG_SIZE", "IDLE", "WAIT_TAG_COMP", "IMM_SEND",
		   "TAGGED_RECV_POSTED", "SEND_FAILED", "WAIT_COMP",
		   "WAIT_TOUT_COMP", "SEND_COMP", "WAIT_TOUT_TAG_COMP", "FAIL",
		   "IMM_RECV", "WAIT_TAG_RMA_COMP");

	for (data_size = 0; data_size < KFILND_DATA_SIZE_BUCKETS; data_size++) {
		seq_printf(s, "%-20lu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu %-20llu\n",
			   data_size == 0 ? 0 : BIT(data_size - 1),
			   get_ave_duration(&state_stats->state[TN_STATE_IDLE].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_TAG_COMP].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_IMM_SEND].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_TAGGED_RECV_POSTED].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_SEND_FAILED].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_COMP].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_TIMEOUT_COMP].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_SEND_COMP].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_TIMEOUT_TAG_COMP].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_FAIL].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_IMM_RECV].data_size[data_size]),
			   get_ave_duration(&state_stats->state[TN_STATE_WAIT_TAG_RMA_COMP].data_size[data_size]));
	}
}

static int kfilnd_initiator_state_stats_file_show(struct seq_file *s,
						  void *unused)
{
	seq_print_tn_state_stats(s, s->private, true);

	return 0;
}

static int kfilnd_initiator_state_stats_file_open(struct inode *inode,
						  struct file *file)
{
	return single_open(file, kfilnd_initiator_state_stats_file_show,
			   inode->i_private);
}

const struct file_operations kfilnd_initiator_state_stats_file_ops = {
	.owner = THIS_MODULE,
	.open = kfilnd_initiator_state_stats_file_open,
	.read = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};

static int kfilnd_target_state_stats_file_show(struct seq_file *s,
					       void *unused)
{
	seq_print_tn_state_stats(s, s->private, false);

	return 0;
}

static int kfilnd_target_state_stats_file_open(struct inode *inode,
					       struct file *file)
{
	return single_open(file, kfilnd_target_state_stats_file_show,
			   inode->i_private);
}

const struct file_operations kfilnd_target_state_stats_file_ops = {
	.owner = THIS_MODULE,
	.open = kfilnd_target_state_stats_file_open,
	.read = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};

static void seq_print_tn_stats(struct seq_file *s, struct kfilnd_dev *dev,
			       bool initiator)
{
	struct kfilnd_tn_data_size_duration_stats *stats;
	unsigned int data_size;

	if (initiator)
		stats = &dev->initiator_stats;
	else
		stats = &dev->target_stats;

	seq_printf(s, "%16s %16s %16s %16s %16s\n", "MSG_SIZE", "MIN", "MAX",
		   "AVE", "COUNT");

	for (data_size = 0; data_size < KFILND_DATA_SIZE_BUCKETS; data_size++) {
		seq_printf(s, "%16lu %16llu %16llu %16llu %16d\n",
			   data_size == 0 ? 0 : BIT(data_size - 1),
			   get_min_duration(&stats->data_size[data_size]),
			   atomic64_read(&stats->data_size[data_size].max_duration),
			   get_ave_duration(&stats->data_size[data_size]),
			   atomic_read(&stats->data_size[data_size].accumulated_count));
	}
}

static int kfilnd_initiator_stats_file_show(struct seq_file *s, void *unused)
{
	seq_print_tn_stats(s, s->private, true);

	return 0;
}

static int kfilnd_initiator_stats_file_open(struct inode *inode,
					    struct file *file)
{
	return single_open(file, kfilnd_initiator_stats_file_show,
			   inode->i_private);
}

const struct file_operations kfilnd_initiator_stats_file_ops = {
	.owner = THIS_MODULE,
	.open = kfilnd_initiator_stats_file_open,
	.read = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};

static int kfilnd_target_stats_file_show(struct seq_file *s, void *unused)
{
	seq_print_tn_stats(s, s->private, false);

	return 0;
}

static int kfilnd_target_stats_file_open(struct inode *inode, struct file *file)
{
	return single_open(file, kfilnd_target_stats_file_show,
			   inode->i_private);
}

const struct file_operations kfilnd_target_stats_file_ops = {
	.owner = THIS_MODULE,
	.open = kfilnd_target_stats_file_open,
	.read = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};

static ssize_t kfilnd_reset_stats_file_write(struct file *filp,
					     const char __user *buf,
					     size_t count, loff_t *loff)
{
	kfilnd_dev_reset_stats(filp->f_inode->i_private);

	return count;
}

const struct file_operations kfilnd_reset_stats_file_ops = {
	.owner = THIS_MODULE,
	.write = kfilnd_reset_stats_file_write,
};

static int kfilnd_mempool_stats_file_show(struct seq_file *s, void *unused)
{
	int tn_min, tn_curr, msg_min, msg_curr;

	if (kfilnd_tn_get_mempool_stats(&tn_min, &tn_curr,
					&msg_min, &msg_curr) == 0) {
		seq_puts(s, "Transaction Mempool:\n");
		seq_printf(s, "  min_reserve: %d\n", tn_min);
		seq_printf(s, "  curr_avail: %d\n", tn_curr);
		seq_printf(s, "  elements_allocated: %d\n", tn_min - tn_curr);

		seq_puts(s, "\nMessage Buffer Mempool:\n");
		seq_printf(s, "  min_reserve: %d\n", msg_min);
		seq_printf(s, "  curr_avail: %d\n", msg_curr);
		seq_printf(s, "  elements_allocated: %d\n", msg_min - msg_curr);
	} else {
		seq_puts(s, "Transaction Mempool:\n");
		seq_puts(s, "  Not initialized\n");
		seq_puts(s, "\nMessage Buffer Mempool:\n");
		seq_puts(s, "  Not initialized\n");
	}

	return 0;
}

static int kfilnd_mempool_stats_file_open(struct inode *inode,
					  struct file *file)
{
	return single_open(file, kfilnd_mempool_stats_file_show,
			   inode->i_private);
}

const struct file_operations kfilnd_mempool_stats_file_ops = {
	.owner = THIS_MODULE,
	.open = kfilnd_mempool_stats_file_open,
	.read = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};