Skip to content

Commit becd9be

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: target: Move sess cmd counter to new struct
iSCSI needs to wait on outstanding commands like how SRP and the FC/FCoE drivers do. It can't use target_stop_session() because for MCS support we can't stop the entire session during recovery because if other connections are OK then we want to be able to continue to execute I/O on them. Move the per session cmd counters to a new struct so iSCSI can allocate them per connection. The xcopy code can also just not allocate in the future since it doesn't need to track commands. Signed-off-by: Mike Christie <michael.christie@oracle.com> Link: https://lore.kernel.org/r/20230319015620.96006-2-michael.christie@oracle.com Reviewed-by: Maurizio Lombardi <mlombard@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent fe15c26 commit becd9be

File tree

4 files changed

+107
-44
lines changed

4 files changed

+107
-44
lines changed

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 (atomic_read(&sess->stopped))
331+
if (sess->cmd_cnt && atomic_read(&sess->cmd_cnt->stopped))
332332
continue;
333333

334334
list_del_init(&sess->sess_acl_list);

drivers/target/target_core_transport.c

Lines changed: 96 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,49 @@ void transport_subsystem_check_init(void)
220220
sub_api_initialized = 1;
221221
}
222222

223-
static void target_release_sess_cmd_refcnt(struct percpu_ref *ref)
223+
static void target_release_cmd_refcnt(struct percpu_ref *ref)
224224
{
225-
struct se_session *sess = container_of(ref, typeof(*sess), cmd_count);
225+
struct target_cmd_counter *cmd_cnt = container_of(ref,
226+
typeof(*cmd_cnt),
227+
refcnt);
228+
wake_up(&cmd_cnt->refcnt_wq);
229+
}
230+
231+
static struct target_cmd_counter *target_alloc_cmd_counter(void)
232+
{
233+
struct target_cmd_counter *cmd_cnt;
234+
int rc;
235+
236+
cmd_cnt = kzalloc(sizeof(*cmd_cnt), GFP_KERNEL);
237+
if (!cmd_cnt)
238+
return NULL;
226239

227-
wake_up(&sess->cmd_count_wq);
240+
init_completion(&cmd_cnt->stop_done);
241+
init_waitqueue_head(&cmd_cnt->refcnt_wq);
242+
atomic_set(&cmd_cnt->stopped, 0);
243+
244+
rc = percpu_ref_init(&cmd_cnt->refcnt, target_release_cmd_refcnt, 0,
245+
GFP_KERNEL);
246+
if (rc)
247+
goto free_cmd_cnt;
248+
249+
return cmd_cnt;
250+
251+
free_cmd_cnt:
252+
kfree(cmd_cnt);
253+
return NULL;
254+
}
255+
256+
static void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt)
257+
{
258+
/*
259+
* Drivers like loop do not call target_stop_session during session
260+
* shutdown so we have to drop the ref taken at init time here.
261+
*/
262+
if (!atomic_read(&cmd_cnt->stopped))
263+
percpu_ref_put(&cmd_cnt->refcnt);
264+
265+
percpu_ref_exit(&cmd_cnt->refcnt);
228266
}
229267

230268
/**
@@ -238,25 +276,17 @@ int transport_init_session(struct se_session *se_sess)
238276
INIT_LIST_HEAD(&se_sess->sess_list);
239277
INIT_LIST_HEAD(&se_sess->sess_acl_list);
240278
spin_lock_init(&se_sess->sess_cmd_lock);
241-
init_waitqueue_head(&se_sess->cmd_count_wq);
242-
init_completion(&se_sess->stop_done);
243-
atomic_set(&se_sess->stopped, 0);
244-
return percpu_ref_init(&se_sess->cmd_count,
245-
target_release_sess_cmd_refcnt, 0, GFP_KERNEL);
279+
se_sess->cmd_cnt = target_alloc_cmd_counter();
280+
if (!se_sess->cmd_cnt)
281+
return -ENOMEM;
282+
283+
return 0;
246284
}
247285
EXPORT_SYMBOL(transport_init_session);
248286

249287
void transport_uninit_session(struct se_session *se_sess)
250288
{
251-
/*
252-
* Drivers like iscsi and loop do not call target_stop_session
253-
* during session shutdown so we have to drop the ref taken at init
254-
* time here.
255-
*/
256-
if (!atomic_read(&se_sess->stopped))
257-
percpu_ref_put(&se_sess->cmd_count);
258-
259-
percpu_ref_exit(&se_sess->cmd_count);
289+
target_free_cmd_counter(se_sess->cmd_cnt);
260290
}
261291

262292
/**
@@ -2970,9 +3000,16 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
29703000
se_cmd->se_cmd_flags |= SCF_ACK_KREF;
29713001
}
29723002

2973-
if (!percpu_ref_tryget_live(&se_sess->cmd_count))
2974-
ret = -ESHUTDOWN;
2975-
3003+
/*
3004+
* Users like xcopy do not use counters since they never do a stop
3005+
* and wait.
3006+
*/
3007+
if (se_sess->cmd_cnt) {
3008+
if (!percpu_ref_tryget_live(&se_sess->cmd_cnt->refcnt))
3009+
ret = -ESHUTDOWN;
3010+
else
3011+
se_cmd->cmd_cnt = se_sess->cmd_cnt;
3012+
}
29763013
if (ret && ack_kref)
29773014
target_put_sess_cmd(se_cmd);
29783015

@@ -2993,7 +3030,7 @@ static void target_free_cmd_mem(struct se_cmd *cmd)
29933030
static void target_release_cmd_kref(struct kref *kref)
29943031
{
29953032
struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
2996-
struct se_session *se_sess = se_cmd->se_sess;
3033+
struct target_cmd_counter *cmd_cnt = se_cmd->cmd_cnt;
29973034
struct completion *free_compl = se_cmd->free_compl;
29983035
struct completion *abrt_compl = se_cmd->abrt_compl;
29993036

@@ -3004,7 +3041,8 @@ static void target_release_cmd_kref(struct kref *kref)
30043041
if (abrt_compl)
30053042
complete(abrt_compl);
30063043

3007-
percpu_ref_put(&se_sess->cmd_count);
3044+
if (cmd_cnt)
3045+
percpu_ref_put(&cmd_cnt->refcnt);
30083046
}
30093047

30103048
/**
@@ -3123,46 +3161,65 @@ void target_show_cmd(const char *pfx, struct se_cmd *cmd)
31233161
}
31243162
EXPORT_SYMBOL(target_show_cmd);
31253163

3126-
static void target_stop_session_confirm(struct percpu_ref *ref)
3164+
static void target_stop_cmd_counter_confirm(struct percpu_ref *ref)
3165+
{
3166+
struct target_cmd_counter *cmd_cnt = container_of(ref,
3167+
struct target_cmd_counter,
3168+
refcnt);
3169+
complete_all(&cmd_cnt->stop_done);
3170+
}
3171+
3172+
/**
3173+
* target_stop_cmd_counter - Stop new IO from being added to the counter.
3174+
* @cmd_cnt: counter to stop
3175+
*/
3176+
static void target_stop_cmd_counter(struct target_cmd_counter *cmd_cnt)
31273177
{
3128-
struct se_session *se_sess = container_of(ref, struct se_session,
3129-
cmd_count);
3130-
complete_all(&se_sess->stop_done);
3178+
pr_debug("Stopping command counter.\n");
3179+
if (!atomic_cmpxchg(&cmd_cnt->stopped, 0, 1))
3180+
percpu_ref_kill_and_confirm(&cmd_cnt->refcnt,
3181+
target_stop_cmd_counter_confirm);
31313182
}
31323183

31333184
/**
31343185
* target_stop_session - Stop new IO from being queued on the session.
3135-
* @se_sess: session to stop
3186+
* @se_sess: session to stop
31363187
*/
31373188
void target_stop_session(struct se_session *se_sess)
31383189
{
3139-
pr_debug("Stopping session queue.\n");
3140-
if (atomic_cmpxchg(&se_sess->stopped, 0, 1) == 0)
3141-
percpu_ref_kill_and_confirm(&se_sess->cmd_count,
3142-
target_stop_session_confirm);
3190+
target_stop_cmd_counter(se_sess->cmd_cnt);
31433191
}
31443192
EXPORT_SYMBOL(target_stop_session);
31453193

31463194
/**
3147-
* target_wait_for_sess_cmds - Wait for outstanding commands
3148-
* @se_sess: session to wait for active I/O
3195+
* target_wait_for_cmds - Wait for outstanding cmds.
3196+
* @cmd_cnt: counter to wait for active I/O for.
31493197
*/
3150-
void target_wait_for_sess_cmds(struct se_session *se_sess)
3198+
static void target_wait_for_cmds(struct target_cmd_counter *cmd_cnt)
31513199
{
31523200
int ret;
31533201

3154-
WARN_ON_ONCE(!atomic_read(&se_sess->stopped));
3202+
WARN_ON_ONCE(!atomic_read(&cmd_cnt->stopped));
31553203

31563204
do {
31573205
pr_debug("Waiting for running cmds to complete.\n");
3158-
ret = wait_event_timeout(se_sess->cmd_count_wq,
3159-
percpu_ref_is_zero(&se_sess->cmd_count),
3160-
180 * HZ);
3206+
ret = wait_event_timeout(cmd_cnt->refcnt_wq,
3207+
percpu_ref_is_zero(&cmd_cnt->refcnt),
3208+
180 * HZ);
31613209
} while (ret <= 0);
31623210

3163-
wait_for_completion(&se_sess->stop_done);
3211+
wait_for_completion(&cmd_cnt->stop_done);
31643212
pr_debug("Waiting for cmds done.\n");
31653213
}
3214+
3215+
/**
3216+
* target_wait_for_sess_cmds - Wait for outstanding commands
3217+
* @se_sess: session to wait for active I/O
3218+
*/
3219+
void target_wait_for_sess_cmds(struct se_session *se_sess)
3220+
{
3221+
target_wait_for_cmds(se_sess->cmd_cnt);
3222+
}
31663223
EXPORT_SYMBOL(target_wait_for_sess_cmds);
31673224

31683225
/*

include/target/iscsi/iscsi_target_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ struct iscsit_conn {
600600
struct iscsi_tpg_np *tpg_np;
601601
/* Pointer to parent session */
602602
struct iscsit_session *sess;
603+
struct target_cmd_counter *cmd_cnt;
603604
int bitmap_id;
604605
int rx_thread_active;
605606
struct task_struct *rx_thread;

include/target/target_core_base.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ struct se_cmd {
494494
struct se_lun *se_lun;
495495
/* Only used for internal passthrough and legacy TCM fabric modules */
496496
struct se_session *se_sess;
497+
struct target_cmd_counter *cmd_cnt;
497498
struct se_tmr_req *se_tmr_req;
498499
struct llist_node se_cmd_list;
499500
struct completion *free_compl;
@@ -619,22 +620,26 @@ static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item)
619620
acl_fabric_stat_group);
620621
}
621622

622-
struct se_session {
623+
struct target_cmd_counter {
624+
struct percpu_ref refcnt;
625+
wait_queue_head_t refcnt_wq;
626+
struct completion stop_done;
623627
atomic_t stopped;
628+
};
629+
630+
struct se_session {
624631
u64 sess_bin_isid;
625632
enum target_prot_op sup_prot_ops;
626633
enum target_prot_type sess_prot_type;
627634
struct se_node_acl *se_node_acl;
628635
struct se_portal_group *se_tpg;
629636
void *fabric_sess_ptr;
630-
struct percpu_ref cmd_count;
631637
struct list_head sess_list;
632638
struct list_head sess_acl_list;
633639
spinlock_t sess_cmd_lock;
634-
wait_queue_head_t cmd_count_wq;
635-
struct completion stop_done;
636640
void *sess_cmd_map;
637641
struct sbitmap_queue sess_tag_pool;
642+
struct target_cmd_counter *cmd_cnt;
638643
};
639644

640645
struct se_device;

0 commit comments

Comments
 (0)