diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-03-30 18:50:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-13 07:59:40 -0400 |
commit | d306606e58d53a9d8cd78fefacbe9a50b3aa9fcd (patch) | |
tree | 4ff53131f6e1b06540a6f0415bb99a6810a68157 | |
parent | 50c648e394a0968f19d448b70bec82da88219963 (diff) |
iser-target: Add missing se_cmd put for WRITE_PENDING in tx_comp_err
commit 03e7848a64ed535a30f5d7fc6dede2d5a6a2534b upstream.
This patch fixes a bug where outstanding RDMA_READs with WRITE_PENDING
status require an extra target_put_sess_cmd() in isert_put_cmd() code
when called from isert_cq_tx_comp_err() + isert_cq_drain_comp_llist()
context during session shutdown.
The extra kref PUT is required so that transport_generic_free_cmd()
invokes the last target_put_sess_cmd() -> target_release_cmd_kref(),
which will complete(&se_cmd->cmd_wait_comp) the outstanding se_cmd
descriptor with WRITE_PENDING status, and awake the completion in
target_wait_for_sess_cmds() to invoke TFO->release_cmd().
The bug was manifesting itself in target_wait_for_sess_cmds() where
a se_cmd descriptor with WRITE_PENDING status would end up sleeping
indefinately.
Acked-by: Sagi Grimberg <sagig@mellanox.com>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 588a5eca63d8..ce6c603a3cc9 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -1201,7 +1201,7 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) | |||
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | static void | 1203 | static void |
1204 | isert_put_cmd(struct isert_cmd *isert_cmd) | 1204 | isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) |
1205 | { | 1205 | { |
1206 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; | 1206 | struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; |
1207 | struct isert_conn *isert_conn = isert_cmd->conn; | 1207 | struct isert_conn *isert_conn = isert_cmd->conn; |
@@ -1216,8 +1216,21 @@ isert_put_cmd(struct isert_cmd *isert_cmd) | |||
1216 | list_del_init(&cmd->i_conn_node); | 1216 | list_del_init(&cmd->i_conn_node); |
1217 | spin_unlock_bh(&conn->cmd_lock); | 1217 | spin_unlock_bh(&conn->cmd_lock); |
1218 | 1218 | ||
1219 | if (cmd->data_direction == DMA_TO_DEVICE) | 1219 | if (cmd->data_direction == DMA_TO_DEVICE) { |
1220 | iscsit_stop_dataout_timer(cmd); | 1220 | iscsit_stop_dataout_timer(cmd); |
1221 | /* | ||
1222 | * Check for special case during comp_err where | ||
1223 | * WRITE_PENDING has been handed off from core, | ||
1224 | * but requires an extra target_put_sess_cmd() | ||
1225 | * before transport_generic_free_cmd() below. | ||
1226 | */ | ||
1227 | if (comp_err && | ||
1228 | cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { | ||
1229 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
1230 | |||
1231 | target_put_sess_cmd(se_cmd->se_sess, se_cmd); | ||
1232 | } | ||
1233 | } | ||
1221 | 1234 | ||
1222 | isert_unmap_cmd(isert_cmd, isert_conn); | 1235 | isert_unmap_cmd(isert_cmd, isert_conn); |
1223 | transport_generic_free_cmd(&cmd->se_cmd, 0); | 1236 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
@@ -1271,7 +1284,7 @@ isert_unmap_tx_desc(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev) | |||
1271 | 1284 | ||
1272 | static void | 1285 | static void |
1273 | isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, | 1286 | isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, |
1274 | struct ib_device *ib_dev) | 1287 | struct ib_device *ib_dev, bool comp_err) |
1275 | { | 1288 | { |
1276 | if (isert_cmd->sense_buf_dma != 0) { | 1289 | if (isert_cmd->sense_buf_dma != 0) { |
1277 | pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n"); | 1290 | pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n"); |
@@ -1281,7 +1294,7 @@ isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, | |||
1281 | } | 1294 | } |
1282 | 1295 | ||
1283 | isert_unmap_tx_desc(tx_desc, ib_dev); | 1296 | isert_unmap_tx_desc(tx_desc, ib_dev); |
1284 | isert_put_cmd(isert_cmd); | 1297 | isert_put_cmd(isert_cmd, comp_err); |
1285 | } | 1298 | } |
1286 | 1299 | ||
1287 | static void | 1300 | static void |
@@ -1336,14 +1349,14 @@ isert_do_control_comp(struct work_struct *work) | |||
1336 | iscsit_tmr_post_handler(cmd, cmd->conn); | 1349 | iscsit_tmr_post_handler(cmd, cmd->conn); |
1337 | 1350 | ||
1338 | cmd->i_state = ISTATE_SENT_STATUS; | 1351 | cmd->i_state = ISTATE_SENT_STATUS; |
1339 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 1352 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); |
1340 | break; | 1353 | break; |
1341 | case ISTATE_SEND_REJECT: | 1354 | case ISTATE_SEND_REJECT: |
1342 | pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n"); | 1355 | pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n"); |
1343 | atomic_dec(&isert_conn->post_send_buf_count); | 1356 | atomic_dec(&isert_conn->post_send_buf_count); |
1344 | 1357 | ||
1345 | cmd->i_state = ISTATE_SENT_STATUS; | 1358 | cmd->i_state = ISTATE_SENT_STATUS; |
1346 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); | 1359 | isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); |
1347 | break; | 1360 | break; |
1348 | case ISTATE_SEND_LOGOUTRSP: | 1361 | case ISTATE_SEND_LOGOUTRSP: |
1349 | pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); | 1362 | pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); |
@@ -1382,7 +1395,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc, | |||
1382 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); | 1395 | atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); |
1383 | 1396 | ||
1384 | cmd->i_state = ISTATE_SENT_STATUS; | 1397 | cmd->i_state = ISTATE_SENT_STATUS; |
1385 | isert_completion_put(tx_desc, isert_cmd, ib_dev); | 1398 | isert_completion_put(tx_desc, isert_cmd, ib_dev, false); |
1386 | } | 1399 | } |
1387 | 1400 | ||
1388 | static void | 1401 | static void |
@@ -1436,7 +1449,7 @@ isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn | |||
1436 | if (!isert_cmd) | 1449 | if (!isert_cmd) |
1437 | isert_unmap_tx_desc(tx_desc, ib_dev); | 1450 | isert_unmap_tx_desc(tx_desc, ib_dev); |
1438 | else | 1451 | else |
1439 | isert_completion_put(tx_desc, isert_cmd, ib_dev); | 1452 | isert_completion_put(tx_desc, isert_cmd, ib_dev, true); |
1440 | } | 1453 | } |
1441 | 1454 | ||
1442 | static void | 1455 | static void |