Commit bb8222b6 authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "target: RW/num_cmds stats improvements"

Mike Christie <michael.christie@oracle.com> says:

The following patches were made over Linus tree. They fix/improve the
stats used in the main IO path. The first patch fixes an issue where
I made some stats u32 when they should have stayed u64. The rest of
the patches improve the handling of RW/num_cmds stats to reduce code
duplication and improve performance.

Link: https://patch.msgid.link/20250917221338.14813-1-michael.christie@oracle.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 867e4b1b bbb49005
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -814,6 +814,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
	dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
	dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT;

	/* Skip allocating lun_stats since we can't export them. */
	xcopy_lun = &dev->xcopy_lun;
	rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
	init_completion(&xcopy_lun->lun_shutdown_comp);
+1 −1
Original line number Diff line number Diff line
@@ -697,7 +697,7 @@ static void target_fabric_port_release(struct config_item *item)
	struct se_lun *lun = container_of(to_config_group(item),
					  struct se_lun, lun_group);

	kfree_rcu(lun, rcu_head);
	call_rcu(&lun->rcu_head, target_tpg_free_lun);
}

static struct configfs_item_operations target_fabric_port_item_ops = {
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *,
				  struct se_lun *);
void	core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u64);
void	target_tpg_free_lun(struct rcu_head *head);
int	core_tpg_add_lun(struct se_portal_group *, struct se_lun *,
		bool, struct se_device *);
void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *);
+85 −183
Original line number Diff line number Diff line
@@ -276,56 +276,39 @@ static ssize_t target_stat_lu_state_bit_show(struct config_item *item,
	return snprintf(page, PAGE_SIZE, "exposed\n");
}

static ssize_t target_stat_lu_num_cmds_show(struct config_item *item,
		char *page)
{
	struct se_device *dev = to_stat_lu_dev(item);
	struct se_dev_io_stats *stats;
	unsigned int cpu;
	u32 cmds = 0;

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(dev->stats, cpu);
		cmds += stats->total_cmds;
	}
#define per_cpu_stat_snprintf(stats_struct, prefix, field, shift)	\
static ssize_t								\
per_cpu_stat_##prefix##_snprintf(struct stats_struct __percpu *per_cpu_stats, \
				 char *page)				\
{									\
	struct stats_struct *stats;					\
	unsigned int cpu;						\
	u64 sum = 0;							\
									\
	for_each_possible_cpu(cpu) {					\
		stats = per_cpu_ptr(per_cpu_stats, cpu);		\
		sum += stats->field;					\
	}								\
									\
	return snprintf(page, PAGE_SIZE, "%llu\n", sum >> shift);	\
}

#define lu_show_per_cpu_stat(prefix, field, shift)			\
per_cpu_stat_snprintf(se_dev_io_stats, prefix, field, shift);		\
static ssize_t								\
target_stat_##prefix##_show(struct config_item *item, char *page)	\
{									\
	struct se_device *dev = to_stat_lu_dev(item);			\
									\
	return per_cpu_stat_##prefix##_snprintf(dev->stats, page);	\
}									\

/* scsiLuNumCommands */
	return snprintf(page, PAGE_SIZE, "%u\n", cmds);
}

static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_device *dev = to_stat_lu_dev(item);
	struct se_dev_io_stats *stats;
	unsigned int cpu;
	u32 bytes = 0;

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(dev->stats, cpu);
		bytes += stats->read_bytes;
	}

lu_show_per_cpu_stat(lu_num_cmds, total_cmds, 0);
/* scsiLuReadMegaBytes */
	return snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
}

static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_device *dev = to_stat_lu_dev(item);
	struct se_dev_io_stats *stats;
	unsigned int cpu;
	u32 bytes = 0;

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(dev->stats, cpu);
		bytes += stats->write_bytes;
	}

lu_show_per_cpu_stat(lu_read_mbytes, read_bytes, 20);
/* scsiLuWrittenMegaBytes */
	return snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
}
lu_show_per_cpu_stat(lu_write_mbytes, write_bytes, 20);

static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page)
{
@@ -623,53 +606,30 @@ static ssize_t target_stat_tgt_port_port_index_show(struct config_item *item,
	return ret;
}

static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item,
		char *page)
{
	struct se_lun *lun = to_stat_tgt_port(item);
	struct se_device *dev;
	ssize_t ret = -ENODEV;

	rcu_read_lock();
	dev = rcu_dereference(lun->lun_se_dev);
	if (dev)
		ret = snprintf(page, PAGE_SIZE, "%lu\n",
			       atomic_long_read(&lun->lun_stats.cmd_pdus));
	rcu_read_unlock();
	return ret;
}

static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_lun *lun = to_stat_tgt_port(item);
	struct se_device *dev;
	ssize_t ret = -ENODEV;

	rcu_read_lock();
	dev = rcu_dereference(lun->lun_se_dev);
	if (dev)
		ret = snprintf(page, PAGE_SIZE, "%u\n",
			(u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20));
	rcu_read_unlock();
	return ret;
}

static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_lun *lun = to_stat_tgt_port(item);
	struct se_device *dev;
	ssize_t ret = -ENODEV;

	rcu_read_lock();
	dev = rcu_dereference(lun->lun_se_dev);
	if (dev)
		ret = snprintf(page, PAGE_SIZE, "%u\n",
				(u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20));
	rcu_read_unlock();
	return ret;
}
#define tgt_port_show_per_cpu_stat(prefix, field, shift)		\
per_cpu_stat_snprintf(scsi_port_stats, prefix, field, shift);		\
static ssize_t								\
target_stat_##prefix##_show(struct config_item *item, char *page)	\
{									\
	struct se_lun *lun = to_stat_tgt_port(item);			\
	struct se_device *dev;						\
	int ret;							\
									\
	rcu_read_lock();						\
	dev = rcu_dereference(lun->lun_se_dev);				\
	if (!dev) {							\
		rcu_read_unlock();					\
		return -ENODEV;						\
	}								\
									\
	ret = per_cpu_stat_##prefix##_snprintf(lun->lun_stats, page);	\
	rcu_read_unlock();						\
	return ret;							\
}

tgt_port_show_per_cpu_stat(tgt_port_in_cmds, cmd_pdus, 0);
tgt_port_show_per_cpu_stat(tgt_port_write_mbytes, rx_data_octets, 20);
tgt_port_show_per_cpu_stat(tgt_port_read_mbytes, tx_data_octets, 20);

static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item,
		char *page)
@@ -1035,92 +995,34 @@ static ssize_t target_stat_auth_att_count_show(struct config_item *item,
	return ret;
}

static ssize_t target_stat_auth_num_cmds_show(struct config_item *item,
		char *page)
{
	struct se_lun_acl *lacl = auth_to_lacl(item);
	struct se_node_acl *nacl = lacl->se_lun_nacl;
	struct se_dev_entry_io_stats *stats;
	struct se_dev_entry *deve;
	unsigned int cpu;
	ssize_t ret;
	u32 cmds = 0;

	rcu_read_lock();
	deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
	if (!deve) {
		rcu_read_unlock();
		return -ENODEV;
	}

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(deve->stats, cpu);
		cmds += stats->total_cmds;
#define auth_show_per_cpu_stat(prefix, field, shift)			\
per_cpu_stat_snprintf(se_dev_entry_io_stats, prefix, field, shift);	\
static ssize_t								\
target_stat_##prefix##_show(struct config_item *item, char *page)	\
{									\
	struct se_lun_acl *lacl = auth_to_lacl(item);			\
	struct se_node_acl *nacl = lacl->se_lun_nacl;			\
	struct se_dev_entry *deve;					\
	int ret;							\
									\
	rcu_read_lock();						\
	deve = target_nacl_find_deve(nacl, lacl->mapped_lun);		\
	if (!deve) {							\
		rcu_read_unlock();					\
		return -ENODEV;						\
	}								\
									\
	ret = per_cpu_stat_##prefix##_snprintf(deve->stats, page);	\
	rcu_read_unlock();						\
	return ret;							\
}

/* scsiAuthIntrOutCommands */
	ret = snprintf(page, PAGE_SIZE, "%u\n", cmds);
	rcu_read_unlock();
	return ret;
}

static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_lun_acl *lacl = auth_to_lacl(item);
	struct se_node_acl *nacl = lacl->se_lun_nacl;
	struct se_dev_entry_io_stats *stats;
	struct se_dev_entry *deve;
	unsigned int cpu;
	ssize_t ret;
	u32 bytes = 0;

	rcu_read_lock();
	deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
	if (!deve) {
		rcu_read_unlock();
		return -ENODEV;
	}

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(deve->stats, cpu);
		bytes += stats->read_bytes;
	}

auth_show_per_cpu_stat(auth_num_cmds, total_cmds, 0);
/* scsiAuthIntrReadMegaBytes */
	ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
	rcu_read_unlock();
	return ret;
}

static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item,
		char *page)
{
	struct se_lun_acl *lacl = auth_to_lacl(item);
	struct se_node_acl *nacl = lacl->se_lun_nacl;
	struct se_dev_entry_io_stats *stats;
	struct se_dev_entry *deve;
	unsigned int cpu;
	ssize_t ret;
	u32 bytes = 0;

	rcu_read_lock();
	deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
	if (!deve) {
		rcu_read_unlock();
		return -ENODEV;
	}

	for_each_possible_cpu(cpu) {
		stats = per_cpu_ptr(deve->stats, cpu);
		bytes += stats->write_bytes;
	}

auth_show_per_cpu_stat(auth_read_mbytes, read_bytes, 20);
/* scsiAuthIntrWrittenMegaBytes */
	ret = snprintf(page, PAGE_SIZE, "%u\n", bytes >> 20);
	rcu_read_unlock();
	return ret;
}
auth_show_per_cpu_stat(auth_write_mbytes, write_bytes, 20);

static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item,
		char *page)
+21 −2
Original line number Diff line number Diff line
@@ -548,7 +548,7 @@ int core_tpg_register(
		ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0,
				true, g_lun0_dev);
		if (ret < 0) {
			kfree(se_tpg->tpg_virt_lun0);
			target_tpg_free_lun(&se_tpg->tpg_virt_lun0->rcu_head);
			return ret;
		}
	}
@@ -595,7 +595,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)

	if (se_tpg->proto_id >= 0) {
		core_tpg_remove_lun(se_tpg, se_tpg->tpg_virt_lun0);
		kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head);
		call_rcu(&se_tpg->tpg_virt_lun0->rcu_head, target_tpg_free_lun);
	}

	target_tpg_deregister_rtpi(se_tpg);
@@ -615,6 +615,13 @@ struct se_lun *core_tpg_alloc_lun(
		pr_err("Unable to allocate se_lun memory\n");
		return ERR_PTR(-ENOMEM);
	}

	lun->lun_stats = alloc_percpu(struct scsi_port_stats);
	if (!lun->lun_stats) {
		pr_err("Unable to allocate se_lun stats memory\n");
		goto free_lun;
	}

	lun->unpacked_lun = unpacked_lun;
	atomic_set(&lun->lun_acl_count, 0);
	init_completion(&lun->lun_shutdown_comp);
@@ -628,6 +635,18 @@ struct se_lun *core_tpg_alloc_lun(
	lun->lun_tpg = tpg;

	return lun;

free_lun:
	kfree(lun);
	return ERR_PTR(-ENOMEM);
}

void target_tpg_free_lun(struct rcu_head *head)
{
	struct se_lun *lun = container_of(head, struct se_lun, rcu_head);

	free_percpu(lun->lun_stats);
	kfree(lun);
}

int core_tpg_add_lun(
Loading