From: <vl...@us...> - 2008-01-24 10:57:25
|
Revision: 248 http://scst.svn.sourceforge.net/scst/?rev=248&view=rev Author: vlnb Date: 2008-01-24 02:56:35 -0800 (Thu, 24 Jan 2008) Log Message: ----------- - A bunch of minor, mostly stability related, fixes. - Docs update Modified Paths: -------------- trunk/iscsi-scst/README trunk/iscsi-scst/etc/initd/initd.debian trunk/iscsi-scst/kernel/iscsi.c trunk/iscsi-scst/kernel/iscsi.h trunk/iscsi-scst/kernel/nthread.c trunk/iscsi-scst/kernel/session.c trunk/scst/README trunk/scst/include/scsi_tgt.h trunk/scst/src/dev_handlers/scst_cdrom.c trunk/scst/src/dev_handlers/scst_changer.c trunk/scst/src/dev_handlers/scst_disk.c trunk/scst/src/dev_handlers/scst_modisk.c trunk/scst/src/dev_handlers/scst_processor.c trunk/scst/src/dev_handlers/scst_raid.c trunk/scst/src/dev_handlers/scst_tape.c trunk/scst/src/dev_handlers/scst_vdisk.c trunk/scst/src/scst_lib.c trunk/scst/src/scst_targ.c Modified: trunk/iscsi-scst/README =================================================================== --- trunk/iscsi-scst/README 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/README 2008-01-24 10:56:35 UTC (rev 248) @@ -102,7 +102,7 @@ their parameters, SCST core is responsible for handling backstorage. If you need to configure different LUs for different targets you should -create for each target group "Default_target_name", where target name +create for each target group "Default_target_name", where "target_name" means name of the target, for example: "Default_iqn.2007-05.com.example:storage.disk1.sys1.xyz", and add there all necessary LUNs. Check SCST README file for details. @@ -114,6 +114,15 @@ iscsi-scstd.conf file for the corresponding target. See also SCST README file for more details about that issue. +Sometimes, when there are communication problems with initiator(s), +shutting down iSCSI-SCST can take very long time, up to about 10 +minutes. This can happen, because iSCSI-SCST can't be shutdown before +all already sent to TCP for initiator(s) data will be actually sent +and/or released by TCP. In case of communication failures this can take +up to TCP transmit timeout, which is about 10 minutes. In such cases +using netstat utility you can see that there is/are connection(s) to +initiator(s) with non-0 "Send-Q". + CAUTION: Working of target and initiator on the same host isn't ======== supported. See SCST README file for details. Modified: trunk/iscsi-scst/etc/initd/initd.debian =================================================================== --- trunk/iscsi-scst/etc/initd/initd.debian 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/etc/initd/initd.debian 2008-01-24 10:56:35 UTC (rev 248) @@ -109,23 +109,6 @@ exit 1 fi ;; - dump) - DUMP=`tempfile -p iscsi-scstd` - RETVAL=$? - if [ $RETVAL -ne 0 ]; then - echo "Failed to create dump file $DUMP" - exit 1 - fi - iscsi-scst-adm --mode dump --all >$DUMP - RETVAL=$? - if [ $RETVAL -ne 0 ]; then - echo "Error dumping config from daemon" - rm $DUMP - exit 1 - fi - mv -u $DUMP $CONFIG_FILE - echo "Config dumped to $CONFIG_FILE" - ;; *) echo $"Usage: $0 {start|stop|restart|status|dump}" exit 1 Modified: trunk/iscsi-scst/kernel/iscsi.c =================================================================== --- trunk/iscsi-scst/kernel/iscsi.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/kernel/iscsi.c 2008-01-24 10:56:35 UTC (rev 248) @@ -92,6 +92,8 @@ static inline void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd) { + EXTRACHECKS_BUG_ON(cmnd->data_waiting); + cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED; scst_restart_cmd(cmnd->scst_cmd, SCST_PREPROCESS_STATUS_SUCCESS, SCST_CONTEXT_THREAD); @@ -166,6 +168,12 @@ { TRACE_DBG("%p", cmnd); + if (unlikely(cmnd->tmfabort)) { + TRACE_MGMT_DBG("Free aborted cmd %p (scst cmd %p, state %d, " + "parent_req %p)", cmnd, cmnd->scst_cmd, cmnd->scst_state, + cmnd->parent_req); + } + /* Catch users from cmd_list or rsp_cmd_list */ EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) != 0); @@ -221,12 +229,16 @@ if (cmnd->scst_cmd) { switch(cmnd->scst_state) { case ISCSI_CMD_STATE_AFTER_PREPROC: + { + struct scst_cmd *scst_cmd = cmnd->scst_cmd; TRACE_DBG("cmd %p AFTER_PREPROC", cmnd); cmnd->scst_state = ISCSI_CMD_STATE_RESTARTED; - scst_restart_cmd(cmnd->scst_cmd, + cmnd->scst_cmd = NULL; + scst_restart_cmd(scst_cmd, SCST_PREPROCESS_STATUS_ERROR_FATAL, - SCST_CONTEXT_DIRECT); + SCST_CONTEXT_THREAD); break; + } case ISCSI_CMD_STATE_PROCESSED: TRACE_DBG("cmd %p PROCESSED", cmnd); scst_tgt_cmd_done(cmnd->scst_cmd); @@ -1300,7 +1312,8 @@ if (dir == SCST_DATA_WRITE) { req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL); req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize; - req->data_waiting = 1; + if (req->r2t_length > 0) + req->data_waiting = 1; } req->target_task_tag = get_next_ttt(conn); req->sg = scst_cmd_get_sg(scst_cmd); Modified: trunk/iscsi-scst/kernel/iscsi.h =================================================================== --- trunk/iscsi-scst/kernel/iscsi.h 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/kernel/iscsi.h 2008-01-24 10:56:35 UTC (rev 248) @@ -103,7 +103,7 @@ u32 tm_sn; struct iscsi_cmnd *tm_rsp; - /* read only, if there are connection(s) */ + /* Read only, if there are connection(s) */ struct iscsi_sess_param sess_param; spinlock_t cmnd_hash_lock; @@ -113,7 +113,7 @@ struct list_head session_list_entry; - /* Bot don't need any protection */ + /* Both don't need any protection */ char *initiator_name; u64 sid; }; Modified: trunk/iscsi-scst/kernel/nthread.c =================================================================== --- trunk/iscsi-scst/kernel/nthread.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/kernel/nthread.c 2008-01-24 10:56:35 UTC (rev 248) @@ -183,6 +183,15 @@ /* We want all our already send operations to complete */ conn->sock->ops->shutdown(conn->sock, RCV_SHUTDOWN); + /* + * We need to call scst_unregister_session() ASAP to make SCST start + * stuck commands recovery. + * + * ToDo: this is incompatible with MC/S + */ + scst_unregister_session(session->scst_sess, 0, NULL); + session->scst_sess = NULL; + if (conn->read_state != RX_INIT_BHS) { struct iscsi_cmnd *cmnd = conn->read_cmnd; conn->read_cmnd = NULL; @@ -295,7 +304,7 @@ } iscsi_make_conn_wr_active(conn); - msleep(50); + msleep(200); TRACE_CONN_CLOSE("conn %p, conn_ref_cnt %d left, wr_state %d, " "exp_cmd_sn %u", conn, atomic_read(&conn->conn_ref_cnt), @@ -379,8 +388,8 @@ mutex_lock(&target->target_mutex); conn_free(conn); - if (list_empty(&session->conn_list)) - session_del(target, session->sid); + /* ToDo: this is incompatible with MC/S */ + session_free(session); mutex_unlock(&target->target_mutex); TRACE_EXIT(); Modified: trunk/iscsi-scst/kernel/session.c =================================================================== --- trunk/iscsi-scst/kernel/session.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/iscsi-scst/kernel/session.c 2008-01-24 10:56:35 UTC (rev 248) @@ -136,7 +136,8 @@ for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) sBUG_ON(!list_empty(&session->cmnd_hash[i])); - scst_unregister_session(session->scst_sess, 1, NULL); + if (session->scst_sess != NULL) + scst_unregister_session(session->scst_sess, 1, NULL); list_del(&session->session_list_entry); Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/README 2008-01-24 10:56:35 UTC (rev 248) @@ -426,7 +426,11 @@ and "FLAGS" are valid only for disk VDISK. The block size must be power of 2 and >= 512 bytes. Default is 512. Possible flags: - - WRITE_THROUGH - write back caching disabled + - WRITE_THROUGH - write back caching disabled. Note, this option + has sense only if you also *manually* disable write-back cache + in *all* your backstorage devices and make sure it's actually + disabled, since many devices are known to lie about this mode to + get better benchmark results. - READ_ONLY - read only @@ -439,20 +443,23 @@ way as "*_perf" handlers. - NV_CACHE - enables "non-volatile cache" mode. In this mode it is - assumed that the target has GOOD UPS and software/hardware bug - free, i.e. all data from the target's cache are guaranteed - sooner or later to go to the media, hence all data - synchronization with media operations, like SYNCHRONIZE_CACHE, - are ignored (BTW, so violating SCSI standard) in order to bring - a bit more performance. Use with extreme caution, since in this - mode after a crash of the target journaled file systems don't - guarantee the consistency after journal recovery, therefore - manual fsck MUST be ran. The main intent for it is to determine - the performance impact caused by the cache synchronization. - Note, that since usually the journal barrier protection (see - "IMPORTANT" below) turned off, enabling NV_CACHE could change - nothing, since no data synchronization with media operations - will go from the initiator. + assumed that the target has a GOOD UPS with ability to cleanly + shutdown target in case of power failure and it is + software/hardware bugs free, i.e. all data from the target's + cache are guaranteed sooner or later to go to the media. Hence + all data synchronization with media operations, like + SYNCHRONIZE_CACHE, are ignored in order to bring more + performance. Also in this mode target reports to initiators that + the corresponding device has write-through cache to disable all + write-back cache workarounds used by initiators. Use with + extreme caution, since in this mode after a crash of the target + journaled file systems don't guarantee the consistency after + journal recovery, therefore manual fsck MUST be ran. Note, that + since usually the journal barrier protection (see "IMPORTANT" + note below) turned off, enabling NV_CACHE could change nothing + from data protection point of view, since no data + synchronization with media operations will go from the + initiator. This option overrides WRITE_THROUGH. - BLOCKIO - enables block mode, which will perform direct block IO with a block device, bypassing page-cache for all operations. @@ -503,7 +510,7 @@ backstorage device and lost on power failure event. Thus, ever with write-through cache mode, you still need a good UPS to protect yourself from your data loss (note, data loss, not - the file system integrity). + the file system integrity corruption). IMPORTANT: Some disk and partition table management utilities don't support ========= block sizes >512 bytes, therefore make sure that your favorite one Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/include/scsi_tgt.h 2008-01-24 10:56:35 UTC (rev 248) @@ -1621,13 +1621,23 @@ * Parameter: * - sess - session * - * Note: All outstanding commands will be finished regularly. After - * scst_unregister_session() returned no new commands must be sent to - * SCST via scst_rx_cmd(). Also, the caller must ensure that no - * scst_rx_cmd() or scst_rx_mgmt_fn_*() is called in paralell with - * scst_unregister_session(). - * Can be called before result_fn() of scst_register_session() called, - * i.e. during the session registration/initialization. + * Notes: + * + * - All outstanding commands will be finished regularly. After + * scst_unregister_session() returned no new commands must be sent to + * SCST via scst_rx_cmd(). + * + * - The caller must ensure that no scst_rx_cmd() or scst_rx_mgmt_fn_*() is + * called in paralell with scst_unregister_session(). + * + * - Can be called before result_fn() of scst_register_session() called, + * i.e. during the session registration/initialization. + * + * - It is highly recommended to call scst_unregister_session() as soon as it + * gets clear that session will be unregistered and not to wait until all + * related commands finished. This function provides the wait functionality, + * but it also starts recovering stuck commands, if there are any. + * Otherwise, your target driver could wait for those commands forever. */ void scst_unregister_session(struct scst_session *sess, int wait, void (*unreg_done_fn) (struct scst_session *sess)); Modified: trunk/scst/src/dev_handlers/scst_cdrom.c =================================================================== --- trunk/scst/src/dev_handlers/scst_cdrom.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_cdrom.c 2008-01-24 10:56:35 UTC (rev 248) @@ -148,8 +148,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out_free_buf; + } out_free_buf: kfree(buffer); Modified: trunk/scst/src/dev_handlers/scst_changer.c =================================================================== --- trunk/scst/src/dev_handlers/scst_changer.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_changer.c 2008-01-24 10:56:35 UTC (rev 248) @@ -96,8 +96,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out; + } out: TRACE_EXIT_HRES(res); Modified: trunk/scst/src/dev_handlers/scst_disk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_disk.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_disk.c 2008-01-24 10:56:35 UTC (rev 248) @@ -220,8 +220,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out_free_buf; + } out_free_buf: kfree(buffer); Modified: trunk/scst/src/dev_handlers/scst_modisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_modisk.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_modisk.c 2008-01-24 10:56:35 UTC (rev 248) @@ -235,8 +235,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d: %x", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun, res); goto out_free_buf; + } out_free_buf: kfree(buffer); Modified: trunk/scst/src/dev_handlers/scst_processor.c =================================================================== --- trunk/scst/src/dev_handlers/scst_processor.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_processor.c 2008-01-24 10:56:35 UTC (rev 248) @@ -96,8 +96,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out; + } out: TRACE_EXIT(); Modified: trunk/scst/src/dev_handlers/scst_raid.c =================================================================== --- trunk/scst/src/dev_handlers/scst_raid.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_raid.c 2008-01-24 10:56:35 UTC (rev 248) @@ -96,8 +96,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out; + } out: TRACE_EXIT(); Modified: trunk/scst/src/dev_handlers/scst_tape.c =================================================================== --- trunk/scst/src/dev_handlers/scst_tape.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_tape.c 2008-01-24 10:56:35 UTC (rev 248) @@ -223,8 +223,13 @@ } res = scst_obtain_device_parameters(dev); - if (res != 0) + if (res != 0) { + PRINT_ERROR("Failed to obtain control parameters for device " + "%d:%d:%d:%d", dev->scsi_dev->host->host_no, + dev->scsi_dev->channel, dev->scsi_dev->id, + dev->scsi_dev->lun); goto out_free_buf; + } out_free_buf: kfree(buffer); Modified: trunk/scst/src/dev_handlers/scst_vdisk.c =================================================================== --- trunk/scst/src/dev_handlers/scst_vdisk.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/dev_handlers/scst_vdisk.c 2008-01-24 10:56:35 UTC (rev 248) @@ -351,7 +351,7 @@ open_flags |= O_RDWR; if (virt_dev->o_direct_flag) open_flags |= O_DIRECT; - if (virt_dev->wt_flag) + if (virt_dev->wt_flag && !virt_dev->nv_cache) open_flags |= O_SYNC; TRACE_DBG("Opening file %s, flags 0x%x", virt_dev->file_name, open_flags); fd = filp_open(virt_dev->file_name, O_LARGEFILE | open_flags, 0600); @@ -494,7 +494,7 @@ dev->dh_priv = virt_dev; dev->tst = DEF_TST; - if (virt_dev->wt_flag) + if (virt_dev->wt_flag && !virt_dev->nv_cache) dev->queue_alg = DEF_QUEUE_ALG_WT; else dev->queue_alg = DEF_QUEUE_ALG; @@ -1313,7 +1313,7 @@ 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; memcpy(p, caching_pg, sizeof(caching_pg)); - p[2] |= !(virt_dev->wt_flag) ? WCE : 0; + p[2] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ? WCE : 0; if (1 == pcontrol) memset(p + 2, 0, sizeof(caching_pg) - 2); return sizeof(caching_pg); @@ -1344,7 +1344,7 @@ break; case 2: p[2] |= DEF_TST << 5; - if (virt_dev->wt_flag) + if (virt_dev->wt_flag || virt_dev->nv_cache) p[3] |= DEF_QUEUE_ALG_WT << 4; else p[3] |= DEF_QUEUE_ALG << 4; @@ -1529,7 +1529,7 @@ TRACE_ENTRY(); - if ((virt_dev->wt_flag == wt) || virt_dev->nullio) + if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache) goto out; spin_lock(&virt_dev->flags_lock); @@ -2486,7 +2486,7 @@ struct scst_vdisk_dev *virt_dev = (struct scst_vdisk_dev *)dev->dh_priv; dev->tst = DEF_TST; - if (virt_dev->wt_flag) + if (virt_dev->wt_flag && !virt_dev->nv_cache) dev->queue_alg = DEF_QUEUE_ALG_WT; else dev->queue_alg = DEF_QUEUE_ALG; Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/scst_lib.c 2008-01-24 10:56:35 UTC (rev 248) @@ -2296,7 +2296,11 @@ goto out; } else { +#if 0 /* 3ware controller is buggy and returns CONDITION_GOOD instead of CHECK_CONDITION */ if ((status_byte(res) == CHECK_CONDITION) && +#else + if ( +#endif SCST_SENSE_VALID(sense_buffer) && (sense_buffer[2] == ILLEGAL_REQUEST)) { TRACE(TRACE_SCSI|TRACE_MGMT_MINOR, "Device %d:%d:%d:%d " @@ -3103,7 +3107,6 @@ /* All serialized by scst_tm_dbg_lock */ struct { - unsigned int tm_dbg_active:1; unsigned int tm_dbg_release:1; unsigned int tm_dbg_blocked:1; } tm_dbg_flags; @@ -3122,19 +3125,16 @@ { if ((acg_dev->acg == scst_default_acg) && (acg_dev->lun == 0)) { unsigned long flags; + /* Do TM debugging only for LUN 0 */ spin_lock_irqsave(&scst_tm_dbg_lock, flags); - if (!tm_dbg_flags.tm_dbg_active) { - /* Do TM debugging only for LUN 0 */ - tm_dbg_p_cmd_list_waitQ = - &tgt_dev->dev->p_cmd_lists->cmd_list_waitQ; - tm_dbg_state = INIT_TM_DBG_STATE; - tm_dbg_on_state_passes = - tm_dbg_on_state_num_passes[tm_dbg_state]; - __set_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags); - PRINT_INFO("LUN 0 connected from initiator %s is under " - "TM debugging", tgt_dev->sess->tgt->tgtt->name); - tm_dbg_flags.tm_dbg_active = 1; - } + tm_dbg_p_cmd_list_waitQ = + &tgt_dev->dev->p_cmd_lists->cmd_list_waitQ; + tm_dbg_state = INIT_TM_DBG_STATE; + tm_dbg_on_state_passes = + tm_dbg_on_state_num_passes[tm_dbg_state]; + __set_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags); + PRINT_INFO("LUN 0 connected from initiator %s is under " + "TM debugging", tgt_dev->sess->tgt->tgtt->name); spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); } } @@ -3146,7 +3146,6 @@ del_timer_sync(&tm_dbg_timer); spin_lock_irqsave(&scst_tm_dbg_lock, flags); tm_dbg_p_cmd_list_waitQ = NULL; - tm_dbg_flags.tm_dbg_active = 0; spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); } } @@ -3342,9 +3341,6 @@ { unsigned long flags; - if (!tm_dbg_flags.tm_dbg_active) - goto out; - if (dev != NULL) { struct scst_tgt_dev *tgt_dev; bool found = 0; @@ -3371,7 +3367,8 @@ tm_dbg_change_state(); tm_dbg_flags.tm_dbg_release = 1; smp_mb(); - wake_up_all(tm_dbg_p_cmd_list_waitQ); + if (tm_dbg_p_cmd_list_waitQ != NULL) + wake_up_all(tm_dbg_p_cmd_list_waitQ); } else { TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn); } Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2008-01-23 16:03:20 UTC (rev 247) +++ trunk/scst/src/scst_targ.c 2008-01-24 10:56:35 UTC (rev 248) @@ -208,9 +208,16 @@ spin_lock_irqsave(&sess->sess_list_lock, flags); - list_add_tail(&cmd->search_cmd_list_entry, &sess->search_cmd_list); - if (unlikely(sess->init_phase != SCST_SESS_IPH_READY)) { + /* + * We have to always keep command in the search list from the + * very beginning, because otherwise it can be missed during + * TM processing. This check is needed because there might be + * old, i.e. deferred, commands and new, i.e. just coming, ones. + */ + if (cmd->search_cmd_list_entry.next == NULL) + list_add_tail(&cmd->search_cmd_list_entry, + &sess->search_cmd_list); switch(sess->init_phase) { case SCST_SESS_IPH_SUCCESS: break; @@ -228,7 +235,8 @@ default: sBUG(); } - } + } else + list_add_tail(&cmd->search_cmd_list_entry, &sess->search_cmd_list); spin_unlock_irqrestore(&sess->sess_list_lock, flags); @@ -1845,6 +1853,7 @@ struct scst_cmd *cmd = *active_cmd; struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; struct scst_device *dev = cmd->dev; + struct scst_session *sess = cmd->sess; typeof(tgt_dev->expected_sn) expected_sn; int count; @@ -1852,11 +1861,12 @@ res = SCST_CMD_STATE_RES_CONT_NEXT; - __scst_get(0); /* protect dev & tgt_dev */ + __scst_get(0); /* protect dev */ + scst_sess_get(sess); /* protect tgt_dev */ if (unlikely(cmd->internal || cmd->retry)) { rc = scst_do_send_to_midlev(cmd); - /* !! At this point cmd, sess & tgt_dev can be already freed !! */ + /* !! At this point cmd can be already freed !! */ if (rc == SCST_EXEC_NEED_THREAD) { TRACE_DBG("%s", "scst_do_send_to_midlev() requested " "thread context, rescheduling"); @@ -1875,7 +1885,7 @@ getnstimeofday(&ts); cmd->pre_exec_finish = scst_sec_to_nsec(ts.tv_sec) + ts.tv_nsec; TRACE_DBG("cmd %p (sess %p): pre_exec_finish %Ld (tv_sec %ld, " - "tv_nsec %ld)", cmd, cmd->sess, cmd->pre_exec_finish, ts.tv_sec, + "tv_nsec %ld)", cmd, sess, cmd->pre_exec_finish, ts.tv_sec, ts.tv_nsec); } #endif @@ -1960,6 +1970,7 @@ generic_unplug_device(dev->scsi_dev->request_queue); out_put: + scst_sess_put(sess); __scst_put(); /* !! At this point sess, dev and tgt_dev can be already freed !! */ @@ -2434,6 +2445,19 @@ TRACE_ENTRY(); +#ifdef DEBUG_TM + if (cmd->tm_dbg_delayed && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { + if (scst_cmd_atomic(cmd)) { + TRACE_MGMT_DBG("%s", "DEBUG_TM delayed cmd needs a thread"); + res = SCST_CMD_STATE_RES_NEED_THREAD; + return res; + } + TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second", + cmd, cmd->tag); + schedule_timeout_uninterruptible(HZ); + } +#endif + if (cmd->tgt_dev != NULL) { if (unlikely(cmd->queue_type == SCST_CMD_QUEUE_HEAD_OF_QUEUE)) scst_on_hq_cmd_response(cmd); @@ -2516,19 +2540,6 @@ goto out; } -#ifdef DEBUG_TM - if (cmd->tm_dbg_delayed && !test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { - if (atomic && !cmd->tgtt->xmit_response_atomic) { - TRACE_MGMT_DBG("%s", "DEBUG_TM delayed cmd needs a thread"); - res = SCST_CMD_STATE_RES_NEED_THREAD; - goto out; - } - TRACE_MGMT_DBG("Delaying cmd %p (tag %llu) for 1 second", - cmd, cmd->tag); - schedule_timeout_uninterruptible(HZ); - } -#endif - while (1) { int finished_cmds = atomic_read(&cmd->sess->tgt->finished_cmds); @@ -3439,12 +3450,12 @@ return res; } -static int __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd) +static bool __scst_check_unblock_aborted_cmd(struct scst_cmd *cmd, + struct list_head *list_entry) { - int res; + bool res; if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) { - TRACE_MGMT_DBG("Adding aborted blocked cmd %p to active cmd " - "list", cmd); + list_del(list_entry); spin_lock(&cmd->cmd_lists->cmd_list_lock); list_add_tail(&cmd->cmd_list_entry, &cmd->cmd_lists->active_cmd_list); @@ -3472,8 +3483,11 @@ local_irq_disable(); list_for_each_entry_safe(cmd, tcmd, &dev->blocked_cmd_list, blocked_cmd_list_entry) { - if (__scst_check_unblock_aborted_cmd(cmd)) - list_del(&cmd->blocked_cmd_list_entry); + if (__scst_check_unblock_aborted_cmd(cmd, + &cmd->blocked_cmd_list_entry)) { + TRACE_MGMT_DBG("Unblock aborted blocked cmd %p", + cmd); + } } local_irq_enable(); spin_unlock_bh(&dev->dev_lock); @@ -3485,11 +3499,11 @@ list_for_each_entry_safe(cmd, tcmd, &tgt_dev->deferred_cmd_list, sn_cmd_list_entry) { - if (__scst_check_unblock_aborted_cmd(cmd)) { - TRACE_MGMT_DBG("Deleting aborted SN " - "cmd %p from SN list", cmd); + if (__scst_check_unblock_aborted_cmd(cmd, + &cmd->sn_cmd_list_entry)) { + TRACE_MGMT_DBG("Unblockd aborted SN " + "cmd %p", cmd); tgt_dev->def_cmd_count--; - list_del(&cmd->sn_cmd_list_entry); } } spin_unlock(&tgt_dev->sn_lock); @@ -4105,6 +4119,9 @@ if (scst_is_strict_mgmt_fn(mcmd->fn) && (mcmd->completed_cmd_count > 0)) mcmd->status = SCST_MGMT_STATUS_TASK_NOT_EXIST; + TRACE(TRACE_MGMT_MINOR, "TM command fn %d finished, status %x", + mcmd->fn, mcmd->status); + if (mcmd->sess->tgt->tgtt->task_mgmt_fn_done) { TRACE_DBG("Calling target %s task_mgmt_fn_done()", mcmd->sess->tgt->tgtt->name); @@ -4557,7 +4574,6 @@ TRACE_DBG("Deleting cmd %p from init deferred cmd list", cmd); list_del(&cmd->cmd_list_entry); atomic_dec(&sess->sess_cmd_count); - list_del(&cmd->search_cmd_list_entry); spin_unlock_irq(&sess->sess_list_lock); scst_cmd_init_done(cmd, SCST_CONTEXT_THREAD); spin_lock_irq(&sess->sess_list_lock); @@ -4666,12 +4682,13 @@ sess->shutdown_compl = NULL; #endif + TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess); + list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list); + spin_unlock_irqrestore(&scst_mgmt_lock, flags); - tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1); + wake_up(&scst_mgmt_waitQ); - scst_sess_put(sess); - if (wait) { TRACE_DBG("Waiting for session %p to complete", sess); wait_for_completion(pc); @@ -4689,10 +4706,11 @@ { int i; struct scst_tgt_dev *tgt_dev; - unsigned long flags; TRACE_ENTRY(); + tm_dbg_task_mgmt(NULL, "UNREGISTER SESSION", 1); + mutex_lock(&scst_mutex); for(i = 0; i < TGT_DEV_HASH_SIZE; i++) { struct list_head *sess_tgt_dev_list_head = @@ -4713,10 +4731,7 @@ sess->shut_phase = SCST_SESS_SPH_SHUTDOWN; - spin_lock_irqsave(&scst_mgmt_lock, flags); - TRACE_DBG("Adding sess %p to scst_sess_shut_list", sess); - list_add_tail(&sess->sess_shut_list_entry, &scst_sess_shut_list); - spin_unlock_irqrestore(&scst_mgmt_lock, flags); + scst_sess_put(sess); TRACE_EXIT(); return; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |