Skip to content

Commit 10e9cbb

Browse files
Matthew Wilcoxmartinkpetersen
authored andcommitted
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: Matthew Wilcox <[email protected]> Acked-by: Felipe Balbi <[email protected]> # f_tcm Reviewed-by: Jens Axboe <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 83c2b54 commit 10e9cbb

File tree

10 files changed

+59
-24
lines changed

10 files changed

+59
-24
lines changed

drivers/scsi/qla2xxx/qla_target.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,9 +4277,9 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
42774277
{
42784278
struct se_session *se_sess = sess->se_sess;
42794279
struct qla_tgt_cmd *cmd;
4280-
int tag;
4280+
int tag, cpu;
42814281

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

@@ -4292,6 +4292,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha,
42924292
qlt_incr_num_pend_cmds(vha);
42934293
cmd->vha = vha;
42944294
cmd->se_cmd.map_tag = tag;
4295+
cmd->se_cmd.map_cpu = cpu;
42954296
cmd->sess = sess;
42964297
cmd->loop_id = sess->loop_id;
42974298
cmd->conf_compl_supported = sess->conf_compl_supported;
@@ -5294,7 +5295,7 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
52945295
struct fc_port *sess;
52955296
struct se_session *se_sess;
52965297
struct qla_tgt_cmd *cmd;
5297-
int tag;
5298+
int tag, cpu;
52985299
unsigned long flags;
52995300

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

53275328
se_sess = sess->se_sess;
53285329

5329-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
5330+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
53305331
if (tag < 0)
53315332
return;
53325333

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

53615363
if (qfull) {
53625364
cmd->q_full = 1;

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
******************************************************************************/
1818

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

150+
static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup)
151+
{
152+
int tag = -1;
153+
DEFINE_WAIT(wait);
154+
struct sbq_wait_state *ws;
155+
156+
if (state == TASK_RUNNING)
157+
return tag;
158+
159+
ws = &se_sess->sess_tag_pool.ws[0];
160+
for (;;) {
161+
prepare_to_wait_exclusive(&ws->wait, &wait, state);
162+
if (signal_pending_state(state, current))
163+
break;
164+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup);
165+
if (tag >= 0)
166+
break;
167+
schedule();
168+
}
169+
170+
finish_wait(&ws->wait, &wait);
171+
return tag;
172+
}
173+
150174
/*
151175
* May be called from software interrupt (timer) context for allocating
152176
* iSCSI NopINs.
@@ -155,9 +179,11 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
155179
{
156180
struct iscsi_cmd *cmd;
157181
struct se_session *se_sess = conn->sess->se_sess;
158-
int size, tag;
182+
int size, tag, cpu;
159183

160-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state);
184+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
185+
if (tag < 0)
186+
tag = iscsit_wait_for_tag(se_sess, state, &cpu);
161187
if (tag < 0)
162188
return NULL;
163189

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

168194
cmd->se_cmd.map_tag = tag;
195+
cmd->se_cmd.map_cpu = cpu;
169196
cmd->conn = conn;
170197
cmd->data_direction = DMA_NONE;
171198
INIT_LIST_HEAD(&cmd->i_conn_node);

drivers/target/sbp/sbp_target.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,15 +926,16 @@ static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess,
926926
{
927927
struct se_session *se_sess = sess->se_sess;
928928
struct sbp_target_request *req;
929-
int tag;
929+
int tag, cpu;
930930

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

935935
req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag];
936936
memset(req, 0, sizeof(*req));
937937
req->se_cmd.map_tag = tag;
938+
req->se_cmd.map_cpu = cpu;
938939
req->se_cmd.tag = next_orb;
939940

940941
return req;

drivers/target/target_core_transport.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ int transport_alloc_session_tags(struct se_session *se_sess,
260260
}
261261
}
262262

263-
rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num);
263+
rc = sbitmap_queue_init_node(&se_sess->sess_tag_pool, tag_num, -1,
264+
false, GFP_KERNEL, NUMA_NO_NODE);
264265
if (rc < 0) {
265266
pr_err("Unable to init se_sess->sess_tag_pool,"
266267
" tag_num: %u\n", tag_num);
@@ -547,7 +548,7 @@ void transport_free_session(struct se_session *se_sess)
547548
target_put_nacl(se_nacl);
548549
}
549550
if (se_sess->sess_cmd_map) {
550-
percpu_ida_destroy(&se_sess->sess_tag_pool);
551+
sbitmap_queue_free(&se_sess->sess_tag_pool);
551552
kvfree(se_sess->sess_cmd_map);
552553
}
553554
kmem_cache_free(se_sess_cache, se_sess);

drivers/target/tcm_fc/tfc_cmd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include <linux/configfs.h>
2929
#include <linux/ctype.h>
3030
#include <linux/hash.h>
31-
#include <linux/percpu_ida.h>
3231
#include <asm/unaligned.h>
3332
#include <scsi/scsi_tcq.h>
3433
#include <scsi/libfc.h>
@@ -448,16 +447,17 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
448447
struct ft_cmd *cmd;
449448
struct fc_lport *lport = sess->tport->lport;
450449
struct se_session *se_sess = sess->se_sess;
451-
int tag;
450+
int tag, cpu;
452451

453-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
452+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
454453
if (tag < 0)
455454
goto busy;
456455

457456
cmd = &((struct ft_cmd *)se_sess->sess_cmd_map)[tag];
458457
memset(cmd, 0, sizeof(struct ft_cmd));
459458

460459
cmd->se_cmd.map_tag = tag;
460+
cmd->se_cmd.map_cpu = cpu;
461461
cmd->sess = sess;
462462
cmd->seq = fc_seq_assign(lport, fp);
463463
if (!cmd->seq) {

drivers/usb/gadget/function/f_tcm.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,15 +1071,16 @@ static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
10711071
{
10721072
struct se_session *se_sess = tv_nexus->tvn_se_sess;
10731073
struct usbg_cmd *cmd;
1074-
int tag;
1074+
int tag, cpu;
10751075

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

10801080
cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag];
10811081
memset(cmd, 0, sizeof(*cmd));
10821082
cmd->se_cmd.map_tag = tag;
1083+
cmd->se_cmd.map_cpu = cpu;
10831084
cmd->se_cmd.tag = cmd->tag = scsi_tag;
10841085
cmd->fu = fu;
10851086

drivers/vhost/scsi.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
#include <linux/virtio_scsi.h>
4747
#include <linux/llist.h>
4848
#include <linux/bitmap.h>
49-
#include <linux/percpu_ida.h>
5049

5150
#include "vhost.h"
5251

@@ -567,7 +566,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
567566
struct se_session *se_sess;
568567
struct scatterlist *sg, *prot_sg;
569568
struct page **pages;
570-
int tag;
569+
int tag, cpu;
571570

572571
tv_nexus = tpg->tpg_nexus;
573572
if (!tv_nexus) {
@@ -576,7 +575,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
576575
}
577576
se_sess = tv_nexus->tvn_se_sess;
578577

579-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
578+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
580579
if (tag < 0) {
581580
pr_err("Unable to obtain tag for vhost_scsi_cmd\n");
582581
return ERR_PTR(-ENOMEM);
@@ -591,6 +590,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
591590
cmd->tvc_prot_sgl = prot_sg;
592591
cmd->tvc_upages = pages;
593592
cmd->tvc_se_cmd.map_tag = tag;
593+
cmd->tvc_se_cmd.map_cpu = cpu;
594594
cmd->tvc_tag = scsi_tag;
595595
cmd->tvc_lun = lun;
596596
cmd->tvc_task_attr = task_attr;

drivers/xen/xen-scsiback.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,9 +654,9 @@ static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring
654654
struct scsiback_nexus *nexus = tpg->tpg_nexus;
655655
struct se_session *se_sess = nexus->tvn_se_sess;
656656
struct vscsibk_pend *req;
657-
int tag, i;
657+
int tag, cpu, i;
658658

659-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
659+
tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
660660
if (tag < 0) {
661661
pr_err("Unable to obtain tag for vscsiif_request\n");
662662
return ERR_PTR(-ENOMEM);
@@ -665,6 +665,7 @@ static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring
665665
req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag];
666666
memset(req, 0, sizeof(*req));
667667
req->se_cmd.map_tag = tag;
668+
req->se_cmd.map_cpu = cpu;
668669

669670
for (i = 0; i < VSCSI_MAX_GRANTS; i++)
670671
req->grant_handles[i] = SCSIBACK_INVALID_HANDLE;

include/target/iscsi/iscsi_target_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/dma-direction.h> /* enum dma_data_direction */
66
#include <linux/list.h> /* struct list_head */
7+
#include <linux/sched.h>
78
#include <linux/socket.h> /* struct sockaddr_storage */
89
#include <linux/types.h> /* u8 */
910
#include <scsi/iscsi_proto.h> /* itt_t */

include/target/target_core_base.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include <linux/configfs.h> /* struct config_group */
66
#include <linux/dma-direction.h> /* enum dma_data_direction */
7-
#include <linux/percpu_ida.h> /* struct percpu_ida */
7+
#include <linux/sbitmap.h>
88
#include <linux/percpu-refcount.h>
99
#include <linux/semaphore.h> /* struct semaphore */
1010
#include <linux/completion.h>
@@ -455,6 +455,7 @@ struct se_cmd {
455455
int sam_task_attr;
456456
/* Used for se_sess->sess_tag_pool */
457457
unsigned int map_tag;
458+
int map_cpu;
458459
/* Transport protocol dependent state, see transport_state_table */
459460
enum transport_state_table t_state;
460461
/* See se_cmd_flags_table */
@@ -608,7 +609,7 @@ struct se_session {
608609
struct list_head sess_wait_list;
609610
spinlock_t sess_cmd_lock;
610611
void *sess_cmd_map;
611-
struct percpu_ida sess_tag_pool;
612+
struct sbitmap_queue sess_tag_pool;
612613
};
613614

614615
struct se_device;
@@ -936,7 +937,7 @@ static inline void atomic_dec_mb(atomic_t *v)
936937

937938
static inline void target_free_tag(struct se_session *sess, struct se_cmd *cmd)
938939
{
939-
percpu_ida_free(&sess->sess_tag_pool, cmd->map_tag);
940+
sbitmap_queue_clear(&sess->sess_tag_pool, cmd->map_tag, cmd->map_cpu);
940941
}
941942

942943
#endif /* TARGET_CORE_BASE_H */

0 commit comments

Comments
 (0)