Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] libiscsi: make can_queue configurable

This patch allows us to set can_queue and cmds_per_lun from userspace
when we create the session/host. From there we can set it on a per
target basis. The patch fully converts iscsi_tcp, but only hooks
up ib_iser for cmd_per_lun since it currently has a lots of preallocations
based on can_queue.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Cc: Roland Dreier <rdreier@cisco.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

authored by

Mike Christie and committed by
James Bottomley
1548271e 77a23c21

+52 -14
+9 -2
drivers/infiniband/ulp/iser/iscsi_iser.c
··· 373 373 static struct iscsi_cls_session * 374 374 iscsi_iser_session_create(struct iscsi_transport *iscsit, 375 375 struct scsi_transport_template *scsit, 376 - uint32_t initial_cmdsn, uint32_t *hostno) 376 + uint16_t cmds_max, uint16_t qdepth, 377 + uint32_t initial_cmdsn, uint32_t *hostno) 377 378 { 378 379 struct iscsi_cls_session *cls_session; 379 380 struct iscsi_session *session; ··· 385 384 struct iscsi_iser_cmd_task *iser_ctask; 386 385 struct iser_desc *desc; 387 386 387 + /* 388 + * we do not support setting can_queue cmd_per_lun from userspace yet 389 + * because we preallocate so many resources 390 + */ 388 391 cls_session = iscsi_session_setup(iscsit, scsit, 392 + ISCSI_DEF_XMIT_CMDS_MAX, 393 + ISCSI_MAX_CMD_PER_LUN, 389 394 sizeof(struct iscsi_iser_cmd_task), 390 395 sizeof(struct iser_desc), 391 396 initial_cmdsn, &hn); ··· 550 543 static struct scsi_host_template iscsi_iser_sht = { 551 544 .name = "iSCSI Initiator over iSER, v." DRV_VER, 552 545 .queuecommand = iscsi_queuecommand, 553 - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, 546 + .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, 554 547 .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, 555 548 .max_sectors = 1024, 556 549 .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN,
+2 -2
drivers/infiniband/ulp/iser/iscsi_iser.h
··· 98 98 #define ISER_MAX_TX_MISC_PDUS 6 /* NOOP_OUT(2), TEXT(1), * 99 99 * SCSI_TMFUNC(2), LOGOUT(1) */ 100 100 101 - #define ISER_QP_MAX_RECV_DTOS (ISCSI_XMIT_CMDS_MAX + \ 101 + #define ISER_QP_MAX_RECV_DTOS (ISCSI_DEF_XMIT_CMDS_MAX + \ 102 102 ISER_MAX_RX_MISC_PDUS + \ 103 103 ISER_MAX_TX_MISC_PDUS) 104 104 ··· 110 110 111 111 #define ISER_INFLIGHT_DATAOUTS 8 112 112 113 - #define ISER_QP_MAX_REQ_DTOS (ISCSI_XMIT_CMDS_MAX * \ 113 + #define ISER_QP_MAX_REQ_DTOS (ISCSI_DEF_XMIT_CMDS_MAX * \ 114 114 (1 + ISER_INFLIGHT_DATAOUTS) + \ 115 115 ISER_MAX_TX_MISC_PDUS + \ 116 116 ISER_MAX_RX_MISC_PDUS)
+2 -2
drivers/infiniband/ulp/iser/iser_verbs.c
··· 155 155 params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1; 156 156 /* make the pool size twice the max number of SCSI commands * 157 157 * the ML is expected to queue, watermark for unmap at 50% */ 158 - params.pool_size = ISCSI_XMIT_CMDS_MAX * 2; 159 - params.dirty_watermark = ISCSI_XMIT_CMDS_MAX; 158 + params.pool_size = ISCSI_DEF_XMIT_CMDS_MAX * 2; 159 + params.dirty_watermark = ISCSI_DEF_XMIT_CMDS_MAX; 160 160 params.cache = 0; 161 161 params.flush_function = NULL; 162 162 params.access = (IB_ACCESS_LOCAL_WRITE |
+3 -2
drivers/scsi/iscsi_tcp.c
··· 2114 2114 static struct iscsi_cls_session * 2115 2115 iscsi_tcp_session_create(struct iscsi_transport *iscsit, 2116 2116 struct scsi_transport_template *scsit, 2117 + uint16_t cmds_max, uint16_t qdepth, 2117 2118 uint32_t initial_cmdsn, uint32_t *hostno) 2118 2119 { 2119 2120 struct iscsi_cls_session *cls_session; ··· 2122 2121 uint32_t hn; 2123 2122 int cmd_i; 2124 2123 2125 - cls_session = iscsi_session_setup(iscsit, scsit, 2124 + cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, 2126 2125 sizeof(struct iscsi_tcp_cmd_task), 2127 2126 sizeof(struct iscsi_tcp_mgmt_task), 2128 2127 initial_cmdsn, &hn); ··· 2165 2164 .name = "iSCSI Initiator over TCP/IP", 2166 2165 .queuecommand = iscsi_queuecommand, 2167 2166 .change_queue_depth = iscsi_change_queue_depth, 2168 - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, 2167 + .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, 2169 2168 .sg_tablesize = ISCSI_SG_TABLESIZE, 2170 2169 .max_sectors = 0xFFFF, 2171 2170 .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+27 -1
drivers/scsi/libiscsi.c
··· 1330 1330 * iscsi_session_setup - create iscsi cls session and host and session 1331 1331 * @scsit: scsi transport template 1332 1332 * @iscsit: iscsi transport template 1333 + * @cmds_max: scsi host can queue 1334 + * @qdepth: scsi host cmds per lun 1335 + * @cmd_task_size: LLD ctask private data size 1336 + * @mgmt_task_size: LLD mtask private data size 1333 1337 * @initial_cmdsn: initial CmdSN 1334 1338 * @hostno: host no allocated 1335 1339 * ··· 1343 1339 struct iscsi_cls_session * 1344 1340 iscsi_session_setup(struct iscsi_transport *iscsit, 1345 1341 struct scsi_transport_template *scsit, 1342 + uint16_t cmds_max, uint16_t qdepth, 1346 1343 int cmd_task_size, int mgmt_task_size, 1347 1344 uint32_t initial_cmdsn, uint32_t *hostno) 1348 1345 { ··· 1352 1347 struct iscsi_cls_session *cls_session; 1353 1348 int cmd_i; 1354 1349 1350 + if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { 1351 + if (qdepth != 0) 1352 + printk(KERN_ERR "iscsi: invalid queue depth of %d. " 1353 + "Queue depth must be between 1 and %d.\n", 1354 + qdepth, ISCSI_MAX_CMD_PER_LUN); 1355 + qdepth = ISCSI_DEF_CMD_PER_LUN; 1356 + } 1357 + 1358 + if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) || 1359 + cmds_max >= ISCSI_MGMT_ITT_OFFSET) { 1360 + if (cmds_max != 0) 1361 + printk(KERN_ERR "iscsi: invalid can_queue of %d. " 1362 + "can_queue must be a power of 2 and between " 1363 + "2 and %d - setting to %d.\n", cmds_max, 1364 + ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX); 1365 + cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; 1366 + } 1367 + 1355 1368 shost = scsi_host_alloc(iscsit->host_template, 1356 1369 hostdata_privsize(sizeof(*session))); 1357 1370 if (!shost) 1358 1371 return NULL; 1359 1372 1373 + /* the iscsi layer takes one task for reserve */ 1374 + shost->can_queue = cmds_max - 1; 1375 + shost->cmd_per_lun = qdepth; 1360 1376 shost->max_id = 1; 1361 1377 shost->max_channel = 0; 1362 1378 shost->max_lun = iscsit->max_lun; ··· 1391 1365 session->host = shost; 1392 1366 session->state = ISCSI_STATE_FREE; 1393 1367 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 1394 - session->cmds_max = ISCSI_XMIT_CMDS_MAX; 1368 + session->cmds_max = cmds_max; 1395 1369 session->cmdsn = initial_cmdsn; 1396 1370 session->exp_cmdsn = initial_cmdsn + 1; 1397 1371 session->max_cmdsn = initial_cmdsn + 1;
+2
drivers/scsi/scsi_transport_iscsi.c
··· 814 814 uint32_t hostno; 815 815 816 816 session = transport->create_session(transport, &priv->t, 817 + ev->u.c_session.cmds_max, 818 + ev->u.c_session.queue_depth, 817 819 ev->u.c_session.initial_cmdsn, 818 820 &hostno); 819 821 if (!session)
+2
include/scsi/iscsi_if.h
··· 72 72 /* messages u -> k */ 73 73 struct msg_create_session { 74 74 uint32_t initial_cmdsn; 75 + uint16_t cmds_max; 76 + uint16_t queue_depth; 75 77 } c_session; 76 78 struct msg_destroy_session { 77 79 uint32_t sid;
+3 -4
include/scsi/libiscsi.h
··· 48 48 #define debug_scsi(fmt...) 49 49 #endif 50 50 51 - #define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ 52 - #define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ 53 - #define ISCSI_CONN_MAX 1 51 + #define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ 52 + #define ISCSI_MGMT_CMDS_MAX 16 /* must be power of 2 */ 54 53 55 54 #define ISCSI_MGMT_ITT_OFFSET 0xa00 56 55 ··· 267 268 */ 268 269 extern struct iscsi_cls_session * 269 270 iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, 270 - int, int, uint32_t, uint32_t *); 271 + uint16_t, uint16_t, int, int, uint32_t, uint32_t *); 271 272 extern void iscsi_session_teardown(struct iscsi_cls_session *); 272 273 extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); 273 274 extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+2 -1
include/scsi/scsi_transport_iscsi.h
··· 90 90 unsigned int max_conn; 91 91 unsigned int max_cmd_len; 92 92 struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, 93 - struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); 93 + struct scsi_transport_template *t, uint16_t, uint16_t, 94 + uint32_t sn, uint32_t *hn); 94 95 void (*destroy_session) (struct iscsi_cls_session *session); 95 96 struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, 96 97 uint32_t cid);