| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /******************************************************************************* |
|---|
| 2 | 3 | * This file contains the iSCSI Target specific utility functions. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> |
|---|
| 7 | 8 | * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | 9 | ******************************************************************************/ |
|---|
| 18 | 10 | |
|---|
| 19 | 11 | #include <linux/list.h> |
|---|
| .. | .. |
|---|
| 56 | 48 | extern struct list_head g_tiqn_list; |
|---|
| 57 | 49 | extern spinlock_t tiqn_lock; |
|---|
| 58 | 50 | |
|---|
| 59 | | -/* |
|---|
| 60 | | - * Called with cmd->r2t_lock held. |
|---|
| 61 | | - */ |
|---|
| 62 | 51 | int iscsit_add_r2t_to_list( |
|---|
| 63 | 52 | struct iscsi_cmd *cmd, |
|---|
| 64 | 53 | u32 offset, |
|---|
| .. | .. |
|---|
| 67 | 56 | u32 r2t_sn) |
|---|
| 68 | 57 | { |
|---|
| 69 | 58 | struct iscsi_r2t *r2t; |
|---|
| 59 | + |
|---|
| 60 | + lockdep_assert_held(&cmd->r2t_lock); |
|---|
| 61 | + |
|---|
| 62 | + WARN_ON_ONCE((s32)xfer_len < 0); |
|---|
| 70 | 63 | |
|---|
| 71 | 64 | r2t = kmem_cache_zalloc(lio_r2t_cache, GFP_ATOMIC); |
|---|
| 72 | 65 | if (!r2t) { |
|---|
| .. | .. |
|---|
| 128 | 121 | return NULL; |
|---|
| 129 | 122 | } |
|---|
| 130 | 123 | |
|---|
| 131 | | -/* |
|---|
| 132 | | - * Called with cmd->r2t_lock held. |
|---|
| 133 | | - */ |
|---|
| 134 | 124 | void iscsit_free_r2t(struct iscsi_r2t *r2t, struct iscsi_cmd *cmd) |
|---|
| 135 | 125 | { |
|---|
| 126 | + lockdep_assert_held(&cmd->r2t_lock); |
|---|
| 127 | + |
|---|
| 136 | 128 | list_del(&r2t->r2t_list); |
|---|
| 137 | 129 | kmem_cache_free(lio_r2t_cache, r2t); |
|---|
| 138 | 130 | } |
|---|
| .. | .. |
|---|
| 150 | 142 | static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup) |
|---|
| 151 | 143 | { |
|---|
| 152 | 144 | int tag = -1; |
|---|
| 153 | | - DEFINE_WAIT(wait); |
|---|
| 145 | + DEFINE_SBQ_WAIT(wait); |
|---|
| 154 | 146 | struct sbq_wait_state *ws; |
|---|
| 147 | + struct sbitmap_queue *sbq; |
|---|
| 155 | 148 | |
|---|
| 156 | 149 | if (state == TASK_RUNNING) |
|---|
| 157 | 150 | return tag; |
|---|
| 158 | 151 | |
|---|
| 159 | | - ws = &se_sess->sess_tag_pool.ws[0]; |
|---|
| 152 | + sbq = &se_sess->sess_tag_pool; |
|---|
| 153 | + ws = &sbq->ws[0]; |
|---|
| 160 | 154 | for (;;) { |
|---|
| 161 | | - prepare_to_wait_exclusive(&ws->wait, &wait, state); |
|---|
| 155 | + sbitmap_prepare_to_wait(sbq, ws, &wait, state); |
|---|
| 162 | 156 | if (signal_pending_state(state, current)) |
|---|
| 163 | 157 | break; |
|---|
| 164 | | - tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup); |
|---|
| 158 | + tag = sbitmap_queue_get(sbq, cpup); |
|---|
| 165 | 159 | if (tag >= 0) |
|---|
| 166 | 160 | break; |
|---|
| 167 | 161 | schedule(); |
|---|
| 168 | 162 | } |
|---|
| 169 | 163 | |
|---|
| 170 | | - finish_wait(&ws->wait, &wait); |
|---|
| 164 | + sbitmap_finish_wait(sbq, ws, &wait); |
|---|
| 171 | 165 | return tag; |
|---|
| 172 | 166 | } |
|---|
| 173 | 167 | |
|---|
| .. | .. |
|---|
| 735 | 729 | kfree(cmd->pdu_list); |
|---|
| 736 | 730 | kfree(cmd->seq_list); |
|---|
| 737 | 731 | kfree(cmd->tmr_req); |
|---|
| 732 | + kfree(cmd->overflow_buf); |
|---|
| 738 | 733 | kfree(cmd->iov_data); |
|---|
| 739 | 734 | kfree(cmd->text_in_ptr); |
|---|
| 740 | 735 | |
|---|
| .. | .. |
|---|
| 760 | 755 | iscsit_remove_cmd_from_response_queue(cmd, conn); |
|---|
| 761 | 756 | } |
|---|
| 762 | 757 | |
|---|
| 763 | | - if (conn && conn->conn_transport->iscsit_release_cmd) |
|---|
| 764 | | - conn->conn_transport->iscsit_release_cmd(conn, cmd); |
|---|
| 758 | + if (conn && conn->conn_transport->iscsit_unmap_cmd) |
|---|
| 759 | + conn->conn_transport->iscsit_unmap_cmd(conn, cmd); |
|---|
| 765 | 760 | } |
|---|
| 766 | 761 | |
|---|
| 767 | 762 | void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown) |
|---|
| 768 | 763 | { |
|---|
| 769 | 764 | struct se_cmd *se_cmd = cmd->se_cmd.se_tfo ? &cmd->se_cmd : NULL; |
|---|
| 770 | 765 | int rc; |
|---|
| 766 | + |
|---|
| 767 | + WARN_ON(!list_empty(&cmd->i_conn_node)); |
|---|
| 771 | 768 | |
|---|
| 772 | 769 | __iscsit_free_cmd(cmd, shutdown); |
|---|
| 773 | 770 | if (se_cmd) { |
|---|
| .. | .. |
|---|
| 915 | 912 | void iscsit_handle_nopin_response_timeout(struct timer_list *t) |
|---|
| 916 | 913 | { |
|---|
| 917 | 914 | struct iscsi_conn *conn = from_timer(conn, t, nopin_response_timer); |
|---|
| 915 | + struct iscsi_session *sess = conn->sess; |
|---|
| 918 | 916 | |
|---|
| 919 | 917 | iscsit_inc_conn_usage_count(conn); |
|---|
| 920 | 918 | |
|---|
| .. | .. |
|---|
| 925 | 923 | return; |
|---|
| 926 | 924 | } |
|---|
| 927 | 925 | |
|---|
| 928 | | - pr_debug("Did not receive response to NOPIN on CID: %hu on" |
|---|
| 929 | | - " SID: %u, failing connection.\n", conn->cid, |
|---|
| 930 | | - conn->sess->sid); |
|---|
| 926 | + pr_err("Did not receive response to NOPIN on CID: %hu, failing" |
|---|
| 927 | + " connection for I_T Nexus %s,i,0x%6phN,%s,t,0x%02x\n", |
|---|
| 928 | + conn->cid, sess->sess_ops->InitiatorName, sess->isid, |
|---|
| 929 | + sess->tpg->tpg_tiqn->tiqn, (u32)sess->tpg->tpgt); |
|---|
| 931 | 930 | conn->nopin_response_timer_flags &= ~ISCSI_TF_RUNNING; |
|---|
| 932 | 931 | spin_unlock_bh(&conn->nopin_timer_lock); |
|---|
| 933 | 932 | |
|---|
| 934 | | - { |
|---|
| 935 | | - struct iscsi_portal_group *tpg = conn->sess->tpg; |
|---|
| 936 | | - struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; |
|---|
| 937 | | - |
|---|
| 938 | | - if (tiqn) { |
|---|
| 939 | | - spin_lock_bh(&tiqn->sess_err_stats.lock); |
|---|
| 940 | | - strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name, |
|---|
| 941 | | - conn->sess->sess_ops->InitiatorName); |
|---|
| 942 | | - tiqn->sess_err_stats.last_sess_failure_type = |
|---|
| 943 | | - ISCSI_SESS_ERR_CXN_TIMEOUT; |
|---|
| 944 | | - tiqn->sess_err_stats.cxn_timeout_errors++; |
|---|
| 945 | | - atomic_long_inc(&conn->sess->conn_timeout_errors); |
|---|
| 946 | | - spin_unlock_bh(&tiqn->sess_err_stats.lock); |
|---|
| 947 | | - } |
|---|
| 948 | | - } |
|---|
| 949 | | - |
|---|
| 933 | + iscsit_fill_cxn_timeout_err_stats(sess); |
|---|
| 950 | 934 | iscsit_cause_connection_reinstatement(conn, 0); |
|---|
| 951 | 935 | iscsit_dec_conn_usage_count(conn); |
|---|
| 952 | 936 | } |
|---|
| .. | .. |
|---|
| 967 | 951 | spin_unlock_bh(&conn->nopin_timer_lock); |
|---|
| 968 | 952 | } |
|---|
| 969 | 953 | |
|---|
| 970 | | -/* |
|---|
| 971 | | - * Called with conn->nopin_timer_lock held. |
|---|
| 972 | | - */ |
|---|
| 973 | 954 | void iscsit_start_nopin_response_timer(struct iscsi_conn *conn) |
|---|
| 974 | 955 | { |
|---|
| 975 | 956 | struct iscsi_session *sess = conn->sess; |
|---|
| .. | .. |
|---|
| 1027 | 1008 | iscsit_dec_conn_usage_count(conn); |
|---|
| 1028 | 1009 | } |
|---|
| 1029 | 1010 | |
|---|
| 1030 | | -/* |
|---|
| 1031 | | - * Called with conn->nopin_timer_lock held. |
|---|
| 1032 | | - */ |
|---|
| 1033 | 1011 | void __iscsit_start_nopin_timer(struct iscsi_conn *conn) |
|---|
| 1034 | 1012 | { |
|---|
| 1035 | 1013 | struct iscsi_session *sess = conn->sess; |
|---|
| 1036 | 1014 | struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess); |
|---|
| 1015 | + |
|---|
| 1016 | + lockdep_assert_held(&conn->nopin_timer_lock); |
|---|
| 1017 | + |
|---|
| 1037 | 1018 | /* |
|---|
| 1038 | 1019 | * NOPIN timeout is disabled. |
|---|
| 1039 | 1020 | */ |
|---|
| .. | .. |
|---|
| 1247 | 1228 | iscsi_dump_sess_ops(sess->sess_ops); |
|---|
| 1248 | 1229 | } |
|---|
| 1249 | 1230 | |
|---|
| 1250 | | -static int iscsit_do_rx_data( |
|---|
| 1231 | +int rx_data( |
|---|
| 1251 | 1232 | struct iscsi_conn *conn, |
|---|
| 1252 | | - struct iscsi_data_count *count) |
|---|
| 1233 | + struct kvec *iov, |
|---|
| 1234 | + int iov_count, |
|---|
| 1235 | + int data) |
|---|
| 1253 | 1236 | { |
|---|
| 1254 | | - int data = count->data_length, rx_loop = 0, total_rx = 0; |
|---|
| 1237 | + int rx_loop = 0, total_rx = 0; |
|---|
| 1255 | 1238 | struct msghdr msg; |
|---|
| 1256 | 1239 | |
|---|
| 1257 | 1240 | if (!conn || !conn->sock || !conn->conn_ops) |
|---|
| 1258 | 1241 | return -1; |
|---|
| 1259 | 1242 | |
|---|
| 1260 | 1243 | memset(&msg, 0, sizeof(struct msghdr)); |
|---|
| 1261 | | - iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, |
|---|
| 1262 | | - count->iov, count->iov_count, data); |
|---|
| 1244 | + iov_iter_kvec(&msg.msg_iter, READ, iov, iov_count, data); |
|---|
| 1263 | 1245 | |
|---|
| 1264 | 1246 | while (msg_data_left(&msg)) { |
|---|
| 1265 | 1247 | rx_loop = sock_recvmsg(conn->sock, &msg, MSG_WAITALL); |
|---|
| .. | .. |
|---|
| 1274 | 1256 | } |
|---|
| 1275 | 1257 | |
|---|
| 1276 | 1258 | return total_rx; |
|---|
| 1277 | | -} |
|---|
| 1278 | | - |
|---|
| 1279 | | -int rx_data( |
|---|
| 1280 | | - struct iscsi_conn *conn, |
|---|
| 1281 | | - struct kvec *iov, |
|---|
| 1282 | | - int iov_count, |
|---|
| 1283 | | - int data) |
|---|
| 1284 | | -{ |
|---|
| 1285 | | - struct iscsi_data_count c; |
|---|
| 1286 | | - |
|---|
| 1287 | | - if (!conn || !conn->sock || !conn->conn_ops) |
|---|
| 1288 | | - return -1; |
|---|
| 1289 | | - |
|---|
| 1290 | | - memset(&c, 0, sizeof(struct iscsi_data_count)); |
|---|
| 1291 | | - c.iov = iov; |
|---|
| 1292 | | - c.iov_count = iov_count; |
|---|
| 1293 | | - c.data_length = data; |
|---|
| 1294 | | - c.type = ISCSI_RX_DATA; |
|---|
| 1295 | | - |
|---|
| 1296 | | - return iscsit_do_rx_data(conn, &c); |
|---|
| 1297 | 1259 | } |
|---|
| 1298 | 1260 | |
|---|
| 1299 | 1261 | int tx_data( |
|---|
| .. | .. |
|---|
| 1315 | 1277 | |
|---|
| 1316 | 1278 | memset(&msg, 0, sizeof(struct msghdr)); |
|---|
| 1317 | 1279 | |
|---|
| 1318 | | - iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, |
|---|
| 1319 | | - iov, iov_count, data); |
|---|
| 1280 | + iov_iter_kvec(&msg.msg_iter, WRITE, iov, iov_count, data); |
|---|
| 1320 | 1281 | |
|---|
| 1321 | 1282 | while (msg_data_left(&msg)) { |
|---|
| 1322 | 1283 | int tx_loop = sock_sendmsg(conn->sock, &msg); |
|---|
| .. | .. |
|---|
| 1405 | 1366 | |
|---|
| 1406 | 1367 | return tpg->tpg_tiqn; |
|---|
| 1407 | 1368 | } |
|---|
| 1369 | + |
|---|
| 1370 | +void iscsit_fill_cxn_timeout_err_stats(struct iscsi_session *sess) |
|---|
| 1371 | +{ |
|---|
| 1372 | + struct iscsi_portal_group *tpg = sess->tpg; |
|---|
| 1373 | + struct iscsi_tiqn *tiqn = tpg->tpg_tiqn; |
|---|
| 1374 | + |
|---|
| 1375 | + if (!tiqn) |
|---|
| 1376 | + return; |
|---|
| 1377 | + |
|---|
| 1378 | + spin_lock_bh(&tiqn->sess_err_stats.lock); |
|---|
| 1379 | + strlcpy(tiqn->sess_err_stats.last_sess_fail_rem_name, |
|---|
| 1380 | + sess->sess_ops->InitiatorName, |
|---|
| 1381 | + sizeof(tiqn->sess_err_stats.last_sess_fail_rem_name)); |
|---|
| 1382 | + tiqn->sess_err_stats.last_sess_failure_type = |
|---|
| 1383 | + ISCSI_SESS_ERR_CXN_TIMEOUT; |
|---|
| 1384 | + tiqn->sess_err_stats.cxn_timeout_errors++; |
|---|
| 1385 | + atomic_long_inc(&sess->conn_timeout_errors); |
|---|
| 1386 | + spin_unlock_bh(&tiqn->sess_err_stats.lock); |
|---|
| 1387 | +} |
|---|