Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10e9cbb6 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Martin K. Petersen
Browse files

scsi: target: Convert target drivers to use sbitmap

The sbitmap and the percpu_ida perform essentially the same task,
allocating tags for commands.  The sbitmap outperforms the percpu_ida as
documented here: https://lkml.org/lkml/2014/4/22/553



The sbitmap interface is a little harder to use, but being able to remove
the percpu_ida code and getting better performance justifies the additional
complexity.

Signed-off-by: default avatarMatthew Wilcox <willy@infradead.org>
Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>	# f_tcm
Reviewed-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 83c2b54b
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -4277,9 +4277,9 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
{
	struct se_session *se_sess = sess->se_sess;
	struct qla_tgt_cmd *cmd;
	int tag;
	int tag, cpu;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
	if (tag < 0)
		return NULL;

@@ -4292,6 +4292,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
	qlt_incr_num_pend_cmds(vha);
	cmd->vha = vha;
	cmd->se_cmd.map_tag = tag;
	cmd->se_cmd.map_cpu = cpu;
	cmd->sess = sess;
	cmd->loop_id = sess->loop_id;
	cmd->conf_compl_supported = sess->conf_compl_supported;
@@ -5294,7 +5295,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
	struct fc_port *sess;
	struct se_session *se_sess;
	struct qla_tgt_cmd *cmd;
	int tag;
	int tag, cpu;
	unsigned long flags;

	if (unlikely(tgt->tgt_stop)) {
@@ -5326,7 +5327,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,

	se_sess = sess->se_sess;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
	if (tag < 0)
		return;

@@ -5357,6 +5358,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
	cmd->reset_count = ha->base_qpair->chip_reset;
	cmd->q_full = 1;
	cmd->qpair = ha->base_qpair;
	cmd->se_cmd.map_cpu = cpu;

	if (qfull) {
		cmd->q_full = 1;
+30 −3
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
 ******************************************************************************/

#include <linux/list.h>
#include <linux/percpu_ida.h>
#include <linux/sched/signal.h>
#include <net/ipv6.h>         /* ipv6_addr_equal() */
#include <scsi/scsi_tcq.h>
#include <scsi/iscsi_proto.h>
@@ -147,6 +147,30 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
	spin_unlock_bh(&cmd->r2t_lock);
}

static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup)
{
	int tag = -1;
	DEFINE_WAIT(wait);
	struct sbq_wait_state *ws;

	if (state == TASK_RUNNING)
		return tag;

	ws = &se_sess->sess_tag_pool.ws[0];
	for (;;) {
		prepare_to_wait_exclusive(&ws->wait, &wait, state);
		if (signal_pending_state(state, current))
			break;
		tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup);
		if (tag >= 0)
			break;
		schedule();
	}

	finish_wait(&ws->wait, &wait);
	return tag;
}

/*
 * May be called from software interrupt (timer) context for allocating
 * iSCSI NopINs.
@@ -155,9 +179,11 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
{
	struct iscsi_cmd *cmd;
	struct se_session *se_sess = conn->sess->se_sess;
	int size, tag;
	int size, tag, cpu;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state);
	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
	if (tag < 0)
		tag = iscsit_wait_for_tag(se_sess, state, &cpu);
	if (tag < 0)
		return NULL;

@@ -166,6 +192,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
	memset(cmd, 0, size);

	cmd->se_cmd.map_tag = tag;
	cmd->se_cmd.map_cpu = cpu;
	cmd->conn = conn;
	cmd->data_direction = DMA_NONE;
	INIT_LIST_HEAD(&cmd->i_conn_node);
+3 −2
Original line number Diff line number Diff line
@@ -926,15 +926,16 @@ static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess,
{
	struct se_session *se_sess = sess->se_sess;
	struct sbp_target_request *req;
	int tag;
	int tag, cpu;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
	if (tag < 0)
		return ERR_PTR(-ENOMEM);

	req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag];
	memset(req, 0, sizeof(*req));
	req->se_cmd.map_tag = tag;
	req->se_cmd.map_cpu = cpu;
	req->se_cmd.tag = next_orb;

	return req;
+3 −2
Original line number Diff line number Diff line
@@ -260,7 +260,8 @@ int transport_alloc_session_tags(struct se_session *se_sess,
		}
	}

	rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num);
	rc = sbitmap_queue_init_node(&se_sess->sess_tag_pool, tag_num, -1,
			false, GFP_KERNEL, NUMA_NO_NODE);
	if (rc < 0) {
		pr_err("Unable to init se_sess->sess_tag_pool,"
			" tag_num: %u\n", tag_num);
@@ -547,7 +548,7 @@ void transport_free_session(struct se_session *se_sess)
		target_put_nacl(se_nacl);
	}
	if (se_sess->sess_cmd_map) {
		percpu_ida_destroy(&se_sess->sess_tag_pool);
		sbitmap_queue_free(&se_sess->sess_tag_pool);
		kvfree(se_sess->sess_cmd_map);
	}
	kmem_cache_free(se_sess_cache, se_sess);
+3 −3
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
#include <linux/configfs.h>
#include <linux/ctype.h>
#include <linux/hash.h>
#include <linux/percpu_ida.h>
#include <asm/unaligned.h>
#include <scsi/scsi_tcq.h>
#include <scsi/libfc.h>
@@ -448,9 +447,9 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
	struct ft_cmd *cmd;
	struct fc_lport *lport = sess->tport->lport;
	struct se_session *se_sess = sess->se_sess;
	int tag;
	int tag, cpu;

	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
	tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
	if (tag < 0)
		goto busy;

@@ -458,6 +457,7 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
	memset(cmd, 0, sizeof(struct ft_cmd));

	cmd->se_cmd.map_tag = tag;
	cmd->se_cmd.map_cpu = cpu;
	cmd->sess = sess;
	cmd->seq = fc_seq_assign(lport, fp);
	if (!cmd->seq) {
Loading