diff options
author | Nicholas Bellinger <nab@daterainc.com> | 2013-08-17 18:49:08 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-09-09 17:29:22 -0400 |
commit | 988e3a85463d9b6dabc681df3f8f131b23c19953 (patch) | |
tree | 26ae4d803ff49f0938d20f910be19a172a64d8a4 | |
parent | d703ce2f7f4de20c03d71c22a9d5e3708798047b (diff) |
iscsi-target: Convert to per-cpu ida_alloc + ida_free command map
This patch changes iscsi-target to use transport_alloc_session_tags()
pre-allocation logic for per-cpu session tag pooling with internal
ida_alloc() + ida_free() calls based upon the saved se_cmd->map_tag id.
This includes tag pool setup based upon per NodeACL queue_depth after
locating se_node_acl in iscsi_target_locate_portal().
Also update iscsit_allocate_cmd() and iscsit_release_cmd() to use
percpu_ida_alloc() and percpu_ida_free() respectively.
v5 changes;
- Convert to percpu_ida.h include
v2 changes:
- Fix bug with SessionType=Discovery in iscsi_target_locate_portal()
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Kent Overstreet <kmo@daterainc.com>
Signed-off-by: Nicholas Bellinger <nab@daterainc.com>
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 2 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.c | 28 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 27 |
3 files changed, 46 insertions, 11 deletions
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 129b7d77c7cb..af3cd7a47799 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #define SECONDS_FOR_ASYNC_TEXT 10 | 17 | #define SECONDS_FOR_ASYNC_TEXT 10 |
18 | #define SECONDS_FOR_LOGOUT_COMP 15 | 18 | #define SECONDS_FOR_LOGOUT_COMP 15 |
19 | #define WHITE_SPACE " \t\v\f\n\r" | 19 | #define WHITE_SPACE " \t\v\f\n\r" |
20 | #define ISCSIT_MIN_TAGS 16 | ||
21 | #define ISCSIT_EXTRA_TAGS 8 | ||
20 | 22 | ||
21 | /* struct iscsi_node_attrib sanity values */ | 23 | /* struct iscsi_node_attrib sanity values */ |
22 | #define NA_DATAOUT_TIMEOUT 3 | 24 | #define NA_DATAOUT_TIMEOUT 3 |
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 2cce636d1113..24b0e33e7c50 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c | |||
@@ -983,8 +983,9 @@ int iscsi_target_locate_portal( | |||
983 | struct iscsi_tiqn *tiqn; | 983 | struct iscsi_tiqn *tiqn; |
984 | struct iscsi_tpg_np *tpg_np = NULL; | 984 | struct iscsi_tpg_np *tpg_np = NULL; |
985 | struct iscsi_login_req *login_req; | 985 | struct iscsi_login_req *login_req; |
986 | u32 payload_length; | 986 | struct se_node_acl *se_nacl; |
987 | int sessiontype = 0, ret = 0; | 987 | u32 payload_length, queue_depth = 0; |
988 | int sessiontype = 0, ret = 0, tag_num, tag_size; | ||
988 | 989 | ||
989 | INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); | 990 | INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); |
990 | INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup); | 991 | INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup); |
@@ -1084,7 +1085,7 @@ int iscsi_target_locate_portal( | |||
1084 | goto out; | 1085 | goto out; |
1085 | } | 1086 | } |
1086 | ret = 0; | 1087 | ret = 0; |
1087 | goto out; | 1088 | goto alloc_tags; |
1088 | } | 1089 | } |
1089 | 1090 | ||
1090 | get_target: | 1091 | get_target: |
@@ -1181,8 +1182,27 @@ get_target: | |||
1181 | ret = -1; | 1182 | ret = -1; |
1182 | goto out; | 1183 | goto out; |
1183 | } | 1184 | } |
1185 | se_nacl = sess->se_sess->se_node_acl; | ||
1186 | queue_depth = se_nacl->queue_depth; | ||
1187 | /* | ||
1188 | * Setup pre-allocated tags based upon allowed per NodeACL CmdSN | ||
1189 | * depth for non immediate commands, plus extra tags for immediate | ||
1190 | * commands. | ||
1191 | * | ||
1192 | * Also enforce a ISCSIT_MIN_TAGS to prevent unnecessary contention | ||
1193 | * in per-cpu-ida tag allocation logic + small queue_depth. | ||
1194 | */ | ||
1195 | alloc_tags: | ||
1196 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); | ||
1197 | tag_num += ISCSIT_EXTRA_TAGS; | ||
1198 | tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; | ||
1184 | 1199 | ||
1185 | ret = 0; | 1200 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); |
1201 | if (ret < 0) { | ||
1202 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
1203 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
1204 | ret = -1; | ||
1205 | } | ||
1186 | out: | 1206 | out: |
1187 | kfree(tmpbuf); | 1207 | kfree(tmpbuf); |
1188 | return ret; | 1208 | return ret; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 5784cad16be1..8d85d8cceb42 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -19,6 +19,7 @@ | |||
19 | ******************************************************************************/ | 19 | ******************************************************************************/ |
20 | 20 | ||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/percpu_ida.h> | ||
22 | #include <scsi/scsi_tcq.h> | 23 | #include <scsi/scsi_tcq.h> |
23 | #include <scsi/iscsi_proto.h> | 24 | #include <scsi/iscsi_proto.h> |
24 | #include <target/target_core_base.h> | 25 | #include <target/target_core_base.h> |
@@ -156,13 +157,15 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd) | |||
156 | struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) | 157 | struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) |
157 | { | 158 | { |
158 | struct iscsi_cmd *cmd; | 159 | struct iscsi_cmd *cmd; |
159 | int priv_size = conn->conn_transport->priv_size; | 160 | struct se_session *se_sess = conn->sess->se_sess; |
161 | int size, tag; | ||
160 | 162 | ||
161 | cmd = kzalloc(sizeof(struct iscsi_cmd) + priv_size, gfp_mask); | 163 | tag = percpu_ida_alloc(&se_sess->sess_tag_pool, gfp_mask); |
162 | if (!cmd) { | 164 | size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
163 | pr_err("Unable to allocate memory for struct iscsi_cmd.\n"); | 165 | cmd = (struct iscsi_cmd *)(se_sess->sess_cmd_map + (tag * size)); |
164 | return NULL; | 166 | memset(cmd, 0, size); |
165 | } | 167 | |
168 | cmd->se_cmd.map_tag = tag; | ||
166 | cmd->conn = conn; | 169 | cmd->conn = conn; |
167 | INIT_LIST_HEAD(&cmd->i_conn_node); | 170 | INIT_LIST_HEAD(&cmd->i_conn_node); |
168 | INIT_LIST_HEAD(&cmd->datain_list); | 171 | INIT_LIST_HEAD(&cmd->datain_list); |
@@ -678,6 +681,16 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) | |||
678 | 681 | ||
679 | void iscsit_release_cmd(struct iscsi_cmd *cmd) | 682 | void iscsit_release_cmd(struct iscsi_cmd *cmd) |
680 | { | 683 | { |
684 | struct iscsi_session *sess; | ||
685 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
686 | |||
687 | if (cmd->conn) | ||
688 | sess = cmd->conn->sess; | ||
689 | else | ||
690 | sess = cmd->sess; | ||
691 | |||
692 | BUG_ON(!sess || !sess->se_sess); | ||
693 | |||
681 | kfree(cmd->buf_ptr); | 694 | kfree(cmd->buf_ptr); |
682 | kfree(cmd->pdu_list); | 695 | kfree(cmd->pdu_list); |
683 | kfree(cmd->seq_list); | 696 | kfree(cmd->seq_list); |
@@ -685,7 +698,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) | |||
685 | kfree(cmd->iov_data); | 698 | kfree(cmd->iov_data); |
686 | kfree(cmd->text_in_ptr); | 699 | kfree(cmd->text_in_ptr); |
687 | 700 | ||
688 | kfree(cmd); | 701 | percpu_ida_free(&sess->se_sess->sess_tag_pool, se_cmd->map_tag); |
689 | } | 702 | } |
690 | EXPORT_SYMBOL(iscsit_release_cmd); | 703 | EXPORT_SYMBOL(iscsit_release_cmd); |
691 | 704 | ||