@@ -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);
239240void 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)
27632763EXPORT_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 */
27702770int 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}
29532938EXPORT_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 */
29752964void 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}
29912980EXPORT_SYMBOL (target_wait_for_sess_cmds );
29922981
0 commit comments