Skip to content

Commit 6f55b06

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: target: Drop sess_cmd_lock from I/O path
Drop the sess_cmd_lock by: - Removing the sess_cmd_list use from LIO core, because it's been moved to qla2xxx. - Removing sess_tearing_down check in the I/O path. Instead of using that bit and the sess_cmd_lock, we rely on the cmd_count percpu ref. To do this we switch to percpu_ref_kill_and_confirm/percpu_ref_tryget_live. Link: https://lore.kernel.org/r/1604257174-4524-7-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 605e740 commit 6f55b06

File tree

8 files changed

+43
-59
lines changed

8 files changed

+43
-59
lines changed

drivers/infiniband/ulp/isert/ib_isert.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2471,7 +2471,7 @@ isert_wait4cmds(struct iscsi_conn *conn)
24712471
isert_info("iscsi_conn %p\n", conn);
24722472

24732473
if (conn->sess) {
2474-
target_sess_cmd_list_set_waiting(conn->sess->se_sess);
2474+
target_stop_session(conn->sess->se_sess);
24752475
target_wait_for_sess_cmds(conn->sess->se_sess);
24762476
}
24772477
}

drivers/infiniband/ulp/srpt/ib_srpt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2084,7 +2084,7 @@ static void srpt_release_channel_work(struct work_struct *w)
20842084
se_sess = ch->sess;
20852085
BUG_ON(!se_sess);
20862086

2087-
target_sess_cmd_list_set_waiting(se_sess);
2087+
target_stop_session(se_sess);
20882088
target_wait_for_sess_cmds(se_sess);
20892089

20902090
target_remove_session(se_sess);

drivers/scsi/qla2xxx/tcm_qla2xxx.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,15 +368,10 @@ static void tcm_qla2xxx_put_sess(struct fc_port *sess)
368368
static void tcm_qla2xxx_close_session(struct se_session *se_sess)
369369
{
370370
struct fc_port *sess = se_sess->fabric_sess_ptr;
371-
struct scsi_qla_host *vha;
372-
unsigned long flags;
373371

374372
BUG_ON(!sess);
375-
vha = sess->vha;
376373

377-
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
378-
target_sess_cmd_list_set_waiting(se_sess);
379-
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
374+
target_stop_session(se_sess);
380375

381376
sess->explicit_logout = 1;
382377
tcm_qla2xxx_put_sess(sess);
@@ -831,7 +826,7 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess)
831826

832827
static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess)
833828
{
834-
target_sess_cmd_list_set_waiting(sess->se_sess);
829+
target_stop_session(sess->se_sess);
835830
}
836831

837832
static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl,

drivers/target/target_core_tpg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ static void target_shutdown_sessions(struct se_node_acl *acl)
328328
restart:
329329
spin_lock_irqsave(&acl->nacl_sess_lock, flags);
330330
list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) {
331-
if (sess->sess_tearing_down)
331+
if (atomic_read(&sess->stopped))
332332
continue;
333333

334334
list_del_init(&sess->sess_acl_list);

drivers/target/target_core_transport.c

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ static void target_release_sess_cmd_refcnt(struct percpu_ref *ref)
215215
{
216216
struct se_session *sess = container_of(ref, typeof(*sess), cmd_count);
217217

218-
wake_up(&sess->cmd_list_wq);
218+
wake_up(&sess->cmd_count_wq);
219219
}
220220

221221
/**
@@ -228,9 +228,10 @@ int transport_init_session(struct se_session *se_sess)
228228
{
229229
INIT_LIST_HEAD(&se_sess->sess_list);
230230
INIT_LIST_HEAD(&se_sess->sess_acl_list);
231-
INIT_LIST_HEAD(&se_sess->sess_cmd_list);
232231
spin_lock_init(&se_sess->sess_cmd_lock);
233-
init_waitqueue_head(&se_sess->cmd_list_wq);
232+
init_waitqueue_head(&se_sess->cmd_count_wq);
233+
init_completion(&se_sess->stop_done);
234+
atomic_set(&se_sess->stopped, 0);
234235
return percpu_ref_init(&se_sess->cmd_count,
235236
target_release_sess_cmd_refcnt, 0, GFP_KERNEL);
236237
}
@@ -239,11 +240,11 @@ EXPORT_SYMBOL(transport_init_session);
239240
void transport_uninit_session(struct se_session *se_sess)
240241
{
241242
/*
242-
* Drivers like iscsi and loop do not call
243-
* target_sess_cmd_list_set_waiting during session shutdown so we
244-
* have to drop the ref taken at init time here.
243+
* Drivers like iscsi and loop do not call target_stop_session
244+
* during session shutdown so we have to drop the ref taken at init
245+
* time here.
245246
*/
246-
if (!se_sess->sess_tearing_down)
247+
if (!atomic_read(&se_sess->stopped))
247248
percpu_ref_put(&se_sess->cmd_count);
248249

249250
percpu_ref_exit(&se_sess->cmd_count);
@@ -1632,9 +1633,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
16321633
if (flags & TARGET_SCF_UNKNOWN_SIZE)
16331634
se_cmd->unknown_data_length = 1;
16341635
/*
1635-
* Obtain struct se_cmd->cmd_kref reference and add new cmd to
1636-
* se_sess->sess_cmd_list. A second kref_get here is necessary
1637-
* for fabrics using TARGET_SCF_ACK_KREF that expect a second
1636+
* Obtain struct se_cmd->cmd_kref reference. A second kref_get here is
1637+
* necessary for fabrics using TARGET_SCF_ACK_KREF that expect a second
16381638
* kref_put() to happen during fabric packet acknowledgement.
16391639
*/
16401640
ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
@@ -2763,14 +2763,13 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
27632763
EXPORT_SYMBOL(transport_generic_free_cmd);
27642764

27652765
/**
2766-
* target_get_sess_cmd - Add command to active ->sess_cmd_list
2766+
* target_get_sess_cmd - Verify the session is accepting cmds and take ref
27672767
* @se_cmd: command descriptor to add
27682768
* @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd()
27692769
*/
27702770
int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
27712771
{
27722772
struct se_session *se_sess = se_cmd->se_sess;
2773-
unsigned long flags;
27742773
int ret = 0;
27752774

27762775
/*
@@ -2785,15 +2784,8 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
27852784
se_cmd->se_cmd_flags |= SCF_ACK_KREF;
27862785
}
27872786

2788-
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
2789-
if (se_sess->sess_tearing_down) {
2787+
if (!percpu_ref_tryget_live(&se_sess->cmd_count))
27902788
ret = -ESHUTDOWN;
2791-
goto out;
2792-
}
2793-
list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
2794-
percpu_ref_get(&se_sess->cmd_count);
2795-
out:
2796-
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
27972789

27982790
if (ret && ack_kref)
27992791
target_put_sess_cmd(se_cmd);
@@ -2818,13 +2810,6 @@ static void target_release_cmd_kref(struct kref *kref)
28182810
struct se_session *se_sess = se_cmd->se_sess;
28192811
struct completion *free_compl = se_cmd->free_compl;
28202812
struct completion *abrt_compl = se_cmd->abrt_compl;
2821-
unsigned long flags;
2822-
2823-
if (se_sess) {
2824-
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
2825-
list_del_init(&se_cmd->se_cmd_list);
2826-
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
2827-
}
28282813

28292814
target_free_cmd_mem(se_cmd);
28302815
se_cmd->se_tfo->release_cmd(se_cmd);
@@ -2952,41 +2937,45 @@ void target_show_cmd(const char *pfx, struct se_cmd *cmd)
29522937
}
29532938
EXPORT_SYMBOL(target_show_cmd);
29542939

2940+
static void target_stop_session_confirm(struct percpu_ref *ref)
2941+
{
2942+
struct se_session *se_sess = container_of(ref, struct se_session,
2943+
cmd_count);
2944+
complete_all(&se_sess->stop_done);
2945+
}
2946+
29552947
/**
2956-
* target_sess_cmd_list_set_waiting - Set sess_tearing_down so no new commands are queued.
2957-
* @se_sess: session to flag
2948+
* target_stop_session - Stop new IO from being queued on the session.
2949+
* @se_sess: session to stop
29582950
*/
2959-
void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
2951+
void target_stop_session(struct se_session *se_sess)
29602952
{
2961-
unsigned long flags;
2962-
2963-
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
2964-
se_sess->sess_tearing_down = 1;
2965-
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
2966-
2967-
percpu_ref_kill(&se_sess->cmd_count);
2953+
pr_debug("Stopping session queue.\n");
2954+
if (atomic_cmpxchg(&se_sess->stopped, 0, 1) == 0)
2955+
percpu_ref_kill_and_confirm(&se_sess->cmd_count,
2956+
target_stop_session_confirm);
29682957
}
2969-
EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
2958+
EXPORT_SYMBOL(target_stop_session);
29702959

29712960
/**
29722961
* target_wait_for_sess_cmds - Wait for outstanding commands
29732962
* @se_sess: session to wait for active I/O
29742963
*/
29752964
void target_wait_for_sess_cmds(struct se_session *se_sess)
29762965
{
2977-
struct se_cmd *cmd;
29782966
int ret;
29792967

2980-
WARN_ON_ONCE(!se_sess->sess_tearing_down);
2968+
WARN_ON_ONCE(!atomic_read(&se_sess->stopped));
29812969

29822970
do {
2983-
ret = wait_event_timeout(se_sess->cmd_list_wq,
2971+
pr_debug("Waiting for running cmds to complete.\n");
2972+
ret = wait_event_timeout(se_sess->cmd_count_wq,
29842973
percpu_ref_is_zero(&se_sess->cmd_count),
29852974
180 * HZ);
2986-
list_for_each_entry(cmd, &se_sess->sess_cmd_list, se_cmd_list)
2987-
target_show_cmd("session shutdown: still waiting for ",
2988-
cmd);
29892975
} while (ret <= 0);
2976+
2977+
wait_for_completion(&se_sess->stop_done);
2978+
pr_debug("Waiting for cmds done.\n");
29902979
}
29912980
EXPORT_SYMBOL(target_wait_for_sess_cmds);
29922981

drivers/target/tcm_fc/tfc_sess.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id)
275275

276276
static void ft_close_sess(struct ft_sess *sess)
277277
{
278-
target_sess_cmd_list_set_waiting(sess->se_sess);
278+
target_stop_session(sess->se_sess);
279279
target_wait_for_sess_cmds(sess->se_sess);
280280
ft_sess_put(sess);
281281
}

include/target/target_core_base.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item)
608608
}
609609

610610
struct se_session {
611-
unsigned sess_tearing_down:1;
611+
atomic_t stopped;
612612
u64 sess_bin_isid;
613613
enum target_prot_op sup_prot_ops;
614614
enum target_prot_type sess_prot_type;
@@ -618,9 +618,9 @@ struct se_session {
618618
struct percpu_ref cmd_count;
619619
struct list_head sess_list;
620620
struct list_head sess_acl_list;
621-
struct list_head sess_cmd_list;
622621
spinlock_t sess_cmd_lock;
623-
wait_queue_head_t cmd_list_wq;
622+
wait_queue_head_t cmd_count_wq;
623+
struct completion stop_done;
624624
void *sess_cmd_map;
625625
struct sbitmap_queue sess_tag_pool;
626626
};

include/target/target_core_fabric.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ int transport_send_check_condition_and_sense(struct se_cmd *,
178178
int target_send_busy(struct se_cmd *cmd);
179179
int target_get_sess_cmd(struct se_cmd *, bool);
180180
int target_put_sess_cmd(struct se_cmd *);
181-
void target_sess_cmd_list_set_waiting(struct se_session *);
181+
void target_stop_session(struct se_session *se_sess);
182182
void target_wait_for_sess_cmds(struct se_session *);
183183
void target_show_cmd(const char *pfx, struct se_cmd *cmd);
184184

0 commit comments

Comments
 (0)