Hi Nick, So I'm looking through the flow in tcm_qla2xxx when we have a WRITE that fails to transfer data. In tcm_qla2xxx_handle_data() we end up in if (!cmd->write_data_transferred) { ... se_cmd->scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; INIT_WORK(&cmd->work, tcm_qla2xxx_do_rsp); queue_work(tcm_qla2xxx_free_wq, &cmd->work); return 0; } and tcm_qla2xxx_do_rsp() is just: void tcm_qla2xxx_do_rsp(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); /* * Dispatch ->queue_status from workqueue process context */ transport_send_check_condition_and_sense(&cmd->se_cmd, cmd->se_cmd.scsi_sense_reason, 0); } so we'll send the status back but it seems we never drop the second kref on the command? I have to admit I'm still a bit vague on exactly what we're supposed to do to finish the command here. Is it as simple as adding target_put_sess_cmd() ? Anyway I think this explains one reason we get stuck waiting for session commands on shutdown -- if any commands ever hit this path, I guess they'll never get freed and so we'll end up waiting forever for them... make sense? - R. -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html