From: <vl...@us...> - 2007-12-14 16:51:39
|
Revision: 236 http://scst.svn.sourceforge.net/scst/?rev=236&view=rev Author: vlnb Date: 2007-12-14 08:51:36 -0800 (Fri, 14 Dec 2007) Log Message: ----------- - Makes sessions registration/unregistration independant from other activities - Cleanups - Docs update Modified Paths: -------------- trunk/scst/README trunk/scst/include/scsi_tgt.h trunk/scst/src/scst_lib.c trunk/scst/src/scst_main.c trunk/scst/src/scst_priv.h trunk/scst/src/scst_targ.c Modified: trunk/scst/README =================================================================== --- trunk/scst/README 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/README 2007-12-14 16:51:36 UTC (rev 236) @@ -676,15 +676,18 @@ - Make sure that your target hardware (e.g. target FC or network card) and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to - which your disks connected) don't share the same PCI bus. They have - to work in parallel, so it will be better if they don't compete for - the bus. The problem is not only in the bandwidth, which they have to - share, but also in the interaction between cards during that - competition. This is very important, because in some cases if target - and backend storage controllers share the same PCI bus, it could lead - up to 5-10 times less performance, than expected. If you have no - choice, but PCI bus sharing, set in the BIOS PCI latency as low as - possible. + which your disks connected) don't share the same PCI bus. You can + check it using lspci utility. They have to work in parallel, so it + will be better if they don't compete for the bus. The problem is not + only in the bandwidth, which they have to share, but also in the + interaction between cards during that competition. This is very + important, because in some cases if target and backend storage + controllers share the same PCI bus, it could lead up to 5-10 times + less performance, than expected. Moreover, some motherboard (by + Supermicro, particularly) have serious stability issues if there are + several high speed devices on the same bus working in parallel. If + you have no choice, but PCI bus sharing, set in the BIOS PCI latency + as low as possible. IMPORTANT: If you use on initiator some versions of Windows (at least W2K) ========= you can't get good write performance for VDISK FILEIO devices with Modified: trunk/scst/include/scsi_tgt.h =================================================================== --- trunk/scst/include/scsi_tgt.h 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/include/scsi_tgt.h 2007-12-14 16:51:36 UTC (rev 236) @@ -1355,8 +1355,8 @@ struct list_head dev_list_entry; /* - * List of tgt_dev's, one per session, protected by scst_mutex and - * suspended activity + * List of tgt_dev's, one per session, protected by scst_mutex or + * dev_lock for reads and both for writes */ struct list_head dev_tgt_dev_list; Modified: trunk/scst/src/scst_lib.c =================================================================== --- trunk/scst/src/scst_lib.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_lib.c 2007-12-14 16:51:36 UTC (rev 236) @@ -206,8 +206,7 @@ #ifdef EXTRACHECKS if (!list_empty(&dev->dev_tgt_dev_list) || - !list_empty(&dev->dev_acg_dev_list)) - { + !list_empty(&dev->dev_acg_dev_list)) { PRINT_ERROR("%s: dev_tgt_dev_list or dev_acg_dev_list " "is not empty!", __FUNCTION__); sBUG(); @@ -311,8 +310,7 @@ /* Freeing acg_devs */ list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list, - acg_dev_list_entry) - { + acg_dev_list_entry) { struct scst_tgt_dev *tgt_dev, *tt; list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list, @@ -325,8 +323,7 @@ /* Freeing names */ list_for_each_entry_safe(n, nn, &acg->acn_list, - acn_list_entry) - { + acn_list_entry) { list_del(&n->acn_list_entry); kfree(n->name); kfree(n); @@ -339,10 +336,7 @@ return res; } -/* - * No spin locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess, struct scst_acg_dev *acg_dev) { @@ -479,10 +473,12 @@ goto out_thr_free; } } - + + spin_lock_bh(&dev->dev_lock); list_add_tail(&tgt_dev->dev_tgt_dev_list_entry, &dev->dev_tgt_dev_list); if (dev->dev_reserved) __set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags); + spin_unlock_bh(&dev->dev_lock); sess_tgt_dev_list_head = &sess->sess_tgt_dev_list_hash[HASH_VAL(tgt_dev->lun)]; @@ -508,10 +504,7 @@ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev); -/* - * No locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* No locks supposed to be held, scst_mutex - held */ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev) { TRACE_ENTRY(); @@ -533,10 +526,7 @@ return; } -/* - * No locks supposed to be held, scst_mutex - held. - * The activity is suspended. - */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ static void scst_free_tgt_dev(struct scst_tgt_dev *tgt_dev) { struct scst_device *dev = tgt_dev->dev; @@ -546,7 +536,10 @@ tm_dbg_deinit_tgt_dev(tgt_dev); + spin_lock_bh(&dev->dev_lock); list_del(&tgt_dev->dev_tgt_dev_list_entry); + spin_unlock_bh(&dev->dev_lock); + list_del(&tgt_dev->sess_tgt_dev_list_entry); scst_clear_reservation(tgt_dev); @@ -572,7 +565,7 @@ return; } -/* The activity supposed to be suspended and scst_mutex held */ +/* scst_mutex supposed to be held */ int scst_sess_alloc_tgt_devs(struct scst_session *sess) { int res = 0; @@ -582,8 +575,7 @@ TRACE_ENTRY(); list_for_each_entry(acg_dev, &sess->acg->acg_dev_list, - acg_dev_list_entry) - { + acg_dev_list_entry) { tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev); if (tgt_dev == NULL) { res = -ENOMEM; @@ -600,7 +592,7 @@ goto out; } -/* scst_mutex supposed to be held and activity suspended */ +/* scst_mutex supposed to be held, there must not be parallel activity in this sess */ void scst_sess_free_tgt_devs(struct scst_session *sess) { int i; @@ -1062,15 +1054,17 @@ } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */ +/* scst_mutex supposed to be held */ static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev) { struct scst_device *dev = tgt_dev->dev; + int release = 0; TRACE_ENTRY(); + spin_lock_bh(&dev->dev_lock); if (dev->dev_reserved && - !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) - { + !test_bit(SCST_TGT_DEV_RESERVED, &tgt_dev->tgt_dev_flags)) { /* This is one who holds the reservation */ struct scst_tgt_dev *tgt_dev_tmp; list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, @@ -1079,9 +1073,11 @@ &tgt_dev_tmp->tgt_dev_flags); } dev->dev_reserved = 0; + } + spin_unlock_bh(&dev->dev_lock); + if (release) scst_send_release(tgt_dev); - } TRACE_EXIT(); return; @@ -1149,7 +1145,6 @@ { TRACE_ENTRY(); - scst_suspend_activity(); mutex_lock(&scst_mutex); TRACE_DBG("Removing sess %p from the list", sess); @@ -1162,7 +1157,6 @@ wake_up_all(&sess->tgt->unreg_waitQ); mutex_unlock(&scst_mutex); - scst_resume_activity(); kfree(sess->initiator_name); kmem_cache_free(scst_sess_cachep, sess); @@ -2332,7 +2326,6 @@ /* Clear RESERVE'ation, if necessary */ if (dev->dev_reserved) { - /* Either scst_mutex held or exclude_cmd non-NULL */ list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { TRACE(TRACE_MGMT, "Clearing RESERVE'ation for tgt_dev " @@ -2452,7 +2445,7 @@ goto out; } -/* Called under dev_lock, tgt_dev_lock and BH off */ +/* Called under tgt_dev_lock and BH off */ void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, int sense_len, int head) { @@ -2515,7 +2508,7 @@ return; } -/* No locks, but the activity must not get suspended while inside this function */ +/* Called under dev_lock and BH off */ void scst_dev_check_set_local_UA(struct scst_device *dev, struct scst_cmd *exclude, const uint8_t *sense, int sense_len) { @@ -2676,11 +2669,6 @@ TRACE_ENTRY(); - /* - * This is read-only function for dev->dev_tgt_dev_list, so - * suspending the activity isn't necessary. - */ - mutex_lock(&scst_mutex); list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, Modified: trunk/scst/src/scst_main.c =================================================================== --- trunk/scst/src/scst_main.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_main.c 2007-12-14 16:51:36 UTC (rev 236) @@ -920,7 +920,7 @@ return; } -/* Called under scst_mutex and suspended activity */ +/* Called under scst_mutex */ int scst_add_dev_threads(struct scst_device *dev, int num) { int i, res = 0; @@ -992,7 +992,7 @@ return res; } -/* Called under scst_mutex and suspended activity */ +/* Called under scst_mutex */ void scst_del_dev_threads(struct scst_device *dev, int num) { struct scst_cmd_thread_t *ct, *tmp; Modified: trunk/scst/src/scst_priv.h =================================================================== --- trunk/scst/src/scst_priv.h 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_priv.h 2007-12-14 16:51:36 UTC (rev 236) @@ -366,6 +366,7 @@ } void scst_dev_check_set_local_UA(struct scst_device *dev, struct scst_cmd *exclude, const uint8_t *sense, int sense_len); + void scst_check_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, int sense_len, int head); void scst_alloc_set_UA(struct scst_tgt_dev *tgt_dev, const uint8_t *sense, Modified: trunk/scst/src/scst_targ.c =================================================================== --- trunk/scst/src/scst_targ.c 2007-12-14 16:43:23 UTC (rev 235) +++ trunk/scst/src/scst_targ.c 2007-12-14 16:51:36 UTC (rev 236) @@ -1368,8 +1368,7 @@ } list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { if (cmd->tgt_dev != tgt_dev_tmp) set_bit(SCST_TGT_DEV_RESERVED, &tgt_dev_tmp->tgt_dev_flags); @@ -2140,17 +2139,22 @@ if (!test_bit(SCST_TGT_DEV_RESERVED, &cmd->tgt_dev->tgt_dev_flags)) { struct scst_tgt_dev *tgt_dev_tmp; + struct scst_device *dev = cmd->dev; + TRACE(TRACE_SCSI, "Real RESERVE failed lun=%Ld, status=%x", (uint64_t)cmd->lun, cmd->status); TRACE_BUFF_FLAG(TRACE_SCSI, "Sense", cmd->sense_buffer, sizeof(cmd->sense_buffer)); + /* Clearing the reservation */ - list_for_each_entry(tgt_dev_tmp, &cmd->dev->dev_tgt_dev_list, + spin_lock_bh(&dev->dev_lock); + list_for_each_entry(tgt_dev_tmp, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { clear_bit(SCST_TGT_DEV_RESERVED, &tgt_dev_tmp->tgt_dev_flags); } - cmd->dev->dev_reserved = 0; + dev->dev_reserved = 0; + spin_unlock_bh(&dev->dev_lock); } } @@ -2203,7 +2207,8 @@ if (unlikely((cmd->cdb[0] == MODE_SELECT) || (cmd->cdb[0] == MODE_SELECT_10) || (cmd->cdb[0] == LOG_SELECT))) { - if (atomic && (cmd->dev->scsi_dev != NULL)) { + struct scst_device *dev = cmd->dev; + if (atomic && (dev->scsi_dev != NULL)) { TRACE_DBG("%s", "MODE/LOG SELECT: thread " "context required"); res = SCST_CMD_STATE_RES_NEED_THREAD; @@ -2214,7 +2219,8 @@ "setting the SELECT UA (lun=%Ld)", (uint64_t)cmd->lun); - spin_lock_bh(&scst_temp_UA_lock); + spin_lock_bh(&dev->dev_lock); + spin_lock(&scst_temp_UA_lock); if (cmd->cdb[0] == LOG_SELECT) { scst_set_sense(scst_temp_UA, sizeof(scst_temp_UA), @@ -2224,12 +2230,13 @@ sizeof(scst_temp_UA), UNIT_ATTENTION, 0x2a, 0x01); } - scst_dev_check_set_local_UA(cmd->dev, cmd, scst_temp_UA, + scst_dev_check_set_local_UA(dev, cmd, scst_temp_UA, sizeof(scst_temp_UA)); - spin_unlock_bh(&scst_temp_UA_lock); + spin_unlock(&scst_temp_UA_lock); + spin_unlock_bh(&dev->dev_lock); - if (cmd->dev->scsi_dev != NULL) - scst_obtain_device_parameters(cmd->dev); + if (dev->scsi_dev != NULL) + scst_obtain_device_parameters(dev); } } else if ((cmd->status == SAM_STAT_CHECK_CONDITION) && SCST_SENSE_VALID(cmd->sense_buffer) && @@ -3499,9 +3506,10 @@ __scst_abort_task_set(mcmd, mcmd->mcmd_tgt_dev, 0, 0); + mutex_lock(&scst_mutex); + list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { struct scst_session *sess = tgt_dev->sess; struct scst_cmd *cmd; int aborted = 0; @@ -3528,6 +3536,8 @@ &UA_tgt_devs); } + mutex_unlock(&scst_mutex); + scst_unblock_aborted_cmds(0); if (!dev->tas) { @@ -3686,8 +3696,7 @@ cont = 0; c = 0; list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) - { + dev_tgt_dev_list_entry) { cont = 1; rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); if (rc == SCST_DEV_TM_NOT_COMPLETED) @@ -4378,7 +4387,6 @@ TRACE_ENTRY(); - scst_suspend_activity(); mutex_lock(&scst_mutex); if (sess->initiator_name) @@ -4401,7 +4409,6 @@ res = scst_sess_alloc_tgt_devs(sess); mutex_unlock(&scst_mutex); - scst_resume_activity(); if (sess->init_result_fn) { TRACE_DBG("Calling init_result_fn(%p)", sess); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |