Skip to content

Commit 88dcd2d

Browse files
author
Nicholas Bellinger
committed
iscsi-target: Convert iscsi_thread_set usage to kthread.h
This patch converts iscsi-target code to use modern kthread.h API callers for creating RX/TX threads for each new iscsi_conn descriptor, and releasing associated RX/TX threads during connection shutdown. This is done using iscsit_start_kthreads() -> kthread_run() to start new kthreads from within iscsi_post_login_handler(), and invoking kthread_stop() from existing iscsit_close_connection() code. Also, convert iscsit_logout_post_handler_closesession() code to use cmpxchg when determing when iscsit_cause_connection_reinstatement() needs to sleep waiting for completion. Reported-by: Sagi Grimberg <sagig@mellanox.com> Tested-by: Sagi Grimberg <sagig@mellanox.com> Cc: Slava Shwartsman <valyushash@gmail.com> Cc: <stable@vger.kernel.org> # v3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent 5bc6510 commit 88dcd2d

File tree

4 files changed

+114
-69
lines changed

4 files changed

+114
-69
lines changed

drivers/target/iscsi/iscsi_target.c

Lines changed: 45 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ static struct iscsit_transport iscsi_target_transport = {
537537

538538
static int __init iscsi_target_init_module(void)
539539
{
540-
int ret = 0;
540+
int ret = 0, size;
541541

542542
pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
543543

@@ -546,6 +546,7 @@ static int __init iscsi_target_init_module(void)
546546
pr_err("Unable to allocate memory for iscsit_global\n");
547547
return -1;
548548
}
549+
spin_lock_init(&iscsit_global->ts_bitmap_lock);
549550
mutex_init(&auth_id_lock);
550551
spin_lock_init(&sess_idr_lock);
551552
idr_init(&tiqn_idr);
@@ -555,15 +556,11 @@ static int __init iscsi_target_init_module(void)
555556
if (ret < 0)
556557
goto out;
557558

558-
ret = iscsi_thread_set_init();
559-
if (ret < 0)
559+
size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
560+
iscsit_global->ts_bitmap = vzalloc(size);
561+
if (!iscsit_global->ts_bitmap) {
562+
pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
560563
goto configfs_out;
561-
562-
if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) !=
563-
TARGET_THREAD_SET_COUNT) {
564-
pr_err("iscsi_allocate_thread_sets() returned"
565-
" unexpected value!\n");
566-
goto ts_out1;
567564
}
568565

569566
lio_qr_cache = kmem_cache_create("lio_qr_cache",
@@ -572,7 +569,7 @@ static int __init iscsi_target_init_module(void)
572569
if (!lio_qr_cache) {
573570
pr_err("nable to kmem_cache_create() for"
574571
" lio_qr_cache\n");
575-
goto ts_out2;
572+
goto bitmap_out;
576573
}
577574

578575
lio_dr_cache = kmem_cache_create("lio_dr_cache",
@@ -617,10 +614,8 @@ static int __init iscsi_target_init_module(void)
617614
kmem_cache_destroy(lio_dr_cache);
618615
qr_out:
619616
kmem_cache_destroy(lio_qr_cache);
620-
ts_out2:
621-
iscsi_deallocate_thread_sets();
622-
ts_out1:
623-
iscsi_thread_set_free();
617+
bitmap_out:
618+
vfree(iscsit_global->ts_bitmap);
624619
configfs_out:
625620
iscsi_target_deregister_configfs();
626621
out:
@@ -630,8 +625,6 @@ static int __init iscsi_target_init_module(void)
630625

631626
static void __exit iscsi_target_cleanup_module(void)
632627
{
633-
iscsi_deallocate_thread_sets();
634-
iscsi_thread_set_free();
635628
iscsit_release_discovery_tpg();
636629
iscsit_unregister_transport(&iscsi_target_transport);
637630
kmem_cache_destroy(lio_qr_cache);
@@ -641,6 +634,7 @@ static void __exit iscsi_target_cleanup_module(void)
641634

642635
iscsi_target_deregister_configfs();
643636

637+
vfree(iscsit_global->ts_bitmap);
644638
kfree(iscsit_global);
645639
}
646640

@@ -3709,17 +3703,16 @@ static int iscsit_send_reject(
37093703

37103704
void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
37113705
{
3712-
struct iscsi_thread_set *ts = conn->thread_set;
37133706
int ord, cpu;
37143707
/*
3715-
* thread_id is assigned from iscsit_global->ts_bitmap from
3716-
* within iscsi_thread_set.c:iscsi_allocate_thread_sets()
3708+
* bitmap_id is assigned from iscsit_global->ts_bitmap from
3709+
* within iscsit_start_kthreads()
37173710
*
3718-
* Here we use thread_id to determine which CPU that this
3719-
* iSCSI connection's iscsi_thread_set will be scheduled to
3711+
* Here we use bitmap_id to determine which CPU that this
3712+
* iSCSI connection's RX/TX threads will be scheduled to
37203713
* execute upon.
37213714
*/
3722-
ord = ts->thread_id % cpumask_weight(cpu_online_mask);
3715+
ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
37233716
for_each_online_cpu(cpu) {
37243717
if (ord-- == 0) {
37253718
cpumask_set_cpu(cpu, conn->conn_cpumask);
@@ -3908,7 +3901,7 @@ iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
39083901
switch (state) {
39093902
case ISTATE_SEND_LOGOUTRSP:
39103903
if (!iscsit_logout_post_handler(cmd, conn))
3911-
goto restart;
3904+
return -ECONNRESET;
39123905
/* fall through */
39133906
case ISTATE_SEND_STATUS:
39143907
case ISTATE_SEND_ASYNCMSG:
@@ -3936,8 +3929,6 @@ iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
39363929

39373930
err:
39383931
return -1;
3939-
restart:
3940-
return -EAGAIN;
39413932
}
39423933

39433934
static int iscsit_handle_response_queue(struct iscsi_conn *conn)
@@ -3964,21 +3955,13 @@ static int iscsit_handle_response_queue(struct iscsi_conn *conn)
39643955
int iscsi_target_tx_thread(void *arg)
39653956
{
39663957
int ret = 0;
3967-
struct iscsi_conn *conn;
3968-
struct iscsi_thread_set *ts = arg;
3958+
struct iscsi_conn *conn = arg;
39693959
/*
39703960
* Allow ourselves to be interrupted by SIGINT so that a
39713961
* connection recovery / failure event can be triggered externally.
39723962
*/
39733963
allow_signal(SIGINT);
39743964

3975-
restart:
3976-
conn = iscsi_tx_thread_pre_handler(ts);
3977-
if (!conn)
3978-
goto out;
3979-
3980-
ret = 0;
3981-
39823965
while (!kthread_should_stop()) {
39833966
/*
39843967
* Ensure that both TX and RX per connection kthreads
@@ -3987,11 +3970,9 @@ int iscsi_target_tx_thread(void *arg)
39873970
iscsit_thread_check_cpumask(conn, current, 1);
39883971

39893972
wait_event_interruptible(conn->queues_wq,
3990-
!iscsit_conn_all_queues_empty(conn) ||
3991-
ts->status == ISCSI_THREAD_SET_RESET);
3973+
!iscsit_conn_all_queues_empty(conn));
39923974

3993-
if ((ts->status == ISCSI_THREAD_SET_RESET) ||
3994-
signal_pending(current))
3975+
if (signal_pending(current))
39953976
goto transport_err;
39963977

39973978
get_immediate:
@@ -4002,15 +3983,14 @@ int iscsi_target_tx_thread(void *arg)
40023983
ret = iscsit_handle_response_queue(conn);
40033984
if (ret == 1)
40043985
goto get_immediate;
4005-
else if (ret == -EAGAIN)
4006-
goto restart;
3986+
else if (ret == -ECONNRESET)
3987+
goto out;
40073988
else if (ret < 0)
40083989
goto transport_err;
40093990
}
40103991

40113992
transport_err:
40123993
iscsit_take_action_for_connection_exit(conn);
4013-
goto restart;
40143994
out:
40153995
return 0;
40163996
}
@@ -4105,20 +4085,14 @@ int iscsi_target_rx_thread(void *arg)
41054085
int ret;
41064086
u8 buffer[ISCSI_HDR_LEN], opcode;
41074087
u32 checksum = 0, digest = 0;
4108-
struct iscsi_conn *conn = NULL;
4109-
struct iscsi_thread_set *ts = arg;
4088+
struct iscsi_conn *conn = arg;
41104089
struct kvec iov;
41114090
/*
41124091
* Allow ourselves to be interrupted by SIGINT so that a
41134092
* connection recovery / failure event can be triggered externally.
41144093
*/
41154094
allow_signal(SIGINT);
41164095

4117-
restart:
4118-
conn = iscsi_rx_thread_pre_handler(ts);
4119-
if (!conn)
4120-
goto out;
4121-
41224096
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
41234097
struct completion comp;
41244098
int rc;
@@ -4128,7 +4102,7 @@ int iscsi_target_rx_thread(void *arg)
41284102
if (rc < 0)
41294103
goto transport_err;
41304104

4131-
goto out;
4105+
goto transport_err;
41324106
}
41334107

41344108
while (!kthread_should_stop()) {
@@ -4204,8 +4178,6 @@ int iscsi_target_rx_thread(void *arg)
42044178
if (!signal_pending(current))
42054179
atomic_set(&conn->transport_failed, 1);
42064180
iscsit_take_action_for_connection_exit(conn);
4207-
goto restart;
4208-
out:
42094181
return 0;
42104182
}
42114183

@@ -4261,7 +4233,24 @@ int iscsit_close_connection(
42614233
*/
42624234
complete(&conn->conn_logout_comp);
42634235

4264-
iscsi_release_thread_set(conn);
4236+
if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
4237+
if (conn->tx_thread &&
4238+
cmpxchg(&conn->tx_thread_active, true, false)) {
4239+
send_sig(SIGINT, conn->tx_thread, 1);
4240+
kthread_stop(conn->tx_thread);
4241+
}
4242+
} else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
4243+
if (conn->rx_thread &&
4244+
cmpxchg(&conn->rx_thread_active, true, false)) {
4245+
send_sig(SIGINT, conn->rx_thread, 1);
4246+
kthread_stop(conn->rx_thread);
4247+
}
4248+
}
4249+
4250+
spin_lock(&iscsit_global->ts_bitmap_lock);
4251+
bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
4252+
get_order(1));
4253+
spin_unlock(&iscsit_global->ts_bitmap_lock);
42654254

42664255
iscsit_stop_timers_for_cmds(conn);
42674256
iscsit_stop_nopin_response_timer(conn);
@@ -4539,29 +4528,26 @@ static void iscsit_logout_post_handler_closesession(
45394528
struct iscsi_conn *conn)
45404529
{
45414530
struct iscsi_session *sess = conn->sess;
4542-
4543-
iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
4544-
iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
4531+
int sleep = cmpxchg(&conn->tx_thread_active, true, false);
45454532

45464533
atomic_set(&conn->conn_logout_remove, 0);
45474534
complete(&conn->conn_logout_comp);
45484535

45494536
iscsit_dec_conn_usage_count(conn);
4550-
iscsit_stop_session(sess, 1, 1);
4537+
iscsit_stop_session(sess, sleep, sleep);
45514538
iscsit_dec_session_usage_count(sess);
45524539
target_put_session(sess->se_sess);
45534540
}
45544541

45554542
static void iscsit_logout_post_handler_samecid(
45564543
struct iscsi_conn *conn)
45574544
{
4558-
iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
4559-
iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
4545+
int sleep = cmpxchg(&conn->tx_thread_active, true, false);
45604546

45614547
atomic_set(&conn->conn_logout_remove, 0);
45624548
complete(&conn->conn_logout_comp);
45634549

4564-
iscsit_cause_connection_reinstatement(conn, 1);
4550+
iscsit_cause_connection_reinstatement(conn, sleep);
45654551
iscsit_dec_conn_usage_count(conn);
45664552
}
45674553

drivers/target/iscsi/iscsi_target_erl0.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,10 @@ void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn)
861861
}
862862
spin_unlock_bh(&conn->state_lock);
863863

864-
iscsi_thread_set_force_reinstatement(conn);
864+
if (conn->tx_thread && conn->tx_thread_active)
865+
send_sig(SIGINT, conn->tx_thread, 1);
866+
if (conn->rx_thread && conn->rx_thread_active)
867+
send_sig(SIGINT, conn->rx_thread, 1);
865868

866869
sleep:
867870
wait_for_completion(&conn->conn_wait_rcfr_comp);
@@ -886,10 +889,10 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
886889
return;
887890
}
888891

889-
if (iscsi_thread_set_force_reinstatement(conn) < 0) {
890-
spin_unlock_bh(&conn->state_lock);
891-
return;
892-
}
892+
if (conn->tx_thread && conn->tx_thread_active)
893+
send_sig(SIGINT, conn->tx_thread, 1);
894+
if (conn->rx_thread && conn->rx_thread_active)
895+
send_sig(SIGINT, conn->rx_thread, 1);
893896

894897
atomic_set(&conn->connection_reinstatement, 1);
895898
if (!sleep) {

drivers/target/iscsi/iscsi_target_login.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,51 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
699699
iscsit_start_nopin_timer(conn);
700700
}
701701

702+
int iscsit_start_kthreads(struct iscsi_conn *conn)
703+
{
704+
int ret = 0;
705+
706+
spin_lock(&iscsit_global->ts_bitmap_lock);
707+
conn->bitmap_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
708+
ISCSIT_BITMAP_BITS, get_order(1));
709+
spin_unlock(&iscsit_global->ts_bitmap_lock);
710+
711+
if (conn->bitmap_id < 0) {
712+
pr_err("bitmap_find_free_region() failed for"
713+
" iscsit_start_kthreads()\n");
714+
return -ENOMEM;
715+
}
716+
717+
conn->tx_thread = kthread_run(iscsi_target_tx_thread, conn,
718+
"%s", ISCSI_TX_THREAD_NAME);
719+
if (IS_ERR(conn->tx_thread)) {
720+
pr_err("Unable to start iscsi_target_tx_thread\n");
721+
ret = PTR_ERR(conn->tx_thread);
722+
goto out_bitmap;
723+
}
724+
conn->tx_thread_active = true;
725+
726+
conn->rx_thread = kthread_run(iscsi_target_rx_thread, conn,
727+
"%s", ISCSI_RX_THREAD_NAME);
728+
if (IS_ERR(conn->rx_thread)) {
729+
pr_err("Unable to start iscsi_target_rx_thread\n");
730+
ret = PTR_ERR(conn->rx_thread);
731+
goto out_tx;
732+
}
733+
conn->rx_thread_active = true;
734+
735+
return 0;
736+
out_tx:
737+
kthread_stop(conn->tx_thread);
738+
conn->tx_thread_active = false;
739+
out_bitmap:
740+
spin_lock(&iscsit_global->ts_bitmap_lock);
741+
bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
742+
get_order(1));
743+
spin_unlock(&iscsit_global->ts_bitmap_lock);
744+
return ret;
745+
}
746+
702747
int iscsi_post_login_handler(
703748
struct iscsi_np *np,
704749
struct iscsi_conn *conn,
@@ -709,7 +754,7 @@ int iscsi_post_login_handler(
709754
struct se_session *se_sess = sess->se_sess;
710755
struct iscsi_portal_group *tpg = sess->tpg;
711756
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
712-
struct iscsi_thread_set *ts;
757+
int rc;
713758

714759
iscsit_inc_conn_usage_count(conn);
715760

@@ -724,7 +769,6 @@ int iscsi_post_login_handler(
724769
/*
725770
* SCSI Initiator -> SCSI Target Port Mapping
726771
*/
727-
ts = iscsi_get_thread_set();
728772
if (!zero_tsih) {
729773
iscsi_set_session_parameters(sess->sess_ops,
730774
conn->param_list, 0);
@@ -751,9 +795,11 @@ int iscsi_post_login_handler(
751795
sess->sess_ops->InitiatorName);
752796
spin_unlock_bh(&sess->conn_lock);
753797

754-
iscsi_post_login_start_timers(conn);
798+
rc = iscsit_start_kthreads(conn);
799+
if (rc)
800+
return rc;
755801

756-
iscsi_activate_thread_set(conn, ts);
802+
iscsi_post_login_start_timers(conn);
757803
/*
758804
* Determine CPU mask to ensure connection's RX and TX kthreads
759805
* are scheduled on the same CPU.
@@ -810,8 +856,11 @@ int iscsi_post_login_handler(
810856
" iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt);
811857
spin_unlock_bh(&se_tpg->session_lock);
812858

859+
rc = iscsit_start_kthreads(conn);
860+
if (rc)
861+
return rc;
862+
813863
iscsi_post_login_start_timers(conn);
814-
iscsi_activate_thread_set(conn, ts);
815864
/*
816865
* Determine CPU mask to ensure connection's RX and TX kthreads
817866
* are scheduled on the same CPU.

0 commit comments

Comments
 (0)