@@ -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}
247285EXPORT_SYMBOL (transport_init_session );
248286
249287void 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)
29933030static 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}
31243162EXPORT_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 */
31373188void 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}
31443192EXPORT_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+ }
31663223EXPORT_SYMBOL (target_wait_for_sess_cmds );
31673224
31683225/*
0 commit comments