History

Merge patch series "target: TMF and recovery fixes"

Mike Christie <michael.christie@oracle.com> says: The following patches apply over Martin's 6.4 branches and Linus's tree. They fix a couple regressions in iscsit that occur when there are TMRs executing and a connection is closed. It also includes Dimitry's fixes in related code paths for cmd cleanup when ERL2 is used and the write pending hang during conn cleanup. This version of the patchset brings it back to just regressions and fixes for bugs we have a lot of users hitting. I'm going to fix isert and get it hooked into iscsit properly in a second patchset, because this one was getting so large. I've also moved my cleanup type of patches for a 3rd patchset.

Martin K. Petersen committed 3 years ago

Commit ae2fb3c2 parents 5c8c74e ea8798113 files · +230 −118Browse files

Unified · Split

13 files
  1. drivers/infiniband/ulp/isert/ib_isert.c +2 −2
  2. drivers/target/iscsi/iscsi_target.c +38 −13
  3. drivers/target/iscsi/iscsi_target_login.c +7 −0
  4. drivers/target/target_core_device.c +1 −0
  5. drivers/target/target_core_internal.h +0 −1
  6. drivers/target/target_core_tmr.c +23 −3
  7. drivers/target/target_core_tpg.c +1 −1
  8. drivers/target/target_core_transport.c +128 −71
  9. drivers/target/target_core_xcopy.c +6 −17
  10. drivers/usb/gadget/function/f_tcm.c +2 −2
  11. include/target/iscsi/iscsi_target_core.h +1 −0
  12. include/target/target_core_base.h +10 −4
  13. include/target/target_core_fabric.h +11 −4
drivers/infiniband/ulp/isert/ib_isert.c+2−2
@@ -2506,8 +2506,8 @@ isert_wait4cmds(struct iscsit_conn *conn) · 2505 unmodified lines
2506 isert_info("iscsit_conn %p\n", conn);2506 isert_info("iscsit_conn %p\n", conn);
2507 2507
2508 if (conn->sess) {2508 if (conn->sess) {
2509 target_stop_session(conn->sess->se_sess);2509 target_stop_cmd_counter(conn->cmd_cnt);
2510 target_wait_for_sess_cmds(conn->sess->se_sess);2510 target_wait_for_cmds(conn->cmd_cnt);
2511 }2511 }
2512}2512}
2513 2513
drivers/target/iscsi/iscsi_target.c+38−13
@@ -26,6 +26,7 @@ · 25 unmodified lines
26#include <target/target_core_base.h>26#include <target/target_core_base.h>
27#include <target/target_core_fabric.h>27#include <target/target_core_fabric.h>
28 28
29#include <target/target_core_backend.h>
29#include <target/iscsi/iscsi_target_core.h>30#include <target/iscsi/iscsi_target_core.h>
30#include "iscsi_target_parameters.h"31#include "iscsi_target_parameters.h"
31#include "iscsi_target_seq_pdu_list.h"32#include "iscsi_target_seq_pdu_list.h"
@@ -1190,9 +1191,10 @@ int iscsit_setup_scsi_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, · 1158 unmodified lines
1190 * Initialize struct se_cmd descriptor from target_core_mod infrastructure1191 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
1191 */1192 */
1192 __target_init_cmd(&cmd->se_cmd, &iscsi_ops,1193 __target_init_cmd(&cmd->se_cmd, &iscsi_ops,
1193 conn->sess->se_sess, be32_to_cpu(hdr->data_length),1194 conn->sess->se_sess, be32_to_cpu(hdr->data_length),
1194 cmd->data_direction, sam_task_attr,1195 cmd->data_direction, sam_task_attr,
1195 cmd->sense_buffer + 2, scsilun_to_int(&hdr->lun));1196 cmd->sense_buffer + 2, scsilun_to_int(&hdr->lun),
1197 conn->cmd_cnt);
1196 1198
1197 pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"1199 pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
1198 " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,1200 " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
@@ -2055,7 +2057,8 @@ iscsit_handle_task_mgt_cmd(struct iscsit_conn *conn, struct iscsit_cmd *cmd, · 856 unmodified lines
2055 __target_init_cmd(&cmd->se_cmd, &iscsi_ops,2057 __target_init_cmd(&cmd->se_cmd, &iscsi_ops,
2056 conn->sess->se_sess, 0, DMA_NONE,2058 conn->sess->se_sess, 0, DMA_NONE,
2057 TCM_SIMPLE_TAG, cmd->sense_buffer + 2,2059 TCM_SIMPLE_TAG, cmd->sense_buffer + 2,
2058 scsilun_to_int(&hdr->lun));2060 scsilun_to_int(&hdr->lun),
2061 conn->cmd_cnt);
2059 2062
2060 target_get_sess_cmd(&cmd->se_cmd, true);2063 target_get_sess_cmd(&cmd->se_cmd, true);
2061 2064
@@ -4218,9 +4221,12 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn) · 2156 unmodified lines
4218 list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {4221 list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
4219 struct se_cmd *se_cmd = &cmd->se_cmd;4222 struct se_cmd *se_cmd = &cmd->se_cmd;
4220 4223
4221 if (se_cmd->se_tfo != NULL) {4224 if (!se_cmd->se_tfo)
4222 spin_lock_irq(&se_cmd->t_state_lock);4225 continue;
4223 if (se_cmd->transport_state & CMD_T_ABORTED) {4226
4227 spin_lock_irq(&se_cmd->t_state_lock);
4228 if (se_cmd->transport_state & CMD_T_ABORTED) {
4229 if (!(se_cmd->transport_state & CMD_T_TAS))
4224 /*4230 /*
4225 * LIO's abort path owns the cleanup for this,4231 * LIO's abort path owns the cleanup for this,
4226 * so put it back on the list and let4232 * so put it back on the list and let
@@ -4228,11 +4234,20 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn) · 1 unmodified line
4228 */4234 */
4229 list_move_tail(&cmd->i_conn_node,4235 list_move_tail(&cmd->i_conn_node,
4230 &conn->conn_cmd_list);4236 &conn->conn_cmd_list);
4231 } else {4237 } else {
4232 se_cmd->transport_state |= CMD_T_FABRIC_STOP;4238 se_cmd->transport_state |= CMD_T_FABRIC_STOP;
4233 }4239 }
4240
4241 if (cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
4242 /*
4243 * We never submitted the cmd to LIO core, so we have
4244 * to tell LIO to perform the completion process.
4245 */
4234 spin_unlock_irq(&se_cmd->t_state_lock);4246 spin_unlock_irq(&se_cmd->t_state_lock);
4247 target_complete_cmd(&cmd->se_cmd, SAM_STAT_TASK_ABORTED);
4248 continue;
4235 }4249 }
4250 spin_unlock_irq(&se_cmd->t_state_lock);
4236 }4251 }
4237 spin_unlock_bh(&conn->cmd_lock);4252 spin_unlock_bh(&conn->cmd_lock);
4238 4253
@@ -4243,6 +4258,16 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn) · 4 unmodified lines
4243 iscsit_free_cmd(cmd, true);4258 iscsit_free_cmd(cmd, true);
4244 4259
4245 }4260 }
4261
4262 /*
4263 * Wait on commands that were cleaned up via the aborted_task path.
4264 * LLDs that implement iscsit_wait_conn will already have waited for
4265 * commands.
4266 */
4267 if (!conn->conn_transport->iscsit_wait_conn) {
4268 target_stop_cmd_counter(conn->cmd_cnt);
4269 target_wait_for_cmds(conn->cmd_cnt);
4270 }
4246}4271}
4247 4272
4248static void iscsit_stop_timers_for_cmds(4273static void iscsit_stop_timers_for_cmds(
@@ -4517,6 +4542,9 @@ int iscsit_close_session(struct iscsit_session *sess, bool can_sleep) · 268 unmodified lines
4517 iscsit_stop_time2retain_timer(sess);4542 iscsit_stop_time2retain_timer(sess);
4518 spin_unlock_bh(&se_tpg->session_lock);4543 spin_unlock_bh(&se_tpg->session_lock);
4519 4544
4545 if (sess->sess_ops->ErrorRecoveryLevel == 2)
4546 iscsit_free_connection_recovery_entries(sess);
4547
4520 /*4548 /*
4521 * transport_deregister_session_configfs() will clear the4549 * transport_deregister_session_configfs() will clear the
4522 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context4550 * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context
@@ -4540,9 +4568,6 @@ int iscsit_close_session(struct iscsit_session *sess, bool can_sleep) · 17 unmodified lines
4540 4568
4541 transport_deregister_session(sess->se_sess);4569 transport_deregister_session(sess->se_sess);
4542 4570
4543 if (sess->sess_ops->ErrorRecoveryLevel == 2)
4544 iscsit_free_connection_recovery_entries(sess);
4545
4546 iscsit_free_all_ooo_cmdsns(sess);4571 iscsit_free_all_ooo_cmdsns(sess);
4547 4572
4548 spin_lock_bh(&se_tpg->session_lock);4573 spin_lock_bh(&se_tpg->session_lock);
drivers/target/iscsi/iscsi_target_login.c+7−0
@@ -1147,8 +1147,14 @@ static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np) · 1146 unmodified lines
1147 goto free_conn_cpumask;1147 goto free_conn_cpumask;
1148 }1148 }
1149 1149
1150 conn->cmd_cnt = target_alloc_cmd_counter();
1151 if (!conn->cmd_cnt)
1152 goto free_conn_allowed_cpumask;
1153
1150 return conn;1154 return conn;
1151 1155
1156free_conn_allowed_cpumask:
1157 free_cpumask_var(conn->allowed_cpumask);
1152free_conn_cpumask:1158free_conn_cpumask:
1153 free_cpumask_var(conn->conn_cpumask);1159 free_cpumask_var(conn->conn_cpumask);
1154free_conn_ops:1160free_conn_ops:
@@ -1162,6 +1168,7 @@ free_conn: · 7 unmodified lines
1162 1168
1163void iscsit_free_conn(struct iscsit_conn *conn)1169void iscsit_free_conn(struct iscsit_conn *conn)
1164{1170{
1171 target_free_cmd_counter(conn->cmd_cnt);
1165 free_cpumask_var(conn->allowed_cpumask);1172 free_cpumask_var(conn->allowed_cpumask);
1166 free_cpumask_var(conn->conn_cpumask);1173 free_cpumask_var(conn->conn_cpumask);
1167 kfree(conn->conn_ops);1174 kfree(conn->conn_ops);
drivers/target/target_core_device.c+1−0
@@ -741,6 +741,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) · 740 unmodified lines
741 spin_lock_init(&dev->t10_alua.lba_map_lock);741 spin_lock_init(&dev->t10_alua.lba_map_lock);
742 742
743 INIT_WORK(&dev->delayed_cmd_work, target_do_delayed_work);743 INIT_WORK(&dev->delayed_cmd_work, target_do_delayed_work);
744 mutex_init(&dev->lun_reset_mutex);
744 745
745 dev->t10_wwn.t10_dev = dev;746 dev->t10_wwn.t10_dev = dev;
746 /*747 /*
drivers/target/target_core_internal.h+0−1
@@ -139,7 +139,6 @@ int init_se_kmem_caches(void); · 138 unmodified lines
139void release_se_kmem_caches(void);139void release_se_kmem_caches(void);
140u32 scsi_get_new_index(scsi_index_t);140u32 scsi_get_new_index(scsi_index_t);
141void transport_subsystem_check_init(void);141void transport_subsystem_check_init(void);
142void transport_uninit_session(struct se_session *);
143unsigned char *transport_dump_cmd_direction(struct se_cmd *);142unsigned char *transport_dump_cmd_direction(struct se_cmd *);
144void transport_dump_dev_state(struct se_device *, char *, int *);143void transport_dump_dev_state(struct se_device *, char *, int *);
145void transport_dump_dev_info(struct se_device *, struct se_lun *,144void transport_dump_dev_info(struct se_device *, struct se_lun *,
drivers/target/target_core_tmr.c+23−3
@@ -188,14 +188,23 @@ static void core_tmr_drain_tmr_list( · 187 unmodified lines
188 * LUN_RESET tmr..188 * LUN_RESET tmr..
189 */189 */
190 spin_lock_irqsave(&dev->se_tmr_lock, flags);190 spin_lock_irqsave(&dev->se_tmr_lock, flags);
191 if (tmr)
192 list_del_init(&tmr->tmr_list);
193 list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {191 list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
192 if (tmr_p == tmr)
193 continue;
194
194 cmd = tmr_p->task_cmd;195 cmd = tmr_p->task_cmd;
195 if (!cmd) {196 if (!cmd) {
196 pr_err("Unable to locate struct se_cmd for TMR\n");197 pr_err("Unable to locate struct se_cmd for TMR\n");
197 continue;198 continue;
198 }199 }
200
201 /*
202 * We only execute one LUN_RESET at a time so we can't wait
203 * on them below.
204 */
205 if (tmr_p->function == TMR_LUN_RESET)
206 continue;
207
199 /*208 /*
200 * If this function was called with a valid pr_res_key209 * If this function was called with a valid pr_res_key
201 * parameter (eg: for PROUT PREEMPT_AND_ABORT service action210 * parameter (eg: for PROUT PREEMPT_AND_ABORT service action
@@ -379,14 +388,25 @@ int core_tmr_lun_reset( · 177 unmodified lines
379 tmr_nacl->initiatorname);388 tmr_nacl->initiatorname);
380 }389 }
381 }390 }
391
392
393 /*
394 * We only allow one reset or preempt and abort to execute at a time
395 * to prevent one call from claiming all the cmds causing a second
396 * call from returning while cmds it should have waited on are still
397 * running.
398 */
399 mutex_lock(&dev->lun_reset_mutex);
400
382 pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",401 pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
383 (preempt_and_abort_list) ? "Preempt" : "TMR",402 (preempt_and_abort_list) ? "Preempt" : "TMR",
384 dev->transport->name, tas);403 dev->transport->name, tas);
385
386 core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);404 core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
387 core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas,405 core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas,
388 preempt_and_abort_list);406 preempt_and_abort_list);
389 407
408 mutex_unlock(&dev->lun_reset_mutex);
409
390 /*410 /*
391 * Clear any legacy SPC-2 reservation when called during411 * Clear any legacy SPC-2 reservation when called during
392 * LOGICAL UNIT RESET412 * LOGICAL UNIT RESET
drivers/target/target_core_tpg.c+1−1
@@ -329,7 +329,7 @@ static void target_shutdown_sessions(struct se_node_acl *acl) · 328 unmodified lines
329restart:329restart:
330 spin_lock_irqsave(&acl->nacl_sess_lock, flags);330 spin_lock_irqsave(&acl->nacl_sess_lock, flags);
331 list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) {331 list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) {
332 if (atomic_read(&sess->stopped))332 if (sess->cmd_cnt && atomic_read(&sess->cmd_cnt->stopped))
333 continue;333 continue;
334 334
335 list_del_init(&sess->sess_acl_list);335 list_del_init(&sess->sess_acl_list);
drivers/target/target_core_transport.c+128−71
@@ -220,12 +220,52 @@ void transport_subsystem_check_init(void) · 219 unmodified lines
220 sub_api_initialized = 1;220 sub_api_initialized = 1;
221}221}
222 222
223static void target_release_sess_cmd_refcnt(struct percpu_ref *ref)223static void target_release_cmd_refcnt(struct percpu_ref *ref)
224{224{
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
231struct 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;
239
240 init_completion(&cmd_cnt->stop_done);
241 init_waitqueue_head(&cmd_cnt->refcnt_wq);
242 atomic_set(&cmd_cnt->stopped, 0);
226 243
227 wake_up(&sess->cmd_count_wq);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
251free_cmd_cnt:
252 kfree(cmd_cnt);
253 return NULL;
228}254}
255EXPORT_SYMBOL_GPL(target_alloc_cmd_counter);
256
257void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt)
258{
259 /*
260 * Drivers like loop do not call target_stop_session during session
261 * shutdown so we have to drop the ref taken at init time here.
262 */
263 if (!atomic_read(&cmd_cnt->stopped))
264 percpu_ref_put(&cmd_cnt->refcnt);
265
266 percpu_ref_exit(&cmd_cnt->refcnt);
267}
268EXPORT_SYMBOL_GPL(target_free_cmd_counter);
229 269
230/**270/**
231 * transport_init_session - initialize a session object271 * transport_init_session - initialize a session object
@@ -233,32 +273,14 @@ static void target_release_sess_cmd_refcnt(struct percpu_ref *ref) · 1 unmodified line
233 *273 *
234 * The caller must have zero-initialized @se_sess before calling this function.274 * The caller must have zero-initialized @se_sess before calling this function.
235 */275 */
236int transport_init_session(struct se_session *se_sess)276void transport_init_session(struct se_session *se_sess)
237{277{
238 INIT_LIST_HEAD(&se_sess->sess_list);278 INIT_LIST_HEAD(&se_sess->sess_list);
239 INIT_LIST_HEAD(&se_sess->sess_acl_list);279 INIT_LIST_HEAD(&se_sess->sess_acl_list);
240 spin_lock_init(&se_sess->sess_cmd_lock);280 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);
246}281}
247EXPORT_SYMBOL(transport_init_session);282EXPORT_SYMBOL(transport_init_session);
248 283
249void transport_uninit_session(struct se_session *se_sess)
250{
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);
260}
261
262/**284/**
263 * transport_alloc_session - allocate a session object and initialize it285 * transport_alloc_session - allocate a session object and initialize it
264 * @sup_prot_ops: bitmask that defines which T10-PI modes are supported.286 * @sup_prot_ops: bitmask that defines which T10-PI modes are supported.
@@ -266,7 +288,6 @@ void transport_uninit_session(struct se_session *se_sess) · 1 unmodified line
266struct se_session *transport_alloc_session(enum target_prot_op sup_prot_ops)288struct se_session *transport_alloc_session(enum target_prot_op sup_prot_ops)
267{289{
268 struct se_session *se_sess;290 struct se_session *se_sess;
269 int ret;
270 291
271 se_sess = kmem_cache_zalloc(se_sess_cache, GFP_KERNEL);292 se_sess = kmem_cache_zalloc(se_sess_cache, GFP_KERNEL);
272 if (!se_sess) {293 if (!se_sess) {
@@ -274,11 +295,7 @@ struct se_session *transport_alloc_session(enum target_prot_op sup_prot_ops) · 1 unmodified line
274 " se_sess_cache\n");295 " se_sess_cache\n");
275 return ERR_PTR(-ENOMEM);296 return ERR_PTR(-ENOMEM);
276 }297 }
277 ret = transport_init_session(se_sess);298 transport_init_session(se_sess);
278 if (ret < 0) {
279 kmem_cache_free(se_sess_cache, se_sess);
280 return ERR_PTR(ret);
281 }
282 se_sess->sup_prot_ops = sup_prot_ops;299 se_sess->sup_prot_ops = sup_prot_ops;
283 300
284 return se_sess;301 return se_sess;
@@ -444,8 +461,13 @@ target_setup_session(struct se_portal_group *tpg, · 159 unmodified lines
444 int (*callback)(struct se_portal_group *,461 int (*callback)(struct se_portal_group *,
445 struct se_session *, void *))462 struct se_session *, void *))
446{463{
464 struct target_cmd_counter *cmd_cnt;
447 struct se_session *sess;465 struct se_session *sess;
466 int rc;
448 467
468 cmd_cnt = target_alloc_cmd_counter();
469 if (!cmd_cnt)
470 return ERR_PTR(-ENOMEM);
449 /*471 /*
450 * If the fabric driver is using percpu-ida based pre allocation472 * If the fabric driver is using percpu-ida based pre allocation
451 * of I/O descriptor tags, go ahead and perform that setup now..473 * of I/O descriptor tags, go ahead and perform that setup now..
@@ -455,29 +477,36 @@ target_setup_session(struct se_portal_group *tpg, · 3 unmodified lines
455 else477 else
456 sess = transport_alloc_session(prot_op);478 sess = transport_alloc_session(prot_op);
457 479
458 if (IS_ERR(sess))480 if (IS_ERR(sess)) {
459 return sess;481 rc = PTR_ERR(sess);
482 goto free_cnt;
483 }
484 sess->cmd_cnt = cmd_cnt;
460 485
461 sess->se_node_acl = core_tpg_check_initiator_node_acl(tpg,486 sess->se_node_acl = core_tpg_check_initiator_node_acl(tpg,
462 (unsigned char *)initiatorname);487 (unsigned char *)initiatorname);
463 if (!sess->se_node_acl) {488 if (!sess->se_node_acl) {
464 transport_free_session(sess);489 rc = -EACCES;
465 return ERR_PTR(-EACCES);490 goto free_sess;
466 }491 }
467 /*492 /*
468 * Go ahead and perform any remaining fabric setup that is493 * Go ahead and perform any remaining fabric setup that is
469 * required before transport_register_session().494 * required before transport_register_session().
470 */495 */
471 if (callback != NULL) {496 if (callback != NULL) {
472 int rc = callback(tpg, sess, private);497 rc = callback(tpg, sess, private);
473 if (rc) {498 if (rc)
474 transport_free_session(sess);499 goto free_sess;
475 return ERR_PTR(rc);
476 }
477 }500 }
478 501
479 transport_register_session(tpg, sess->se_node_acl, sess, private);502 transport_register_session(tpg, sess->se_node_acl, sess, private);
480 return sess;503 return sess;
504
505free_sess:
506 transport_free_session(sess);
507free_cnt:
508 target_free_cmd_counter(cmd_cnt);
509 return ERR_PTR(rc);
481}510}
482EXPORT_SYMBOL(target_setup_session);511EXPORT_SYMBOL(target_setup_session);
483 512
@@ -602,7 +631,8 @@ void transport_free_session(struct se_session *se_sess) · 118 unmodified lines
602 sbitmap_queue_free(&se_sess->sess_tag_pool);631 sbitmap_queue_free(&se_sess->sess_tag_pool);
603 kvfree(se_sess->sess_cmd_map);632 kvfree(se_sess->sess_cmd_map);
604 }633 }
605 transport_uninit_session(se_sess);634 if (se_sess->cmd_cnt)
635 target_free_cmd_counter(se_sess->cmd_cnt);
606 kmem_cache_free(se_sess_cache, se_sess);636 kmem_cache_free(se_sess_cache, se_sess);
607}637}
608EXPORT_SYMBOL(transport_free_session);638EXPORT_SYMBOL(transport_free_session);
@@ -1412,14 +1442,12 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size) · 803 unmodified lines
1412 *1442 *
1413 * Preserves the value of @cmd->tag.1443 * Preserves the value of @cmd->tag.
1414 */1444 */
1415void __target_init_cmd(1445void __target_init_cmd(struct se_cmd *cmd,
1416 struct se_cmd *cmd,1446 const struct target_core_fabric_ops *tfo,
1417 const struct target_core_fabric_ops *tfo,1447 struct se_session *se_sess, u32 data_length,
1418 struct se_session *se_sess,1448 int data_direction, int task_attr,
1419 u32 data_length,1449 unsigned char *sense_buffer, u64 unpacked_lun,
1420 int data_direction,1450 struct target_cmd_counter *cmd_cnt)
1421 int task_attr,
1422 unsigned char *sense_buffer, u64 unpacked_lun)
1423{1451{
1424 INIT_LIST_HEAD(&cmd->se_delayed_node);1452 INIT_LIST_HEAD(&cmd->se_delayed_node);
1425 INIT_LIST_HEAD(&cmd->se_qf_node);1453 INIT_LIST_HEAD(&cmd->se_qf_node);
@@ -1439,6 +1467,7 @@ void __target_init_cmd( · 13 unmodified lines
1439 cmd->sam_task_attr = task_attr;1467 cmd->sam_task_attr = task_attr;
1440 cmd->sense_buffer = sense_buffer;1468 cmd->sense_buffer = sense_buffer;
1441 cmd->orig_fe_lun = unpacked_lun;1469 cmd->orig_fe_lun = unpacked_lun;
1470 cmd->cmd_cnt = cmd_cnt;
1442 1471
1443 if (!(cmd->se_cmd_flags & SCF_USE_CPUID))1472 if (!(cmd->se_cmd_flags & SCF_USE_CPUID))
1444 cmd->cpuid = raw_smp_processor_id();1473 cmd->cpuid = raw_smp_processor_id();
@@ -1658,7 +1687,8 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, · 213 unmodified lines
1658 * target_core_fabric_ops->queue_status() callback1687 * target_core_fabric_ops->queue_status() callback
1659 */1688 */
1660 __target_init_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, data_length,1689 __target_init_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, data_length,
1661 data_dir, task_attr, sense, unpacked_lun);1690 data_dir, task_attr, sense, unpacked_lun,
1691 se_sess->cmd_cnt);
1662 1692
1663 /*1693 /*
1664 * Obtain struct se_cmd->cmd_kref reference. A second kref_get here is1694 * Obtain struct se_cmd->cmd_kref reference. A second kref_get here is
@@ -1953,7 +1983,8 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, · 288 unmodified lines
1953 BUG_ON(!se_tpg);1983 BUG_ON(!se_tpg);
1954 1984
1955 __target_init_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,1985 __target_init_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
1956 0, DMA_NONE, TCM_SIMPLE_TAG, sense, unpacked_lun);1986 0, DMA_NONE, TCM_SIMPLE_TAG, sense, unpacked_lun,
1987 se_sess->cmd_cnt);
1957 /*1988 /*
1958 * FIXME: Currently expect caller to handle se_cmd->se_tmr_req1989 * FIXME: Currently expect caller to handle se_cmd->se_tmr_req
1959 * allocation failure.1990 * allocation failure.
@@ -2957,7 +2988,6 @@ EXPORT_SYMBOL(transport_generic_free_cmd); · 997 unmodified lines
2957 */2988 */
2958int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)2989int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
2959{2990{
2960 struct se_session *se_sess = se_cmd->se_sess;
2961 int ret = 0;2991 int ret = 0;
2962 2992
2963 /*2993 /*
@@ -2970,9 +3000,14 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) · 6 unmodified lines
2970 se_cmd->se_cmd_flags |= SCF_ACK_KREF;3000 se_cmd->se_cmd_flags |= SCF_ACK_KREF;
2971 }3001 }
2972 3002
2973 if (!percpu_ref_tryget_live(&se_sess->cmd_count))3003 /*
2974 ret = -ESHUTDOWN;3004 * Users like xcopy do not use counters since they never do a stop
2975 3005 * and wait.
3006 */
3007 if (se_cmd->cmd_cnt) {
3008 if (!percpu_ref_tryget_live(&se_cmd->cmd_cnt->refcnt))
3009 ret = -ESHUTDOWN;
3010 }
2976 if (ret && ack_kref)3011 if (ret && ack_kref)
2977 target_put_sess_cmd(se_cmd);3012 target_put_sess_cmd(se_cmd);
2978 3013
@@ -2993,7 +3028,7 @@ static void target_free_cmd_mem(struct se_cmd *cmd) · 14 unmodified lines
2993static void target_release_cmd_kref(struct kref *kref)3028static void target_release_cmd_kref(struct kref *kref)
2994{3029{
2995 struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);3030 struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
2996 struct se_session *se_sess = se_cmd->se_sess;3031 struct target_cmd_counter *cmd_cnt = se_cmd->cmd_cnt;
2997 struct completion *free_compl = se_cmd->free_compl;3032 struct completion *free_compl = se_cmd->free_compl;
2998 struct completion *abrt_compl = se_cmd->abrt_compl;3033 struct completion *abrt_compl = se_cmd->abrt_compl;
2999 3034
@@ -3004,7 +3039,8 @@ static void target_release_cmd_kref(struct kref *kref) · 4 unmodified lines
3004 if (abrt_compl)3039 if (abrt_compl)
3005 complete(abrt_compl);3040 complete(abrt_compl);
3006 3041
3007 percpu_ref_put(&se_sess->cmd_count);3042 if (cmd_cnt)
3043 percpu_ref_put(&cmd_cnt->refcnt);
3008}3044}
3009 3045
3010/**3046/**
@@ -3123,46 +3159,67 @@ void target_show_cmd(const char *pfx, struct se_cmd *cmd) · 112 unmodified lines
3123}3159}
3124EXPORT_SYMBOL(target_show_cmd);3160EXPORT_SYMBOL(target_show_cmd);
3125 3161
3126static void target_stop_session_confirm(struct percpu_ref *ref)3162static void target_stop_cmd_counter_confirm(struct percpu_ref *ref)
3163{
3164 struct target_cmd_counter *cmd_cnt = container_of(ref,
3165 struct target_cmd_counter,
3166 refcnt);
3167 complete_all(&cmd_cnt->stop_done);
3168}
3169
3170/**
3171 * target_stop_cmd_counter - Stop new IO from being added to the counter.
3172 * @cmd_cnt: counter to stop
3173 */
3174void target_stop_cmd_counter(struct target_cmd_counter *cmd_cnt)
3127{3175{
3128 struct se_session *se_sess = container_of(ref, struct se_session,3176 pr_debug("Stopping command counter.\n");
3129 cmd_count);3177 if (!atomic_cmpxchg(&cmd_cnt->stopped, 0, 1))
3130 complete_all(&se_sess->stop_done);3178 percpu_ref_kill_and_confirm(&cmd_cnt->refcnt,
3179 target_stop_cmd_counter_confirm);
3131}3180}
3181EXPORT_SYMBOL_GPL(target_stop_cmd_counter);
3132 3182
3133/**3183/**
3134 * target_stop_session - Stop new IO from being queued on the session.3184 * target_stop_session - Stop new IO from being queued on the session.
3135 * @se_sess: session to stop3185 * @se_sess: session to stop
3136 */3186 */
3137void target_stop_session(struct se_session *se_sess)3187void target_stop_session(struct se_session *se_sess)
3138{3188{
3139 pr_debug("Stopping session queue.\n");3189 target_stop_cmd_counter(se_sess->cmd_cnt);
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);
3143}3190}
3144EXPORT_SYMBOL(target_stop_session);3191EXPORT_SYMBOL(target_stop_session);
3145 3192
3146/**3193/**
3147 * target_wait_for_sess_cmds - Wait for outstanding commands3194 * target_wait_for_cmds - Wait for outstanding cmds.
3148 * @se_sess: session to wait for active I/O3195 * @cmd_cnt: counter to wait for active I/O for.
3149 */3196 */
3150void target_wait_for_sess_cmds(struct se_session *se_sess)3197void target_wait_for_cmds(struct target_cmd_counter *cmd_cnt)
3151{3198{
3152 int ret;3199 int ret;
3153 3200
3154 WARN_ON_ONCE(!atomic_read(&se_sess->stopped));3201 WARN_ON_ONCE(!atomic_read(&cmd_cnt->stopped));
3155 3202
3156 do {3203 do {
3157 pr_debug("Waiting for running cmds to complete.\n");3204 pr_debug("Waiting for running cmds to complete.\n");
3158 ret = wait_event_timeout(se_sess->cmd_count_wq,3205 ret = wait_event_timeout(cmd_cnt->refcnt_wq,
3159 percpu_ref_is_zero(&se_sess->cmd_count),3206 percpu_ref_is_zero(&cmd_cnt->refcnt),
3160 180 * HZ);3207 180 * HZ);
3161 } while (ret <= 0);3208 } while (ret <= 0);
3162 3209
3163 wait_for_completion(&se_sess->stop_done);3210 wait_for_completion(&cmd_cnt->stop_done);
3164 pr_debug("Waiting for cmds done.\n");3211 pr_debug("Waiting for cmds done.\n");
3165}3212}
3213EXPORT_SYMBOL_GPL(target_wait_for_cmds);
3214
3215/**
3216 * target_wait_for_sess_cmds - Wait for outstanding commands
3217 * @se_sess: session to wait for active I/O
3218 */
3219void target_wait_for_sess_cmds(struct se_session *se_sess)
3220{
3221 target_wait_for_cmds(se_sess->cmd_cnt);
3222}
3166EXPORT_SYMBOL(target_wait_for_sess_cmds);3223EXPORT_SYMBOL(target_wait_for_sess_cmds);
3167 3224
3168/*3225/*
drivers/target/target_core_xcopy.c+6−17
@@ -461,8 +461,6 @@ static const struct target_core_fabric_ops xcopy_pt_tfo = { · 460 unmodified lines
461 461
462int target_xcopy_setup_pt(void)462int target_xcopy_setup_pt(void)
463{463{
464 int ret;
465
466 xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0);464 xcopy_wq = alloc_workqueue("xcopy_wq", WQ_MEM_RECLAIM, 0);
467 if (!xcopy_wq) {465 if (!xcopy_wq) {
468 pr_err("Unable to allocate xcopy_wq\n");466 pr_err("Unable to allocate xcopy_wq\n");
@@ -479,9 +477,7 @@ int target_xcopy_setup_pt(void) · 10 unmodified lines
479 INIT_LIST_HEAD(&xcopy_pt_nacl.acl_list);477 INIT_LIST_HEAD(&xcopy_pt_nacl.acl_list);
480 INIT_LIST_HEAD(&xcopy_pt_nacl.acl_sess_list);478 INIT_LIST_HEAD(&xcopy_pt_nacl.acl_sess_list);
481 memset(&xcopy_pt_sess, 0, sizeof(struct se_session));479 memset(&xcopy_pt_sess, 0, sizeof(struct se_session));
482 ret = transport_init_session(&xcopy_pt_sess);480 transport_init_session(&xcopy_pt_sess);
483 if (ret < 0)
484 goto destroy_wq;
485 481
486 xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;482 xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;
487 xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;483 xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;
@@ -490,19 +486,12 @@ int target_xcopy_setup_pt(void) · 2 unmodified lines
490 xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl;486 xcopy_pt_sess.se_node_acl = &xcopy_pt_nacl;
491 487
492 return 0;488 return 0;
493
494destroy_wq:
495 destroy_workqueue(xcopy_wq);
496 xcopy_wq = NULL;
497 return ret;
498}489}
499 490
500void target_xcopy_release_pt(void)491void target_xcopy_release_pt(void)
501{492{
502 if (xcopy_wq) {493 if (xcopy_wq)
503 destroy_workqueue(xcopy_wq);494 destroy_workqueue(xcopy_wq);
504 transport_uninit_session(&xcopy_pt_sess);
505 }
506}495}
507 496
508/*497/*
@@ -602,8 +591,8 @@ static int target_xcopy_read_source( · 93 unmodified lines
602 (unsigned long long)src_lba, transfer_length_block, src_bytes);591 (unsigned long long)src_lba, transfer_length_block, src_bytes);
603 592
604 __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, src_bytes,593 __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, src_bytes,
605 DMA_FROM_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0);594 DMA_FROM_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0,
606 595 NULL);
607 rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, src_dev, &cdb[0],596 rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, src_dev, &cdb[0],
608 remote_port);597 remote_port);
609 if (rc < 0) {598 if (rc < 0) {
@@ -647,8 +636,8 @@ static int target_xcopy_write_destination( · 37 unmodified lines
647 (unsigned long long)dst_lba, transfer_length_block, dst_bytes);636 (unsigned long long)dst_lba, transfer_length_block, dst_bytes);
648 637
649 __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, dst_bytes,638 __target_init_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, dst_bytes,
650 DMA_TO_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0);639 DMA_TO_DEVICE, 0, &xpt_cmd.sense_buffer[0], 0,
651 640 NULL);
652 rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, dst_dev, &cdb[0],641 rc = target_xcopy_setup_pt_cmd(&xpt_cmd, xop, dst_dev, &cdb[0],
653 remote_port);642 remote_port);
654 if (rc < 0) {643 if (rc < 0) {
drivers/usb/gadget/function/f_tcm.c+2−2
@@ -1054,7 +1054,7 @@ static void usbg_cmd_work(struct work_struct *work) · 1053 unmodified lines
1054 tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,1054 tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
1055 tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,1055 tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
1056 cmd->prio_attr, cmd->sense_iu.sense,1056 cmd->prio_attr, cmd->sense_iu.sense,
1057 cmd->unpacked_lun);1057 cmd->unpacked_lun, NULL);
1058 goto out;1058 goto out;
1059 }1059 }
1060 1060
@@ -1183,7 +1183,7 @@ static void bot_cmd_work(struct work_struct *work) · 122 unmodified lines
1183 tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,1183 tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
1184 tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,1184 tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
1185 cmd->prio_attr, cmd->sense_iu.sense,1185 cmd->prio_attr, cmd->sense_iu.sense,
1186 cmd->unpacked_lun);1186 cmd->unpacked_lun, NULL);
1187 goto out;1187 goto out;
1188 }1188 }
1189 1189
include/target/iscsi/iscsi_target_core.h+1−0
@@ -600,6 +600,7 @@ struct iscsit_conn { · 599 unmodified lines
600 struct iscsi_tpg_np *tpg_np;600 struct iscsi_tpg_np *tpg_np;
601 /* Pointer to parent session */601 /* Pointer to parent session */
602 struct iscsit_session *sess;602 struct iscsit_session *sess;
603 struct target_cmd_counter *cmd_cnt;
603 int bitmap_id;604 int bitmap_id;
604 int rx_thread_active;605 int rx_thread_active;
605 struct task_struct *rx_thread;606 struct task_struct *rx_thread;
include/target/target_core_base.h+10−4
@@ -494,6 +494,7 @@ struct se_cmd { · 493 unmodified lines
494 struct se_lun *se_lun;494 struct se_lun *se_lun;
495 /* Only used for internal passthrough and legacy TCM fabric modules */495 /* Only used for internal passthrough and legacy TCM fabric modules */
496 struct se_session *se_sess;496 struct se_session *se_sess;
497 struct target_cmd_counter *cmd_cnt;
497 struct se_tmr_req *se_tmr_req;498 struct se_tmr_req *se_tmr_req;
498 struct llist_node se_cmd_list;499 struct llist_node se_cmd_list;
499 struct completion *free_compl;500 struct completion *free_compl;
@@ -619,22 +620,26 @@ static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item) · 119 unmodified lines
619 acl_fabric_stat_group);620 acl_fabric_stat_group);
620}621}
621 622
622struct se_session {623struct target_cmd_counter {
624 struct percpu_ref refcnt;
625 wait_queue_head_t refcnt_wq;
626 struct completion stop_done;
623 atomic_t stopped;627 atomic_t stopped;
628};
629
630struct se_session {
624 u64 sess_bin_isid;631 u64 sess_bin_isid;
625 enum target_prot_op sup_prot_ops;632 enum target_prot_op sup_prot_ops;
626 enum target_prot_type sess_prot_type;633 enum target_prot_type sess_prot_type;
627 struct se_node_acl *se_node_acl;634 struct se_node_acl *se_node_acl;
628 struct se_portal_group *se_tpg;635 struct se_portal_group *se_tpg;
629 void *fabric_sess_ptr;636 void *fabric_sess_ptr;
630 struct percpu_ref cmd_count;
631 struct list_head sess_list;637 struct list_head sess_list;
632 struct list_head sess_acl_list;638 struct list_head sess_acl_list;
633 spinlock_t sess_cmd_lock;639 spinlock_t sess_cmd_lock;
634 wait_queue_head_t cmd_count_wq;
635 struct completion stop_done;
636 void *sess_cmd_map;640 void *sess_cmd_map;
637 struct sbitmap_queue sess_tag_pool;641 struct sbitmap_queue sess_tag_pool;
642 struct target_cmd_counter *cmd_cnt;
638};643};
639 644
640struct se_device;645struct se_device;
@@ -863,6 +868,7 @@ struct se_device { · 222 unmodified lines
863 struct rcu_head rcu_head;868 struct rcu_head rcu_head;
864 int queue_cnt;869 int queue_cnt;
865 struct se_device_queue *queues;870 struct se_device_queue *queues;
871 struct mutex lun_reset_mutex;
866};872};
867 873
868struct target_opcode_descriptor {874struct target_opcode_descriptor {
include/target/target_core_fabric.h+11−4
@@ -133,7 +133,12 @@ struct se_session *target_setup_session(struct se_portal_group *, · 132 unmodified lines
133 struct se_session *, void *));133 struct se_session *, void *));
134void target_remove_session(struct se_session *);134void target_remove_session(struct se_session *);
135 135
136int transport_init_session(struct se_session *se_sess);136void target_stop_cmd_counter(struct target_cmd_counter *cmd_cnt);
137void target_wait_for_cmds(struct target_cmd_counter *cmd_cnt);
138struct target_cmd_counter *target_alloc_cmd_counter(void);
139void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt);
140
141void transport_init_session(struct se_session *se_sess);
137struct se_session *transport_alloc_session(enum target_prot_op);142struct se_session *transport_alloc_session(enum target_prot_op);
138int transport_alloc_session_tags(struct se_session *, unsigned int,143int transport_alloc_session_tags(struct se_session *, unsigned int,
139 unsigned int);144 unsigned int);
@@ -149,9 +154,11 @@ void transport_deregister_session_configfs(struct se_session *); · 9 unmodified lines
149void transport_deregister_session(struct se_session *);154void transport_deregister_session(struct se_session *);
150 155
151 156
152void __target_init_cmd(struct se_cmd *,157void __target_init_cmd(struct se_cmd *cmd,
153 const struct target_core_fabric_ops *,158 const struct target_core_fabric_ops *tfo,
154 struct se_session *, u32, int, int, unsigned char *, u64);159 struct se_session *sess, u32 data_length, int data_direction,
160 int task_attr, unsigned char *sense_buffer, u64 unpacked_lun,
161 struct target_cmd_counter *cmd_cnt);
155int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,162int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
156 unsigned char *sense, u64 unpacked_lun, u32 data_length,163 unsigned char *sense, u64 unpacked_lun, u32 data_length,
157 int task_attr, int data_dir, int flags);164 int task_attr, int data_dir, int flags);