Skip to content

Commit defd884

Browse files
author
Nicholas Bellinger
committed
iscsi/iser-target: Fix isert_conn->state hung shutdown issues
This patch addresses a couple of different hug shutdown issues related to wait_event() + isert_conn->state. First, it changes isert_conn->conn_wait + isert_conn->conn_wait_comp_err from waitqueues to completions, and sets ISER_CONN_TERMINATING from within isert_disconnect_work(). Second, it splits isert_free_conn() into isert_wait_conn() that is called earlier in iscsit_close_connection() to ensure that all outstanding commands have completed before continuing. Finally, it breaks isert_cq_comp_err() into seperate TX / RX related code, and adds logic in isert_cq_rx_comp_err() to wait for outstanding commands to complete before setting ISER_CONN_DOWN and calling complete(&isert_conn->conn_wait_comp_err). Acked-by: Sagi Grimberg <[email protected]> Cc: Or Gerlitz <[email protected]> Cc: <[email protected]> raspberrypi#3.10+ Signed-off-by: Nicholas Bellinger <[email protected]>
1 parent 5159d76 commit defd884

File tree

4 files changed

+55
-60
lines changed

4 files changed

+55
-60
lines changed

drivers/infiniband/ulp/isert/ib_isert.c

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,8 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
492492
isert_conn->state = ISER_CONN_INIT;
493493
INIT_LIST_HEAD(&isert_conn->conn_accept_node);
494494
init_completion(&isert_conn->conn_login_comp);
495-
init_waitqueue_head(&isert_conn->conn_wait);
496-
init_waitqueue_head(&isert_conn->conn_wait_comp_err);
495+
init_completion(&isert_conn->conn_wait);
496+
init_completion(&isert_conn->conn_wait_comp_err);
497497
kref_init(&isert_conn->conn_kref);
498498
kref_get(&isert_conn->conn_kref);
499499
mutex_init(&isert_conn->conn_mutex);
@@ -688,11 +688,11 @@ isert_disconnect_work(struct work_struct *work)
688688

689689
pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
690690
mutex_lock(&isert_conn->conn_mutex);
691-
isert_conn->state = ISER_CONN_DOWN;
691+
if (isert_conn->state == ISER_CONN_UP)
692+
isert_conn->state = ISER_CONN_TERMINATING;
692693

693694
if (isert_conn->post_recv_buf_count == 0 &&
694695
atomic_read(&isert_conn->post_send_buf_count) == 0) {
695-
pr_debug("Calling wake_up(&isert_conn->conn_wait);\n");
696696
mutex_unlock(&isert_conn->conn_mutex);
697697
goto wake_up;
698698
}
@@ -712,7 +712,7 @@ isert_disconnect_work(struct work_struct *work)
712712
mutex_unlock(&isert_conn->conn_mutex);
713713

714714
wake_up:
715-
wake_up(&isert_conn->conn_wait);
715+
complete(&isert_conn->conn_wait);
716716
isert_put_conn(isert_conn);
717717
}
718718

@@ -1589,7 +1589,7 @@ isert_do_control_comp(struct work_struct *work)
15891589
pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
15901590
/*
15911591
* Call atomic_dec(&isert_conn->post_send_buf_count)
1592-
* from isert_free_conn()
1592+
* from isert_wait_conn()
15931593
*/
15941594
isert_conn->logout_posted = true;
15951595
iscsit_logout_post_handler(cmd, cmd->conn);
@@ -1691,31 +1691,39 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
16911691
}
16921692

16931693
static void
1694-
isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
1694+
isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
16951695
{
16961696
struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
1697+
struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
1698+
1699+
if (!isert_cmd)
1700+
isert_unmap_tx_desc(tx_desc, ib_dev);
1701+
else
1702+
isert_completion_put(tx_desc, isert_cmd, ib_dev);
1703+
}
1704+
1705+
static void
1706+
isert_cq_rx_comp_err(struct isert_conn *isert_conn)
1707+
{
1708+
struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
1709+
struct iscsi_conn *conn = isert_conn->conn;
16971710

1698-
if (tx_desc) {
1699-
struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
1711+
if (isert_conn->post_recv_buf_count)
1712+
return;
17001713

1701-
if (!isert_cmd)
1702-
isert_unmap_tx_desc(tx_desc, ib_dev);
1703-
else
1704-
isert_completion_put(tx_desc, isert_cmd, ib_dev);
1714+
if (conn->sess) {
1715+
target_sess_cmd_list_set_waiting(conn->sess->se_sess);
1716+
target_wait_for_sess_cmds(conn->sess->se_sess);
17051717
}
17061718

1707-
if (isert_conn->post_recv_buf_count == 0 &&
1708-
atomic_read(&isert_conn->post_send_buf_count) == 0) {
1709-
pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1710-
pr_debug("Calling wake_up from isert_cq_comp_err\n");
1719+
while (atomic_read(&isert_conn->post_send_buf_count))
1720+
msleep(3000);
17111721

1712-
mutex_lock(&isert_conn->conn_mutex);
1713-
if (isert_conn->state != ISER_CONN_DOWN)
1714-
isert_conn->state = ISER_CONN_TERMINATING;
1715-
mutex_unlock(&isert_conn->conn_mutex);
1722+
mutex_lock(&isert_conn->conn_mutex);
1723+
isert_conn->state = ISER_CONN_DOWN;
1724+
mutex_unlock(&isert_conn->conn_mutex);
17161725

1717-
wake_up(&isert_conn->conn_wait_comp_err);
1718-
}
1726+
complete(&isert_conn->conn_wait_comp_err);
17191727
}
17201728

17211729
static void
@@ -1740,8 +1748,9 @@ isert_cq_tx_work(struct work_struct *work)
17401748
pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n");
17411749
pr_debug("TX wc.status: 0x%08x\n", wc.status);
17421750
pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err);
1751+
17431752
atomic_dec(&isert_conn->post_send_buf_count);
1744-
isert_cq_comp_err(tx_desc, isert_conn);
1753+
isert_cq_tx_comp_err(tx_desc, isert_conn);
17451754
}
17461755
}
17471756

@@ -1784,7 +1793,7 @@ isert_cq_rx_work(struct work_struct *work)
17841793
wc.vendor_err);
17851794
}
17861795
isert_conn->post_recv_buf_count--;
1787-
isert_cq_comp_err(NULL, isert_conn);
1796+
isert_cq_rx_comp_err(isert_conn);
17881797
}
17891798
}
17901799

@@ -2702,22 +2711,11 @@ isert_free_np(struct iscsi_np *np)
27022711
kfree(isert_np);
27032712
}
27042713

2705-
static int isert_check_state(struct isert_conn *isert_conn, int state)
2706-
{
2707-
int ret;
2708-
2709-
mutex_lock(&isert_conn->conn_mutex);
2710-
ret = (isert_conn->state == state);
2711-
mutex_unlock(&isert_conn->conn_mutex);
2712-
2713-
return ret;
2714-
}
2715-
2716-
static void isert_free_conn(struct iscsi_conn *conn)
2714+
static void isert_wait_conn(struct iscsi_conn *conn)
27172715
{
27182716
struct isert_conn *isert_conn = conn->context;
27192717

2720-
pr_debug("isert_free_conn: Starting \n");
2718+
pr_debug("isert_wait_conn: Starting \n");
27212719
/*
27222720
* Decrement post_send_buf_count for special case when called
27232721
* from isert_do_control_comp() -> iscsit_logout_post_handler()
@@ -2727,38 +2725,29 @@ static void isert_free_conn(struct iscsi_conn *conn)
27272725
atomic_dec(&isert_conn->post_send_buf_count);
27282726

27292727
if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) {
2730-
pr_debug("Calling rdma_disconnect from isert_free_conn\n");
2728+
pr_debug("Calling rdma_disconnect from isert_wait_conn\n");
27312729
rdma_disconnect(isert_conn->conn_cm_id);
27322730
}
27332731
/*
27342732
* Only wait for conn_wait_comp_err if the isert_conn made it
27352733
* into full feature phase..
27362734
*/
2737-
if (isert_conn->state == ISER_CONN_UP) {
2738-
pr_debug("isert_free_conn: Before wait_event comp_err %d\n",
2739-
isert_conn->state);
2740-
mutex_unlock(&isert_conn->conn_mutex);
2741-
2742-
wait_event(isert_conn->conn_wait_comp_err,
2743-
(isert_check_state(isert_conn, ISER_CONN_TERMINATING)));
2744-
2745-
wait_event(isert_conn->conn_wait,
2746-
(isert_check_state(isert_conn, ISER_CONN_DOWN)));
2747-
2748-
isert_put_conn(isert_conn);
2749-
return;
2750-
}
27512735
if (isert_conn->state == ISER_CONN_INIT) {
27522736
mutex_unlock(&isert_conn->conn_mutex);
2753-
isert_put_conn(isert_conn);
27542737
return;
27552738
}
2756-
pr_debug("isert_free_conn: wait_event conn_wait %d\n",
2757-
isert_conn->state);
2739+
if (isert_conn->state == ISER_CONN_UP)
2740+
isert_conn->state = ISER_CONN_TERMINATING;
27582741
mutex_unlock(&isert_conn->conn_mutex);
27592742

2760-
wait_event(isert_conn->conn_wait,
2761-
(isert_check_state(isert_conn, ISER_CONN_DOWN)));
2743+
wait_for_completion(&isert_conn->conn_wait_comp_err);
2744+
2745+
wait_for_completion(&isert_conn->conn_wait);
2746+
}
2747+
2748+
static void isert_free_conn(struct iscsi_conn *conn)
2749+
{
2750+
struct isert_conn *isert_conn = conn->context;
27622751

27632752
isert_put_conn(isert_conn);
27642753
}
@@ -2771,6 +2760,7 @@ static struct iscsit_transport iser_target_transport = {
27712760
.iscsit_setup_np = isert_setup_np,
27722761
.iscsit_accept_np = isert_accept_np,
27732762
.iscsit_free_np = isert_free_np,
2763+
.iscsit_wait_conn = isert_wait_conn,
27742764
.iscsit_free_conn = isert_free_conn,
27752765
.iscsit_get_login_rx = isert_get_login_rx,
27762766
.iscsit_put_login_tx = isert_put_login_tx,

drivers/infiniband/ulp/isert/ib_isert.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ struct isert_conn {
116116
struct isert_device *conn_device;
117117
struct work_struct conn_logout_work;
118118
struct mutex conn_mutex;
119-
wait_queue_head_t conn_wait;
120-
wait_queue_head_t conn_wait_comp_err;
119+
struct completion conn_wait;
120+
struct completion conn_wait_comp_err;
121121
struct kref conn_kref;
122122
struct list_head conn_fr_pool;
123123
int conn_fr_pool_size;

drivers/target/iscsi/iscsi_target.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4196,6 +4196,10 @@ int iscsit_close_connection(
41964196
iscsit_stop_timers_for_cmds(conn);
41974197
iscsit_stop_nopin_response_timer(conn);
41984198
iscsit_stop_nopin_timer(conn);
4199+
4200+
if (conn->conn_transport->iscsit_wait_conn)
4201+
conn->conn_transport->iscsit_wait_conn(conn);
4202+
41994203
iscsit_free_queue_reqs_for_conn(conn);
42004204

42014205
/*

include/target/iscsi/iscsi_transport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct iscsit_transport {
1212
int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *);
1313
int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *);
1414
void (*iscsit_free_np)(struct iscsi_np *);
15+
void (*iscsit_wait_conn)(struct iscsi_conn *);
1516
void (*iscsit_free_conn)(struct iscsi_conn *);
1617
int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *);
1718
int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32);

0 commit comments

Comments
 (0)