Re: [PATCH 09/11] target_core_alua: Use workqueue for ALUA transitioning

2013-10-16 Thread Hannes Reinecke
On 10/17/2013 12:06 AM, Nicholas A. Bellinger wrote:
> On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
>> Use a workqueue for processing ALUA state transitions; this allows
>> us to process implicit delay properly.
>>
>> Signed-off-by: Hannes Reinecke 
>> ---
>>  drivers/target/target_core_alua.c | 174 
>> +++---
>>  include/target/target_core_base.h |   4 +
>>  2 files changed, 128 insertions(+), 50 deletions(-)
>>
> 
> 
> 
>> +static int core_alua_do_transition_tg_pt(
>> +struct t10_alua_tg_pt_gp *tg_pt_gp,
>> +int new_state,
>> +int explicit)
>> +{
>> +struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
>> +DECLARE_COMPLETION_ONSTACK(wait);
>> +
>> +/* Nothing to be done here */
>> +if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state)
>> +return 0;
>> +
>> +if (new_state == ALUA_ACCESS_STATE_TRANSITION)
>> +return -EAGAIN;
>> +
>> +/*
>> + * Flush any pending transitions
>> + */
>> +if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs &&
>> +atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) ==
>> +ALUA_ACCESS_STATE_TRANSITION) {
>> +/* Just in case */
>> +tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
>> +tg_pt_gp->tg_pt_gp_transition_complete = &wait;
>> +flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work);
>> +wait_for_completion(&wait);
>> +tg_pt_gp->tg_pt_gp_transition_complete = NULL;
>> +return 0;
>> +}
>> +
>> +/*
>> + * Save the old primary ALUA access state, and set the current state
>> + * to ALUA_ACCESS_STATE_TRANSITION.
>> + */
>> +tg_pt_gp->tg_pt_gp_alua_previous_state =
>> +atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
>> +tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
>> +
>> +atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
>> +ALUA_ACCESS_STATE_TRANSITION);
>> +tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
>> +ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
>> +ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
>> +
>> +/*
>> + * Check for the optional ALUA primary state transition delay
>> + */
>> +if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0)
>> +msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs);
>> +
>> +/*
>> + * Take a reference for workqueue item
>> + */
>> +spin_lock(&dev->t10_alua.tg_pt_gps_lock);
>> +atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
>> +smp_mb__after_atomic_inc();
>> +spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
>> +
>> +if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) {
>> +unsigned long transition_tmo;
>> +
>> +transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ;
>> +queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
>> +   &tg_pt_gp->tg_pt_gp_transition_work,
>> +   transition_tmo);
>> +} else {
>> +tg_pt_gp->tg_pt_gp_transition_complete = &wait;
>> +queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
>> +   &tg_pt_gp->tg_pt_gp_transition_work, 0);
>> +wait_for_completion(&wait);
>> +tg_pt_gp->tg_pt_gp_transition_complete = NULL;
>> +}
> 
> Mmm, the trans_delay_msecs delay seems a bit out of place now..
> 
> How about dropping it's usage with msleep_interruptible() above, and
> instead combining it with the delay passed into queue_delayed_work()..?
> 
Yeah, we could.
Actually I was thinking of opening up the implicit transition time
to be a general transitioning time, to be used for both implicit and
explicit.
Reasoning here is that one could kick off a userland tool once
'transitioning' mode has been requested.
That tool would then go ahead and do whatever is required to switch
paths around etc, and could write the final ALUA state into configfs.
That would then terminate the workqueue and the system would
continue with the new state.
If the userland tool fails to execute in time the system would
revert to the requested state as it does now.

The only problem with that approach is that it's currently
impossible to have an atomic implicit transition for several tpgs.

You can to an atomic _explicit_ transition, as SET TARGET PORT
GROUPS _can_ carry information about all target port groups.
(Mind you, scsi_dh_alua doesn't use it that way, it only sends
information for the active/optimized target port group).
But you cannot achieve a similar operation via configfs; there you
can only set one tpg at a time, and each of this will potentially
trigger a move to transitioning.

While this is not a violation of the spec, it is certainly
confusing. I'd rather have a way to set the new state for _all_ tpgs
at once and only then kick off the transitioning mechanism.

Any

Re: [PATCH 02/11] target_core_alua: Store supported ALUA states

2013-10-16 Thread Hannes Reinecke
On 10/16/2013 11:19 PM, Nicholas A. Bellinger wrote:
> On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
>> The supported ALUA states might be different for individual
>> devices, so store it in a separate field.
>>
>> Signed-off-by: Hannes Reinecke 
>> ---
>>  drivers/target/target_core_alua.c | 14 --
>>  drivers/target/target_core_alua.h | 11 +++
>>  include/target/target_core_base.h |  1 +
>>  3 files changed, 20 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/target/target_core_alua.c 
>> b/drivers/target/target_core_alua.c
>> index 8297d37..255e83c 100644
>> --- a/drivers/target/target_core_alua.c
>> +++ b/drivers/target/target_core_alua.c
>> @@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd 
>> *cmd)
>>  /*
>>   * Set supported ASYMMETRIC ACCESS State bits
>>   */
>> -buf[off] = 0x80; /* T_SUP */
>> -buf[off] |= 0x40; /* O_SUP */
>> -buf[off] |= 0x8; /* U_SUP */
>> -buf[off] |= 0x4; /* S_SUP */
>> -buf[off] |= 0x2; /* AN_SUP */
>> -buf[off++] |= 0x1; /* AO_SUP */
>> +buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
>>  /*
>>   * TARGET PORT GROUP
>>   */
>> @@ -1367,6 +1362,13 @@ struct t10_alua_tg_pt_gp 
>> *core_alua_allocate_tg_pt_gp(struct se_device *dev,
>>  tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
>>  tg_pt_gp->tg_pt_gp_implicit_trans_secs = 
>> ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
>>  
>> +/*
>> + * Enable all supported states
>> + */
>> +tg_pt_gp->tg_pt_gp_alua_supported_states =
>> +ALUA_T_SUP | ALUA_O_SUP | \
>> +ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
>> +
>>  if (def_group) {
>>  spin_lock(&dev->t10_alua.tg_pt_gps_lock);
>>  tg_pt_gp->tg_pt_gp_id =
>> diff --git a/drivers/target/target_core_alua.h 
>> b/drivers/target/target_core_alua.h
>> index 74cf0c0..e826a65 100644
>> --- a/drivers/target/target_core_alua.h
>> +++ b/drivers/target/target_core_alua.h
>> @@ -23,6 +23,17 @@
>>  #define ALUA_ACCESS_STATE_TRANSITION0xf
>>  
>>  /*
>> + * from spc4r36j section 6.37 Table 306
>> + */
>> +#define ALUA_T_SUP  0x80
>> +#define ALUA_O_SUP  0x40
>> +#define ALUA_LBD_SUP0x10
>> +#define ALUA_U_SUP  0x08
>> +#define ALUA_S_SUP  0x04
>> +#define ALUA_AN_SUP 0x02
>> +#define ALUA_AO_SUP 0x01
>> +
>> +/*
> 
> How about making these the supported bits, TPGS mode, and ALUA access
> state definitions common between target_core_alua.c and
> scsi_dh_alua.c..?
> 
Sure. Good idea.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH][SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path

2013-10-16 Thread Saxena, Sumit


>-Original Message-
>From: James Bottomley [mailto:jbottom...@parallels.com]
>Sent: Thursday, October 17, 2013 3:15 AM
>To: Saxena, Sumit
>Cc: linux-scsi@vger.kernel.org; Desai, Kashyap; aradf...@gmail.com
>Subject: Re: [PATCH][SCSI] megaraid_sas: Fix synchronization problem
>between sysPD IO path and AEN path
>
>On Wed, 2013-10-16 at 17:04 +0530, sumit.sax...@lsi.com wrote:
>> There is syncronization problem between sysPD IO path and AEN path.
>> Driver maintains instance->pd_list[] array, which will get updated(by
>> calling function megasas_get_pd_list[]), whenever any of below events
>> occurs-
>>
>> MR_EVT_PD_INSERTED
>> MR_EVT_PD_REMOVED
>> MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED
>> MR_EVT_FOREIGN_CFG_IMPORTED
>>
>> At same time running sysPD IO will be accessing the same array
>> instance->pd_list[], which is getting updated in AEN path, because of
>this IO may not get correct PD info from instance->pd_list[] array.
>>
>> Signed-off-by: Adam Radford 
>> Signed-off-by: Sumit Saxena 
>
>Explain the signoff chain: is this a joinly authored patch?

Yes, it's jointly authored patch. Originally, this patch is authored by Adam 
Radford, and then modified by me(Sumit Saxena).

>
>James
>


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH Resend] [scsi] pm8001 : fix panic when cat /sys/class/sas_phy/phy-8:0/running_disparity_error_count

2013-10-16 Thread lindar_liu
>
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_h
> wi.c index 9f91030..c0ea473 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
>
@@ -3076,8 +3076,43 @@ static int mpi_get_controller_config_resp(struct pm80
> 01_hba_info *pm8001_ha,
>  static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
>   void *piomb)
>  {
> - PM8001_MSG_DBG(pm8001_ha,
> - pm8001_printk(" pm80xx_addition_functionality\n"));
> + u8 page_code;
> + struct get_phy_profile_resp *pPayload = (struct get_phy_profile_resp
> + *)(piomb + 4);
> + u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
> + u32 status = le32_to_cpu(pPayload->status);
> + u8 phy_id = (u8)(ppc_phyid & 0x00FF);
> + page_code = (u8)((ppc_phyid & 0xFF00) >> 8); struct asd_sas_phy
> + *sas_phy = &(pm8001_ha->phy[phy_id].sas_phy);
> + struct sas_phy *phy = sas_phy->phy;
> +
> + if (status) {
> + /* status is FAILED */
> + PM8001_FAIL_DBG(pm8001_ha,
> + pm8001_printk("PhyProfile command failed  with status "
> + "0x%08X \n", status));
> + return -1;
> + } else {
> + switch (page_code) {
> + case SAS_PHY_ERROR_PAGE:
> + phy->invalid_dword_count =
> + le32_to_cpu(pPayload->ppc_specific_rsp[0]);
> + phy->running_disparity_error_count =
> + le32_to_cpu(pPayload->ppc_specific_rsp[1]);
> + phy->loss_of_dword_sync_count =
> + le32_to_cpu(pPayload->ppc_specific_rsp[3]);
> + phy->phy_reset_problem_count =
> + le32_to_cpu(pPayload->ppc_specific_rsp[4]);
> + complete(pm8001_ha->phy[phy_id].enable_completion);
> + break;
> + default:
> + PM8001_MSG_DBG(pm8001_ha,
> + pm8001_printk("other page code 0x%X\n", page_code)); break; } }
> 
>   return 0;
>  }

Any failure response also need to call complete() function. 
You can put the "complete()" at end before return.

Thanks.
Lindar

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] Fix device detection issues with mvsas driver

2013-10-16 Thread Praveen Murali
The only way to reproduce this is to keep hot plugging drives. To speed it up 
once in a while remove the drive before the detection completes.

> On Oct 16, 2013, at 7:42 PM, "xiangliang yu"  wrote:
> 
> Hi,
> 
> >Subject: Re: [PATCH 3/3] Fix device detection issues with mvsas driver
> 
> >Hi Xiang, Can you please take a look at the attached patch and ack it?
> > /* cleanup and prepare the allocated FIS index */
> > memset( SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), 0, 
> > sizeof(struct dev_to_host_fis) );
> 
> According to spec, the FIS memory don't need to be cleared by software.
> can you tell me how to reproduce the issue? thanks!
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Bug] 12.864681 BUG: lock held when returning to user space!

2013-10-16 Thread vaughan
On 10/17/2013 06:41 AM, Douglas Gilbert wrote:
> That seems to be the case. Vaughan acknowledged the
> problem and forwarded it to me 8 days ago. Yes, it
> seems to be a "no-no" to hold a any kernel semaphore
> when returning to the user space; in this case from
> sg_open(). I was hoping a revised patch might
> appear from Vaughan but to date that has not been
> the case. So with only a few weeks to go before
> lk 3.12 is released, reverting the whole 4 patches
> in that series seems to be the safest course.
>
> Also without a new patch from Vaughan in the next few
> weeks he may also miss the opportunity of getting
> his improved O_EXCL logic into the lk 3.13 series.
>
>
> Thinking about how to solve this problem: a field could
> be added to 'struct sg_device' with one of three states:
> no_opens, non_excl_opens and excl_open. It could be
> manipulated by sg_open() and sg_release() like a
> read-write semaphore. And the faulty 'struct
> rw_semaphore o_sem' in sg_device could be replaced by a
> normal semaphore to protect the manipulation of the new
> three-state field.
> And the new three-state field would replace (or expand)
the 'char exclude' field in struct sg_device .
>
> Doug Gilbert
Hi Doug,

Thanks for providing advice on how to fix this.
However, it seems be still awkward somehow. We have to
1. hold a lock (maybe sg_index_lock or a new one)
2. check
   a) the new three-state field;
   b) if sfp list is empty;
   c) sdp->detached field;
if either condition fails, we may link the open process into o_excl_wait
queue and need wakeup.
if satisfied, we go on.
3. then we release at least sg_index_lock to malloc a new sfp and
initialize.
4. try to acquire sg_index_lock again and add this sfp into sfd_siblings
list if possible.  <== We still have to check at least sdp->detached field
5. update three-state field to reflect the result of Step 4, and wake up
processes waiting in o_excl_wait.

This uncomfortable is introduced by releasing the sg_index_lock in the
middle of check->malloc->add the new sfp struct.

I wanna ask if it is possible to split the sg_add_sfp() into two
functions, sg_init_sfp() and sg_add_sfp2(). We can do all initialize
work in sg_init_sfp()
without any lock and let sg_add_sfp2() only serve lock-check-add in one
way. It seems more convenient for me to understand.
But there is still some questions on this approach:
1. memory consume can be very large if lots of sg_init_sfp in the same time;
2. some field are initialized according to the fields of scsi device sdp
points to, such as low_dma, sg_tablesize, max_sector, phys_segs.
I know scsi_device_get() would keep the underlying scsi_device
alive, however would these fields change in the gap of our initialize
and add?
The relationship of sg_device and scsi_device like above said
confuse me somehow...

Thanks,
Vaughan
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] target_core_alua: Referrals configfs integration

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:25 +0200, Hannes Reinecke wrote:
> Referrals need an LBA map, which needs to be kept
> consistent across all target port groups. So
> instead of tying the map to the target port groups
> I've implemented a single attribute containing the
> entire map.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c  | 101 +++
>  drivers/target/target_core_alua.h  |   8 ++
>  drivers/target/target_core_configfs.c  | 171 
> +
>  drivers/target/target_core_device.c|   1 +
>  drivers/target/target_core_transport.c |  28 +-
>  5 files changed, 308 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/target/target_core_alua.c 
> b/drivers/target/target_core_alua.c
> index 8f66146..9dd01ff 100644
> --- a/drivers/target/target_core_alua.c
> +++ b/drivers/target/target_core_alua.c
> @@ -1340,6 +1340,107 @@ static int core_alua_set_tg_pt_secondary_state(
>   return 0;
>  }
>  
> +struct t10_alua_lba_map *
> +core_alua_allocate_lba_map(struct list_head *list,
> +u64 first_lba, u64 last_lba)
> +{
> + struct t10_alua_lba_map *lba_map;
> +
> + lba_map = kmem_cache_zalloc(t10_alua_lba_map_cache, GFP_KERNEL);
> + if (!lba_map) {
> + pr_err("Unable to allocate struct t10_alua_lba_map\n");
> + return ERR_PTR(-ENOMEM);
> + }
> + INIT_LIST_HEAD(&lba_map->lba_map_mem_list);
> + lba_map->lba_map_first_lba = first_lba;
> + lba_map->lba_map_last_lba = last_lba;
> +
> + list_add_tail(&lba_map->lba_map_list, list);
> + return lba_map;
> +}

This list_add_tail needs to be protected, no..?

> +
> +int
> +core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *lba_map,
> +int pg_id, int state)
> +{
> + struct t10_alua_lba_map_member *lba_map_mem;
> +
> + list_for_each_entry(lba_map_mem, &lba_map->lba_map_mem_list,
> + lba_map_mem_list) {
> + if (lba_map_mem->lba_map_mem_alua_pg_id == pg_id) {
> + pr_err("Duplicate pg_id %d in lba_map\n", pg_id);
> + return -EINVAL;
> + }
> + }
> +
> + lba_map_mem = kmem_cache_zalloc(t10_alua_lba_map_mem_cache, GFP_KERNEL);
> + if (!lba_map_mem) {
> + pr_err("Unable to allocate struct t10_alua_lba_map_mem\n");
> + return -ENOMEM;
> + }
> + lba_map_mem->lba_map_mem_alua_state = state;
> + lba_map_mem->lba_map_mem_alua_pg_id = pg_id;
> +
> + list_add_tail(&lba_map_mem->lba_map_mem_list,
> +   &lba_map->lba_map_mem_list);
> + return 0;
> +}

Ditto here..

> +
> +void
> +core_alua_free_lba_map(struct list_head *lba_list)
> +{
> + struct t10_alua_lba_map *lba_map, *lba_map_tmp;
> + struct t10_alua_lba_map_member *lba_map_mem, *lba_map_mem_tmp;
> +
> + list_for_each_entry_safe(lba_map, lba_map_tmp, lba_list,
> +  lba_map_list) {
> + list_for_each_entry_safe(lba_map_mem, lba_map_mem_tmp,
> +  &lba_map->lba_map_mem_list,
> +  lba_map_mem_list) {
> + list_del(&lba_map_mem->lba_map_mem_list);
> + kmem_cache_free(t10_alua_lba_map_mem_cache,
> + lba_map_mem);
> + }
> + list_del(&lba_map->lba_map_list);
> + kmem_cache_free(t10_alua_lba_map_cache, lba_map);
> + }
> +}

And here..

> +
> +void
> +core_alua_set_lba_map(struct se_device *dev, struct list_head *lba_map_list,
> +   int segment_size, int segment_mult)
> +{
> + struct list_head old_lba_map_list;
> + struct t10_alua_tg_pt_gp *tg_pt_gp;
> + int activate = 0, supported;
> +
> + INIT_LIST_HEAD(&old_lba_map_list);
> + spin_lock(&dev->t10_alua.lba_map_lock);
> + dev->t10_alua.lba_map_segment_size = segment_size;
> + dev->t10_alua.lba_map_segment_multiplier = segment_mult;
> + list_splice_init(&dev->t10_alua.lba_map_list, &old_lba_map_list);
> + if (lba_map_list) {
> + list_splice_init(lba_map_list, &dev->t10_alua.lba_map_list);
> + activate = 1;
> + }
> + spin_unlock(&dev->t10_alua.lba_map_lock);
> + spin_lock(&dev->t10_alua.tg_pt_gps_lock);
> + list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list,
> + tg_pt_gp_list) {
> +
> + if (!tg_pt_gp->tg_pt_gp_valid_id)
> + continue;
> + supported = tg_pt_gp->tg_pt_gp_alua_supported_states;
> + if (activate)
> + supported |= ALUA_LBD_SUP;
> + else
> + supported &= ~ALUA_LBD_SUP;
> + tg_pt_gp->tg_pt_gp_alua_supported_states = supported;
> + }
> + spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
> + core_alua_free_lba_map(&old_lba_map_list);
> +}
> +
>  struct 

Re: [Bug] 12.864681 BUG: lock held when returning to user space!

2013-10-16 Thread Douglas Gilbert

On 13-10-16 09:24 AM, James Bottomley wrote:

On Tue, 2013-10-08 at 09:45 -0400, Douglas Gilbert wrote:

On 13-10-08 02:44 AM, vaughan wrote:

Hi Madper,

CC to Douglas to get comments.
I use the rw_semaphore o_sem to protect excl open, introduced in commit
15b06f9a02406e5460001db6d5af5c738cd3d4e7 since v3.12-rc1.
Is it forbidden to do like that in kernel?...


It appears you can not (allow sg_open() to hold a semaphore
then return to the user space). So you will need to do some
rework on that patch or revert it.


OK, there being no reply on this, I'll do the revert ... that's all four
patches, correct?


That seems to be the case. Vaughan acknowledged the
problem and forwarded it to me 8 days ago. Yes, it
seems to be a "no-no" to hold a any kernel semaphore
when returning to the user space; in this case from
sg_open(). I was hoping a revised patch might
appear from Vaughan but to date that has not been
the case. So with only a few weeks to go before
lk 3.12 is released, reverting the whole 4 patches
in that series seems to be the safest course.

Also without a new patch from Vaughan in the next few
weeks he may also miss the opportunity of getting
his improved O_EXCL logic into the lk 3.13 series.


Thinking about how to solve this problem: a field could
be added to 'struct sg_device' with one of three states:
no_opens, non_excl_opens and excl_open. It could be
manipulated by sg_open() and sg_release() like a
read-write semaphore. And the faulty 'struct
rw_semaphore o_sem' in sg_device could be replaced by a
normal semaphore to protect the manipulation of the new
three-state field.

Doug Gilbert


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] target: Pass through I/O topology for block backstores

2013-10-16 Thread Andy Grover

On 10/12/2013 01:08 AM, Christoph Hellwig wrote:

On Fri, Oct 11, 2013 at 11:52:53AM -0700, Andy Grover wrote:

It seemed better to me to keep the munging from queue_limits values
to what the target core needed in the block backstore code, and not
use a block-specific structure in the backstore<->core interface.

It looks like a few includes of blkdev.h slipped into target core,
but these can be removed safely -- lio core doesn't depend on the
block layer.

We could define a new struct to get the 4 values at once, but it
didn't seem worth it, esp. since two are only needed by
emulate_readcapacity16, and the other two only by emulate_evpd_b0.


I really don't like the influx of methods.  But given thsat you have
done the work I'd say merge your patch for now and then we can later see
if we can come up with something more elegant.


Nick, any cleaner ways to implement this come to mind? Happy to respin.

If not, please apply.

Regards -- Andy

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] target_core_alua: Referrals infrastructure

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:25 +0200, Hannes Reinecke wrote:
> Add infrastructure for referrals.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c | 151 
> ++
>  drivers/target/target_core_alua.h |   4 +-
>  drivers/target/target_core_configfs.c |  12 ++-
>  drivers/target/target_core_device.c   |   2 +
>  drivers/target/target_core_sbc.c  |   5 +-
>  drivers/target/target_core_spc.c  |  20 +
>  include/scsi/scsi.h   |   1 +
>  include/target/target_core_base.h |  18 
>  8 files changed, 209 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/target/target_core_alua.c 
> b/drivers/target/target_core_alua.c
> index 166bee6..8f66146 100644
> --- a/drivers/target/target_core_alua.c
> +++ b/drivers/target/target_core_alua.c
> @@ -56,6 +56,75 @@ static LIST_HEAD(lu_gps_list);
>  struct t10_alua_lu_gp *default_lu_gp;
>  
>  /*
> + * REPORT REFERRALS
> + *
> + * See sbc3r35 section 5.23
> + */
> +sense_reason_t
> +target_emulate_report_referrals(struct se_cmd *cmd)
> +{
> + struct se_device *dev = cmd->se_dev;
> + struct t10_alua_lba_map *map;
> + struct t10_alua_lba_map_member *map_mem;
> + unsigned char *buf;
> + u32 rd_len = 0, off;
> +
> + if (cmd->data_length < 4) {
> + pr_warn("REPORT REFERRALS allocation length %u too"
> + " small\n", cmd->data_length);
> + return TCM_INVALID_CDB_FIELD;
> + }
> +
> + buf = transport_kmap_data_sg(cmd);
> + if (!buf)
> + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +
> + off = 4;
> + spin_lock(&dev->t10_alua.lba_map_lock);
> + if (list_empty(&dev->t10_alua.lba_map_list)) {
> + spin_unlock(&dev->t10_alua.lba_map_lock);
> + transport_kunmap_data_sg(cmd);
> +
> + return TCM_UNSUPPORTED_SCSI_OPCODE;
> + }
> +
> + list_for_each_entry(map, &dev->t10_alua.lba_map_list,
> + lba_map_list) {
> + int desc_num = off + 3;
> + int pg_num;
> +
> + off += 4;
> + put_unaligned_be64(map->lba_map_first_lba, &buf[off]);
> + off += 8;
> + put_unaligned_be64(map->lba_map_last_lba, &buf[off]);
> + off += 8;
> + rd_len += 20;
> + pg_num = 0;
> + list_for_each_entry(map_mem, &map->lba_map_mem_list,
> + lba_map_mem_list) {
> + buf[off++] = map_mem->lba_map_mem_alua_state & 0x0f;
> + off++;
> + buf[off++] = (map_mem->lba_map_mem_alua_pg_id >> 8) & 
> 0xff;
> + buf[off++] = (map_mem->lba_map_mem_alua_pg_id & 0xff);
> + rd_len += 4;
> + pg_num++;
> + }
> + buf[desc_num] = pg_num;
> + }
> + spin_unlock(&dev->t10_alua.lba_map_lock);
> +

For both of these list walks, there needs to be a check against offset
vs. ->data_length to know when the available payload length has been
exhausted..

> + /*
> +  * Set the RETURN DATA LENGTH set in the header of the DataIN Payload
> +  */
> + put_unaligned_be16(rd_len, &buf[2]);
> +
> + transport_kunmap_data_sg(cmd);
> +
> + target_complete_cmd(cmd, GOOD);
> + return 0;
> +}
> +
> +/*
>   * REPORT_TARGET_PORT_GROUPS
>   *
>   * See spc4r17 section 6.27
> @@ -389,6 +458,80 @@ static inline int core_alua_state_nonoptimized(
>   return 0;
>  }
>  
> +static inline int core_alua_state_lba_dependent(
> + struct se_cmd *cmd,
> + struct t10_alua_tg_pt_gp *tg_pt_gp,
> + u8 *alua_ascq)
> +{
> + struct se_device *dev = cmd->se_dev;
> + u32 segment_size, segment_mult, sectors;
> + u64 lba;
> +
> + /* Only need to check for cdb actually containing LBAs */
> + if (!cmd->se_cmd_flags & SCF_SCSI_DATA_CDB)
> + return 0;
> +
> + spin_lock(&dev->t10_alua.lba_map_lock);
> + segment_size = dev->t10_alua.lba_map_segment_size;
> + segment_mult = dev->t10_alua.lba_map_segment_multiplier;
> + sectors = cmd->data_length / dev->dev_attrib.block_size;
> +
> + lba = cmd->t_task_lba;
> + while (lba < cmd->t_task_lba + sectors) {
> + struct t10_alua_lba_map *cur_map = NULL, *map;
> + struct t10_alua_lba_map_member *map_mem;
> +
> + list_for_each_entry(map, &dev->t10_alua.lba_map_list,
> + lba_map_list) {
> + u64 start_lba, last_lba;
> + u64 first_lba = map->lba_map_first_lba;
> +
> + if (segment_mult) {
> + start_lba = lba % (segment_size * segment_mult);
> + last_lba = first_lba + segment_size - 1;
> + if (start_lba >= first_lba &&
> + start_lba <= last_lba) {
> + 

Re: [PATCH 3/3] Fix device detection issues with mvsas driver

2013-10-16 Thread Praveen Murali

Hi Xiang, Can you please take a look at the attached patch and ack it?

Thanks,
Praveen

On 10/16/2013 02:45 PM, James Bottomley wrote:

On Tue, 2013-10-15 at 19:40 -0700, Praveen Murali wrote:

Yes, I checked that today and was meaning to ask you about it. :)

Ideally, I need someone from Marvell to ack it ... can you prod them?

Thanks,

James




>From 6ad9cf691f9d11e8c6de332efc35bd945c0f2840 Mon Sep 17 00:00:00 2001
From: Praveen Murali 
Date: Thu, 21 Jun 2012 09:57:03 -0700
Subject: [PATCH v2] Fix mvsas SATA disk detection issues

 I am using the Marvell SAS HBA (MV64460/64461/64462 System Controller,
Revision B (rev 01)), on a system running Ubuntu 12.04 stock kernel. And
i am seeing some drive detection issues with SATA drives, mostly during
hotplugging the drives; the issue gets exaggerated when we keep removing
and plugging in drives.

>From dmesg, after starting the LibATA debugs, it looks like the
ata_eh_revalidate_and_attach fails because ata_dev_read_id fails to get
the IDENTIFY command response. I see "both IDENTIFYs aborted, assuming
NODEV" for all these drives that go undetected. At this point, if I
unload and reload the mvsas driver, these drives detect fine. So, I
hooked up a SATA analyzer between the HBA and one of the drives, and
restarted the test. From what I can see, even though the drive responds
to the IDENTIFY command, the upper layer detects an error and discards
the response. On further debugging it was evident that the error was
being detected in the FIS.

 After going thru the mvsas driver, I see that during init the driver 
allocates a DMA area for an FIS pool (for as many as 33 FIS's) and initializes 
it to 0. And each ATA command is allocated a FIS area from this pool during
the command prep; but its never cleared.

The fix is to cleanup and prepare the FIS index before issuing the ATA
command (during prep: mvs_task_prep_ata).
---
 drivers/scsi/mvsas/mv_sas.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index a4884a5..73d9816 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -458,6 +458,11 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
 			mvi_dev->device_id);
 		return -EBUSY;
 	}
+
+	/* cleanup and prepare the allocated FIS index */
+	memset( SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), 0, 
+sizeof(struct dev_to_host_fis) );
+
 	slot = &mvi->slot_info[tag];
 	slot->tx = mvi->tx_prod;
 	del_q = TXQ_MODE_I | tag |
-- 
1.7.10



How are you doing.

2013-10-16 Thread Brice

Dear friend  

I am Mr.Axel Brice a banker from one of the international bank here in my 
country. Although the world is  spherical and hard place to met people because 
you don't know who to trust or believe, but I have developed my trust to you to 
confide this confidential business proposal. 

4 years ago, most of the African Politicians used our bank to launder fund to 
overseas through the help of their Political advisers, I find out what was 
going because these days some of the fund where stock for politicians, I was 
able to divert ($15.2M) to an escrow account that belong to unknown person.

So i will like you to act as the depositor of the fund because the bank do not 
know the owner of the fund and also the claim is legal as i have make all the 
good arrangement to transfer the fund to foreign account.

Thanks 
Mr. Axel Brice
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/11] target_core_mod: ALUA updates

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> Hi Nic,
> 
> here are some updates to TCM ALUA handling. Apart from some
> minor fixes and spellchecks the main features are:
> - Make supported states configurable:
>   We should make the list of supported ALUA states configurable,
>   as some setups would possibly like to support a small subset
>   of ALUA states only.
> - Asynchronous transitioning: I've switched 'transitioning'
>   handling to use a workqueue, that should allow us to simulate
>   asynchronous transitioning modes. IE TCM should now be capable
>   of handling requests while in transitioning, and properly terminate
>   these with the correct sense code.
> - Include target device descriptor in VPD page 83
>   For the ALUA device handler we'd need to identify the target device
>   where a given target port belongs to. So include the respective
>   values in the VPD page.
> 
> Hannes Reinecke (11):
>   target core: rename (ex,im)plict -> (ex,im)plicit
>   target_core_alua: Store supported ALUA states
>   target_core_alua: Make supported states configurable
>   target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED
>   target_core_alua: spellcheck
>   target_core_alua: Validate ALUA state transition
>   target_core_alua: Allocate ALUA metadata on demand
>   target_core_alua: store old and pending ALUA state
>   target_core_alua: Use workqueue for ALUA transitioning
>   target_core: simplify scsi_name_len calculation
>   target_core_spc: Include target device descriptor in VPD page 83
> 

Hey Hannes,

It looks like Patches #10 && #11 did not make it to the list.

Care to address the minor comments on the others and repost a -v2 with
the missing ones..?

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 09/11] target_core_alua: Use workqueue for ALUA transitioning

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> Use a workqueue for processing ALUA state transitions; this allows
> us to process implicit delay properly.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c | 174 
> +++---
>  include/target/target_core_base.h |   4 +
>  2 files changed, 128 insertions(+), 50 deletions(-)
> 



> +static int core_alua_do_transition_tg_pt(
> + struct t10_alua_tg_pt_gp *tg_pt_gp,
> + int new_state,
> + int explicit)
> +{
> + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
> + DECLARE_COMPLETION_ONSTACK(wait);
> +
> + /* Nothing to be done here */
> + if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state)
> + return 0;
> +
> + if (new_state == ALUA_ACCESS_STATE_TRANSITION)
> + return -EAGAIN;
> +
> + /*
> +  * Flush any pending transitions
> +  */
> + if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs &&
> + atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) ==
> + ALUA_ACCESS_STATE_TRANSITION) {
> + /* Just in case */
> + tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
> + tg_pt_gp->tg_pt_gp_transition_complete = &wait;
> + flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work);
> + wait_for_completion(&wait);
> + tg_pt_gp->tg_pt_gp_transition_complete = NULL;
> + return 0;
> + }
> +
> + /*
> +  * Save the old primary ALUA access state, and set the current state
> +  * to ALUA_ACCESS_STATE_TRANSITION.
> +  */
> + tg_pt_gp->tg_pt_gp_alua_previous_state =
> + atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
> + tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
> +
> + atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
> + ALUA_ACCESS_STATE_TRANSITION);
> + tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
> + ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
> + ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
> +
> + /*
> +  * Check for the optional ALUA primary state transition delay
> +  */
> + if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0)
> + msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs);
> +
> + /*
> +  * Take a reference for workqueue item
> +  */
> + spin_lock(&dev->t10_alua.tg_pt_gps_lock);
> + atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
> + smp_mb__after_atomic_inc();
> + spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
> +
> + if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) {
> + unsigned long transition_tmo;
> +
> + transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ;
> + queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
> +&tg_pt_gp->tg_pt_gp_transition_work,
> +transition_tmo);
> + } else {
> + tg_pt_gp->tg_pt_gp_transition_complete = &wait;
> + queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq,
> +&tg_pt_gp->tg_pt_gp_transition_work, 0);
> + wait_for_completion(&wait);
> + tg_pt_gp->tg_pt_gp_transition_complete = NULL;
> + }

Mmm, the trans_delay_msecs delay seems a bit out of place now..

How about dropping it's usage with msleep_interruptible() above, and
instead combining it with the delay passed into queue_delayed_work()..?

--nab


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Help us complete this charity project, reply for detail!!!

2013-10-16 Thread Mr. Allen & Violet Large
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] Fix device detection issues with mvsas driver

2013-10-16 Thread James Bottomley
On Tue, 2013-10-15 at 19:40 -0700, Praveen Murali wrote:
> Yes, I checked that today and was meaning to ask you about it. :)

Ideally, I need someone from Marvell to ack it ... can you prod them?

Thanks,

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH][SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path

2013-10-16 Thread James Bottomley
On Wed, 2013-10-16 at 17:04 +0530, sumit.sax...@lsi.com wrote:
> There is syncronization problem between sysPD IO path and AEN path. Driver 
> maintains instance->pd_list[] array, which will get updated(by calling 
> function megasas_get_pd_list[]), whenever any of below events occurs-
> 
> MR_EVT_PD_INSERTED
> MR_EVT_PD_REMOVED
> MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED
> MR_EVT_FOREIGN_CFG_IMPORTED
> 
> At same time running sysPD IO will be accessing the same array 
> instance->pd_list[], which is getting updated in AEN path, because
> of this IO may not get correct PD info from instance->pd_list[] array.
> 
> Signed-off-by: Adam Radford 
> Signed-off-by: Sumit Saxena 

Explain the signoff chain: is this a joinly authored patch?

James

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 07/11] target_core_alua: Allocate ALUA metadata on demand

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> We should only allocate ALUA metadata if we're actually going
> to write them.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c | 70 
> +--
>  drivers/target/target_core_alua.h |  3 ++
>  include/target/target_core_base.h |  3 --
>  3 files changed, 34 insertions(+), 42 deletions(-)
> 

Looks reasonable to me..

--nab

> diff --git a/drivers/target/target_core_alua.c 
> b/drivers/target/target_core_alua.c
> index a420778..b1d08bf 100644
> --- a/drivers/target/target_core_alua.c
> +++ b/drivers/target/target_core_alua.c
> @@ -762,16 +762,22 @@ static int core_alua_write_tpg_metadata(
>   */
>  static int core_alua_update_tpg_primary_metadata(
>   struct t10_alua_tg_pt_gp *tg_pt_gp,
> - int primary_state,
> - unsigned char *md_buf)
> + int primary_state)
>  {
> + unsigned char *md_buf;
>   struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
>   char path[ALUA_METADATA_PATH_LEN];
> - int len;
> + int len, rc;
> +
> + md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL);
> + if (!md_buf) {
> + pr_err("Unable to allocate buf for ALUA metadata\n");
> + return -ENOMEM;
> + }
>  
>   memset(path, 0, ALUA_METADATA_PATH_LEN);
>  
> - len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len,
> + len = snprintf(md_buf, ALUA_MD_BUF_LEN,
>   "tg_pt_gp_id=%hu\n"
>   "alua_access_state=0x%02x\n"
>   "alua_access_status=0x%02x\n",
> @@ -782,14 +788,15 @@ static int core_alua_update_tpg_primary_metadata(
>   "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0],
>   config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item));
>  
> - return core_alua_write_tpg_metadata(path, md_buf, len);
> + rc = core_alua_write_tpg_metadata(path, md_buf, len);
> + kfree(md_buf);
> + return rc;
>  }
>  
>  static int core_alua_do_transition_tg_pt(
>   struct t10_alua_tg_pt_gp *tg_pt_gp,
>   struct se_port *l_port,
>   struct se_node_acl *nacl,
> - unsigned char *md_buf,
>   int new_state,
>   int explicit)
>  {
> @@ -877,8 +884,7 @@ static int core_alua_do_transition_tg_pt(
>*/
>   if (tg_pt_gp->tg_pt_gp_write_metadata) {
>   mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex);
> - core_alua_update_tpg_primary_metadata(tg_pt_gp,
> - new_state, md_buf);
> + core_alua_update_tpg_primary_metadata(tg_pt_gp, new_state);
>   mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex);
>   }
>   /*
> @@ -909,19 +915,12 @@ int core_alua_do_port_transition(
>   struct t10_alua_lu_gp *lu_gp;
>   struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
>   struct t10_alua_tg_pt_gp *tg_pt_gp;
> - unsigned char *md_buf;
>   int primary, valid_states;
>  
>   valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
>   if (core_alua_check_transition(new_state, valid_states, &primary) != 0)
>   return -EINVAL;
>  
> - md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL);
> - if (!md_buf) {
> - pr_err("Unable to allocate buf for ALUA metadata\n");
> - return -ENOMEM;
> - }
> -
>   local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem;
>   spin_lock(&local_lu_gp_mem->lu_gp_mem_lock);
>   lu_gp = local_lu_gp_mem->lu_gp;
> @@ -939,10 +938,9 @@ int core_alua_do_port_transition(
>* success.
>*/
>   core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
> - md_buf, new_state, explicit);
> + new_state, explicit);
>   atomic_dec(&lu_gp->lu_gp_ref_cnt);
>   smp_mb__after_atomic_dec();
> - kfree(md_buf);
>   return 0;
>   }
>   /*
> @@ -992,7 +990,7 @@ int core_alua_do_port_transition(
>* success.
>*/
>   core_alua_do_transition_tg_pt(tg_pt_gp, port,
> - nacl, md_buf, new_state, explicit);
> + nacl, new_state, explicit);
>  
>   spin_lock(&dev->t10_alua.tg_pt_gps_lock);
>   atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
> @@ -1014,7 +1012,6 @@ int core_alua_do_port_transition(
>  
>   atomic_dec(&lu_gp->lu_gp_ref_cnt);
>   smp_mb__after_atomic_dec();
> - kfree(md_buf);
>   return 0;
>  }
>  
> @@ -1023,13 +1020,18 @@ int core_alua_do_port_transition(
>   */
>  static int core_alua_update_tpg_secondary_metadata(
>   struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
> - struct se_port *port,
> - unsigned char *md_buf,
> - u32 md_buf_len)
> + struct se_port *port)
>  {
> + unsigned char *md_buf;
>   struct se

Re: [PATCH 06/11] target_core_alua: Validate ALUA state transition

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> As we now can modify the list of supported states we need to
> validate the requested ALUA state when doing a state transition.
> 
> Signed-off-by: Hannes Reinecke 
> ---

Looks good.

--nab

>  drivers/target/target_core_alua.c | 85 
> ++-
>  1 file changed, 56 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/target/target_core_alua.c 
> b/drivers/target/target_core_alua.c
> index a16115e..a420778 100644
> --- a/drivers/target/target_core_alua.c
> +++ b/drivers/target/target_core_alua.c
> @@ -41,7 +41,8 @@
>  #include "target_core_alua.h"
>  #include "target_core_ua.h"
>  
> -static sense_reason_t core_alua_check_transition(int state, int *primary);
> +static sense_reason_t core_alua_check_transition(int state, int valid,
> +  int *primary);
>  static int core_alua_set_tg_pt_secondary_state(
>   struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
>   struct se_port *port, int explicit, int offline);
> @@ -210,7 +211,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
>   unsigned char *ptr;
>   sense_reason_t rc = TCM_NO_SENSE;
>   u32 len = 4; /* Skip over RESERVED area in header */
> - int alua_access_state, primary = 0;
> + int alua_access_state, primary = 0, valid_states;
>   u16 tg_pt_id, rtpi;
>  
>   if (!l_port)
> @@ -252,6 +253,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
>   rc = TCM_UNSUPPORTED_SCSI_OPCODE;
>   goto out;
>   }
> + valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
>  
>   ptr = &buf[4]; /* Skip over RESERVED area in header */
>  
> @@ -263,7 +265,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
>* the state is a primary or secondary target port asymmetric
>* access state.
>*/
> - rc = core_alua_check_transition(alua_access_state, &primary);
> + rc = core_alua_check_transition(alua_access_state,
> + valid_states, &primary);
>   if (rc) {
>   /*
>* If the SET TARGET PORT GROUPS attempts to establish
> @@ -614,21 +617,57 @@ out:
>   return 0;
>  }
>  
> +static char *core_alua_dump_state(int state)
> +{
> + switch (state) {
> + case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
> + return "Active/Optimized";
> + case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
> + return "Active/NonOptimized";
> + case ALUA_ACCESS_STATE_STANDBY:
> + return "Standby";
> + case ALUA_ACCESS_STATE_UNAVAILABLE:
> + return "Unavailable";
> + case ALUA_ACCESS_STATE_OFFLINE:
> + return "Offline";
> + case ALUA_ACCESS_STATE_TRANSITION:
> + return "Transitioning";
> + default:
> + return "Unknown";
> + }
> +
> + return NULL;
> +}
> +
>  /*
>   * Check implicit and explicit ALUA state change request.
>   */
>  static sense_reason_t
> -core_alua_check_transition(int state, int *primary)
> +core_alua_check_transition(int state, int valid, int *primary)
>  {
> + /*
> +  * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
> +  * defined as primary target port asymmetric access states.
> +  */
>   switch (state) {
>   case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
> + if (!(valid & ALUA_AO_SUP))
> + goto not_supported;
> + *primary = 1;
> + break;
>   case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
> + if (!(valid & ALUA_AN_SUP))
> + goto not_supported;
> + *primary = 1;
> + break;
>   case ALUA_ACCESS_STATE_STANDBY:
> + if (!(valid & ALUA_S_SUP))
> + goto not_supported;
> + *primary = 1;
> + break;
>   case ALUA_ACCESS_STATE_UNAVAILABLE:
> - /*
> -  * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
> -  * defined as primary target port asymmetric access states.
> -  */
> + if (!(valid & ALUA_U_SUP))
> + goto not_supported;
>   *primary = 1;
>   break;
>   case ALUA_ACCESS_STATE_OFFLINE:
> @@ -636,6 +675,8 @@ core_alua_check_transition(int state, int *primary)
>* OFFLINE state is defined as a secondary target port
>* asymmetric access state.
>*/
> + if (!(valid & ALUA_O_SUP))
> + goto not_supported;
>   *primary = 0;
>   break;
>   default:
> @@ -644,26 +685,11 @@ core_alua_check_transition(int state, int *primary)
>   }
>  
>   return 0;
> -}
>  
> -static char *core_alua_dump_state(int state)
> -{
> - switch (state) {
> - cas

Re: [PATCH 03/11] target_core_alua: Make supported states configurable

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_configfs.c | 50 
> +++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/drivers/target/target_core_configfs.c 
> b/drivers/target/target_core_configfs.c
> index d4c28a3..53e9e00 100644
> --- a/drivers/target/target_core_configfs.c
> +++ b/drivers/target/target_core_configfs.c
> @@ -2131,6 +2131,55 @@ static ssize_t 
> target_core_alua_tg_pt_gp_store_attr_alua_access_type(
>  SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
>  
>  /*
> + * alua_supported_states
> + */
> +static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_supported_states(
> + struct t10_alua_tg_pt_gp *tg_pt_gp,
> + char *page)
> +{
> + return sprintf(page, "%02x\n",
> + tg_pt_gp->tg_pt_gp_alua_supported_states);
> +}
> +
> +static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_supported_states(
> + struct t10_alua_tg_pt_gp *tg_pt_gp,
> + const char *page,
> + size_t count)
> +{
> + unsigned long tmp;
> + int new_states, valid_states, ret;
> +
> + if (!tg_pt_gp->tg_pt_gp_valid_id) {
> + pr_err("Unable to do set supported ALUA states on non"
> + " valid tg_pt_gp ID: %hu\n",
> + tg_pt_gp->tg_pt_gp_valid_id);
> + return -EINVAL;
> + }
> +
> + ret = strict_strtoul(page, 0, &tmp);
> + if (ret < 0) {
> + pr_err("Unable to extract new supported ALUA states"
> + " from %s\n", page);
> + return -EINVAL;
> + }
> + new_states = (int)tmp;
> + valid_states = ALUA_T_SUP | ALUA_O_SUP | ALUA_LBD_SUP | \
> + ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
> +
> +
> + if (new_states & ~valid_states) {
> + pr_err("Illegal supported ALUA states: 0x%02x\n",
> + new_states);
> + return -EINVAL;
> + }
> +
> + tg_pt_gp->tg_pt_gp_alua_supported_states = new_states;
> + return count;
> +}
> +
> +SE_DEV_ALUA_TG_PT_ATTR(alua_supported_states, S_IRUGO | S_IWUSR);
> +
> +/*
>   * alua_write_metadata
>   */
>  static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata(
> @@ -2350,6 +2399,7 @@ static struct configfs_attribute 
> *target_core_alua_tg_pt_gp_attrs[] = {
>   &target_core_alua_tg_pt_gp_alua_access_state.attr,
>   &target_core_alua_tg_pt_gp_alua_access_status.attr,
>   &target_core_alua_tg_pt_gp_alua_access_type.attr,
> + &target_core_alua_tg_pt_gp_alua_supported_states.attr,
>   &target_core_alua_tg_pt_gp_alua_write_metadata.attr,
>   &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
>   &target_core_alua_tg_pt_gp_trans_delay_msecs.attr,

I'm thinking this might be better served by individual attributes
representing the seven supported ALUA states, instead of a single
attribute representing them all..

That would certainly make it easier for userspace to manipulate..

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 02/11] target_core_alua: Store supported ALUA states

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> The supported ALUA states might be different for individual
> devices, so store it in a separate field.
> 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c | 14 --
>  drivers/target/target_core_alua.h | 11 +++
>  include/target/target_core_base.h |  1 +
>  3 files changed, 20 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/target/target_core_alua.c 
> b/drivers/target/target_core_alua.c
> index 8297d37..255e83c 100644
> --- a/drivers/target/target_core_alua.c
> +++ b/drivers/target/target_core_alua.c
> @@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd 
> *cmd)
>   /*
>* Set supported ASYMMETRIC ACCESS State bits
>*/
> - buf[off] = 0x80; /* T_SUP */
> - buf[off] |= 0x40; /* O_SUP */
> - buf[off] |= 0x8; /* U_SUP */
> - buf[off] |= 0x4; /* S_SUP */
> - buf[off] |= 0x2; /* AN_SUP */
> - buf[off++] |= 0x1; /* AO_SUP */
> + buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
>   /*
>* TARGET PORT GROUP
>*/
> @@ -1367,6 +1362,13 @@ struct t10_alua_tg_pt_gp 
> *core_alua_allocate_tg_pt_gp(struct se_device *dev,
>   tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
>   tg_pt_gp->tg_pt_gp_implicit_trans_secs = 
> ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
>  
> + /*
> +  * Enable all supported states
> +  */
> + tg_pt_gp->tg_pt_gp_alua_supported_states =
> + ALUA_T_SUP | ALUA_O_SUP | \
> + ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
> +
>   if (def_group) {
>   spin_lock(&dev->t10_alua.tg_pt_gps_lock);
>   tg_pt_gp->tg_pt_gp_id =
> diff --git a/drivers/target/target_core_alua.h 
> b/drivers/target/target_core_alua.h
> index 74cf0c0..e826a65 100644
> --- a/drivers/target/target_core_alua.h
> +++ b/drivers/target/target_core_alua.h
> @@ -23,6 +23,17 @@
>  #define ALUA_ACCESS_STATE_TRANSITION 0xf
>  
>  /*
> + * from spc4r36j section 6.37 Table 306
> + */
> +#define ALUA_T_SUP   0x80
> +#define ALUA_O_SUP   0x40
> +#define ALUA_LBD_SUP 0x10
> +#define ALUA_U_SUP   0x08
> +#define ALUA_S_SUP   0x04
> +#define ALUA_AN_SUP  0x02
> +#define ALUA_AO_SUP  0x01
> +
> +/*

How about making these the supported bits, TPGS mode, and ALUA access
state definitions common between target_core_alua.c and
scsi_dh_alua.c..?

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 01/11] target core: rename (ex,im)plict -> (ex,im)plicit

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:20 +0200, Hannes Reinecke wrote:
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/target/target_core_alua.c  | 110 
> -
>  drivers/target/target_core_alua.h  |  20 +++---
>  drivers/target/target_core_configfs.c  |  26 
>  drivers/target/target_core_device.c|   6 +-
>  drivers/target/target_core_file.c  |   2 +-
>  drivers/target/target_core_pr.c|  24 +++
>  drivers/target/target_core_spc.c   |   6 +-
>  drivers/target/target_core_transport.c |   4 +-
>  drivers/target/target_core_ua.h|   2 +-
>  include/target/target_core_base.h  |   2 +-
>  10 files changed, 101 insertions(+), 101 deletions(-)
> 

Applied to target-pending/for-next.

Thanks Hannes!

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/5] Updates for tcm_loop

2013-10-16 Thread Nicholas A. Bellinger
On Wed, 2013-10-16 at 09:12 +0200, Hannes Reinecke wrote:
> Hi Nic,
> 
> here are some updates to tcm_loop I've done during ALUA testing.
> I've implemented a 'transport_state' attribute to simulate
> transport failure and added command abort callbacks.
> 
> Hannes Reinecke (5):
>   tcm_loop: Check for valid hba in tcm_loop_drop_nexus()
>   tcm_loop: Implement transport offline
>   tcm_loop: separate out tcm_loop_issue_tmr
>   tcm_loop: TCQ and command abort support
>   tcm_loop: Implement target reset
> 
>  drivers/target/loopback/tcm_loop.c | 233 
> +++--
>  drivers/target/loopback/tcm_loop.h |   6 +
>  include/target/target_core_base.h  |   1 +
>  3 files changed, 204 insertions(+), 36 deletions(-)
> 

Everything looks reasonable to me..  Applied to target-pending/for-next.

Thanks Hannes!

--nab

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] target: Return an error for WRITE SAME with ANCHOR==1

2013-10-16 Thread Nicholas A. Bellinger
On Mon, 2013-10-14 at 15:49 -0700, Roland Dreier wrote:
> From: Roland Dreier 
> 
> Per SBC-3, since we report ANC_SUP==0 in VPD page B2h, we need to return
> an error (ILLEGAL REQUEST/INVALID FIELD IN CDB) for all WRITE SAME
> requests with ANCHOR==1.
> 
> Signed-off-by: Roland Dreier 

Applied to target-pending/master.

Thanks Roland!

--nab

> ---
>  drivers/target/target_core_sbc.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/target/target_core_sbc.c 
> b/drivers/target/target_core_sbc.c
> index 4714c6f8da4b..d9b92b2c524d 100644
> --- a/drivers/target/target_core_sbc.c
> +++ b/drivers/target/target_core_sbc.c
> @@ -263,6 +263,11 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char 
> *flags, struct sbc_ops *o
>   sectors, cmd->se_dev->dev_attrib.max_write_same_len);
>   return TCM_INVALID_CDB_FIELD;
>   }
> + /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
> + if (flags[0] & 0x10) {
> + pr_warn("WRITE SAME with ANCHOR not supported\n");
> + return TCM_INVALID_CDB_FIELD;
> + }
>   /*
>* Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
>* translated into block discard requests within backend code.


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


kernel cant access SATA adapter device

2013-10-16 Thread Robert Story
Hi,

I've got a SATA adapter for a SD card in a Dell Poweredge R610. The BIOS
can see and boot the sdcard, (to Windows, or using syslinux/extlinux), but
when it hands over control to the Linux kernel, the kernel cannot access it.

Here's an excerpt from dmesg:

scsi 0:0:2:0: Direct-Access ATA  FC-1307 SD to CF 1.1  PQ: 0 ANSI: 5
sd 0:0:2:0: Attached scsi generic sg3 type 0
mptsas: ioc0: mptsas_free_fw_event: kfree (fw_event=0x8801ab1ad8c0)
sd 0:0:2:0: [sdc] Spinning up disk .not responding...
sd 0:0:2:0: [sdc] READ CAPACITY(16) failed
sd 0:0:2:0: [sdc] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
sd 0:0:2:0: [sdc] Sense Key : Not Ready [current]
sd 0:0:2:0: [sdc] Add. Sense: Logical unit not ready, initializing command 
required
sd 0:0:2:0: [sdc] READ CAPACITY failed
sd 0:0:2:0: [sdc] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
sd 0:0:2:0: [sdc] Sense Key : Not Ready [current]
sd 0:0:2:0: [sdc] Add. Sense: Logical unit not ready, initializing command 
required
sd 0:0:2:0: [sdc] Test WP failed, assume Write Enabled
sd 0:0:2:0: [sdc] Asking for cache data failed
sd 0:0:2:0: [sdc] Assuming drive cache: write through

After booting and running 'sdparm --command=start /dev/sdc' I can get a
read capacity to work, but cannot access the drive (e.g. fdisk -l /dev/sdc).

If I put the SD card in a USB adapter, it works, and I was able to access
the SD card via the SD adapter in another machine. But our production
machines are dell's, so I really want to get it working there.

I've attached more complete debug info from booting and existing CentOS 6.4
install with the card installed, and a rdsosreport from an attempt to boot
Fedora 20 Alpha.

Any help or suggestions greatly appreciated.


Robert

--
Senior Software Engineer
Parsons Government Services , National Security & Defense Division
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Bug] 12.864681 BUG: lock held when returning to user space!

2013-10-16 Thread James Bottomley
On Tue, 2013-10-08 at 09:45 -0400, Douglas Gilbert wrote:
> On 13-10-08 02:44 AM, vaughan wrote:
> > Hi Madper,
> >
> > CC to Douglas to get comments.
> > I use the rw_semaphore o_sem to protect excl open, introduced in commit
> > 15b06f9a02406e5460001db6d5af5c738cd3d4e7 since v3.12-rc1.
> > Is it forbidden to do like that in kernel?...
> 
> It appears you can not (allow sg_open() to hold a semaphore
> then return to the user space). So you will need to do some
> rework on that patch or revert it.

OK, there being no reply on this, I'll do the revert ... that's all four
patches, correct?

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/3] scsi: Fix erratic device offline during EH

2013-10-16 Thread James Bottomley
On Mon, 2013-09-02 at 13:58 +0200, Hannes Reinecke wrote:
> Commit 18a4d0a22ed6c54b67af7718c305cd010f09ddf8
> (Handle disk devices which can not process medium access commands)
> was introduced to offline any device which cannot process medium
> access commands.
> However, commit 3eef6257de48ff84a5d98ca533685df8a3beaeb8
> (Reduce error recovery time by reducing use of TURs) reduced
> the number of TURs by sending it only on the first failing
> command, which might or might not be a medium access command.
> So in combination this results in an erratic device offlining
> during EH; if the command where the TUR was sent upon happens
> to be a medium access command the device will be set offline,
> if not everything proceeds as normal.
> 
> So instead of checking the EH command in the ->eh_action
> callback we should rather call ->eh_action when we're
> about to finish the command _and_ have sent a TUR previously.
> This should then set the device offline as advertised.
> 
> Cc: Martin K. Petersen 
> Cc: Ewan Milne 
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/scsi/scsi_error.c | 28 +++-
>  1 file changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index abf0916..c88cb7e 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -941,12 +941,6 @@ retry:
>  
>   scsi_eh_restore_cmnd(scmd, &ses);
>  
> - if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
> - struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
> - if (sdrv->eh_action)
> - rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
> - }
> -
>   return rtn;
>  }
>  
> @@ -964,6 +958,18 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
>   return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
>  }
>  
> +static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
> +{
> + static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
> +
> + if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
> + struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
> + if (sdrv->eh_action)
> + rtn = sdrv->eh_action(scmd, tur_command, 6, rtn);

This is all a bit pointless.  You've altered eh_action so it's always
input an eh TUR command, so just eliminate the check of the eh command
and assume it's a TUR in the implementation (i.e. fix up sd.c)

Once that's done, I think the patch looks like the one below, is that
OK?

I still have qualms about the media access check because what can happen
is that we abort, TUR succeeds then the next Media access command fails,
we abort, TUR succeeds etc until the media access timeout goes off.  The
problem is that it never gets escalated to a reset which might fix the
condition.  However, this is beyond the scope of the current patch set.

James

---
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 83e591b..aef80f1 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -923,12 +923,6 @@ retry:
 
scsi_eh_restore_cmnd(scmd, &ses);
 
-   if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
-   struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
-   if (sdrv->eh_action)
-   rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
-   }
-
return rtn;
 }
 
@@ -946,6 +940,16 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
return scsi_send_eh_cmnd(scmd, NULL, 0, scmd->device->eh_timeout, ~0);
 }
 
+static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
+{
+   if (scmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+   struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
+   if (sdrv->eh_action)
+   rtn = sdrv->eh_action(scmd, rtn);
+   }
+   return rtn;
+}
+
 /**
  * scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
  * @scmd:  Original SCSI cmd that eh has finished.
@@ -1094,7 +1098,9 @@ static int scsi_eh_test_devices(struct list_head 
*cmd_list,
 
list_for_each_entry_safe(scmd, next, cmd_list, eh_entry)
if (scmd->device == sdev) {
-   if (finish_cmds)
+   if (finish_cmds &&
+   (try_stu ||
+scsi_eh_action(scmd, SUCCESS) == SUCCESS))
scsi_eh_finish_cmd(scmd, done_q);
else
list_move_tail(&scmd->eh_entry, work_q);
@@ -1208,7 +1214,8 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
!scsi_eh_tur(stu_scmd)) {
list_for_each_entry_safe(scmd, next,
  work_q, eh_entry) {
-   if (scmd-

Re: [PATCH 7/7] scsi: Add 'eh_deadline' to limit SCSI EH runtime

2013-10-16 Thread James Bottomley
On Mon, 2013-07-01 at 08:50 +0200, Hannes Reinecke wrote:
> This patchs adds an 'eh_deadline' sysfs attribute to the scsi
> host which limits the overall runtime of the SCSI EH.
> The 'eh_deadline' value is stored in the now obsolete field
> 'resetting'.
> When a command is failed the start time of the EH is stored
> in 'last_reset'. If the overall runtime of the SCSI EH is longer
> than last_reset + eh_deadline, the EH is short-circuited and
> falls through to issue a host reset only.

OK, so the specific problem with this one is that potentially it will
spend all its time mucking about with aborts (which most often time out
on non FC kit because of the issue problems) and then proceed to host
reset, which mostly does nothing for failing devices.

If you want to impose a deadline, then we need to spend only 50% of the
time attempting aborts and the rest of the time escalating the resets.

[...]
> diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
> index f43de1e..84369f2 100644
> --- a/drivers/scsi/scsi_error.c
> +++ b/drivers/scsi/scsi_error.c
> @@ -89,6 +89,18 @@ void scsi_schedule_eh(struct Scsi_Host *shost)
>  }
>  EXPORT_SYMBOL_GPL(scsi_schedule_eh);
>  
> +static int scsi_host_eh_past_deadline(struct Scsi_Host *shost)
> +{
> + if (!shost->last_reset || !shost->eh_deadline)
> + return 0;
> +
> + if (time_before(jiffies,
> + shost->last_reset + shost->eh_deadline))
> + return 0;
> +
> + return 1;
> +}
> +

What about instead:

static int scsi_host_eh_past_deadline(struct Scsi_Host *shost, int percent) {
if (!shost->last_reset || !shost->eh_deadline)
return 0;

if (time_before(jiffies,
shost->last_reset + shost->eh_deadline * percent/100))
return 0;

return 1;
}

which allows us to have

if (scsi_host_eh_past_deadline(shost, 50)) {

in scsi_eh_abort_cmds()

if (scsi_host_eh_past_deadline(shost, 66) {

in scsi_eh_bus_device_reset()

say 83 in target reset, and 100 in bus reset.

Thus ensuring we at least get a crack at the reset chain?

James

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drivers: scsi: lpfc: Fix typo on NULL assignment

2013-10-16 Thread James Smart

Acked-by: James Smart 

-- james s


On 10/15/2013 8:29 PM, Felipe Pena wrote:

In the lpfc_ct_free_iocb function after freeing associated memory to the
ctiocb->context3, the ctiocb->context1 is set to NULL instead of context3.

Signed-off-by: Felipe Pena 
---
  drivers/scsi/lpfc/lpfc_ct.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 02e8cd9..da61d8d 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -280,7 +280,7 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq 
*ctiocb)
buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
kfree(buf_ptr);
-   ctiocb->context1 = NULL;
+   ctiocb->context3 = NULL;
}
lpfc_sli_release_iocbq(phba, ctiocb);
return 0;
--
1.7.10.4




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: eSATA Drive Detection issues on mvsas

2013-10-16 Thread Praveen Murali


On 10/15/2013 06:11 PM, Dan Williams wrote:

On Tue, Oct 15, 2013 at 5:15 PM, Praveen Murali  wrote:

Dan/James,
  Can you please take a look at this and let me know if I am at the right
place? Or point me in the right direction? As I understand, this deost not
look like an mvsas driver issue.


Looks like a latent bug in libsas to me.  Commit 110dd8f1 "[SCSI]
libsas: fix scr_read/write users and update the libata documentation"
looks like a compile fix when the build was broken by commit  9977126c
"libata: add @is_cmd to ata_tf_to_fis()" where libata changed the
interface for ata_tf_to_fis().  We were passing 0 for pmp prior to
that and changed to 1 here, probably a typo intending 'is_cmd to
always be 1.

Somehow we have gotten away with is_cmd being 0?  Does the following
patch work for you:

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 161c98efade9..d0fb99d5da95 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct
ata_queued_cmd *qc)
 qc->tf.nsect = 0;
 }

-   ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+   ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8*)&task->ata_task.fis);
 task->uldd_task = qc;
 if (ata_is_atapi(qc->tf.protocol)) {
 memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);


Hi Dan,
  I tested this patch and it works great!

Thanks,
Praveen

That being said I don't think anybody has really checked out
port-multiplier support on libsas, but we shouldn't be setting this
bit by default.

--
Dan



On 10/14/2013 05:18 PM, Praveen Murali wrote:

Hi,
   I have couple of external drives (Western Digital and Seagate) that have
an eSATA interface. My Linux box with a Marvell HBA (9445) running Ubuntu
12.04 with 3.2.48 kernel doest not seem to detect the drive. I tried with
the latest upstream kernel and it behaves the same. But both the drives
detect fine if I enter the mvsas BIOS during bootup. So I have hooked up a
SATA analyzer and this is what I found
- When I tried to detect the drives in the mvsas BIOS, all the ATA
commands that the bios issues have the port multiplier byte set to 0.
- If I bootup my Linux system and then connect the drives, the first
IDENTIFY command has the port multiplier set to 0 (this one is successful)
and the subsequent IDENTIFY command has port multiplier set to 1 (this one
fails).

I assume the first IDENTIFY is coming from the BIOS, not Linux correct?


- If I connect any other SATA drives I have to the HBA, all the ATA
commands have port multiplier set to 1 but they detects and work fine.

Just to rule out the port-multiplier possibility I changed the following
line in drivers/scsi/libsas/sas_ata.c - fucntion sas_ata_qc_issue()

ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);

to

ata_tf_to_fis(&qc->tf, 0, 0, (u8*)&task->ata_task.fis);

now all my drives seem to detect just fine. I believe, the eSATA interface
on these external drives is a port multiplier, which is why the command
fails. Also, the normal drives ignore this field thats why they work fine
with port multiplier being set to either 0 or 1.

Question(s): Are my above assumtions correct? If so, what is the reasoning
behind setting the port multiplier to 1 by default in libsas layer?

Thanks,
Praveen




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How to online remove an error scsi disk from the system?

2013-10-16 Thread taco
On Fri, Feb 01, 2013 at 02:13:16PM +0800, Tao Ma wrote:
> Hi All,
>   In our product system, we have several sata disks attached to one
> machine. So when one of the disk fails, the jbd2(yes, we use ext4) will
> hang forever and we will get something in /var/log/messages like below.
> It seems to me that the io sent to the scsi layer is never returned back
> with -EIO which is a little bit surprised for me(It should be a timeout
> somewhere, right?). We have tried echo "offline" >
> /sys/block/sdl/device/state, but it doesn't work. So is there any way
> for us to let the scsi device returns all the io requests back with EIO
> so that all the end_io can be called accordingly? Am I missing something
> here?
> 
> Thanks,
> Tao
> 
> 
> sd 0:0:11:0: attempting task abort! scmd(88180e900580)
It seems that IO timeout cause HBA's driver to abort scmd,
the aborted IO came back with scmd->result = DID_RESET << 16;
with this result code the Middle layer of scsi will retry this IO.
IO timeout again due to Bad disk so, this IO loop forever and
never come back.

might it is a bug of mpt2sas driver.

> sd 0:0:11:0: [sdl] CDB: Write(10): 2a 00 0d ca e0 3f 00 04 00 00
> target0:0:11: handle(0x0015), sas_address(0x500e004aaa0b), phy(11)
> target0:0:11: enclosure_logical_id(0x500e004aaa00), slot(11)
> INFO: task jbd2/sdl1-8:4629 blocked for more than 120 seconds.
> "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> jbd2/sdl1-8   D  0  4629  2 0x
>  88180aa79ae0 0046 88180aa79aa8 
>  88007ce0fe40 00015f40 8818102c0638 8818102c0080
>  880a9184a100 8818102c0638 000105006028 0001
> Call Trace:
>  [] ? cpumask_next_and+0x25/0x40
>  [] ? read_tsc+0x16/0x40
>  [] ? ktime_get_ts+0xa9/0xe0
>  [] ? read_tsc+0x16/0x40
>  [] ? ktime_get_ts+0xa9/0xe0
>  [] io_schedule+0x73/0xc0
>  [] sync_page+0x38/0x50
>  [] __wait_on_bit+0x5e/0x90
>  [] ? sync_page+0x0/0x50
>  [] wait_on_page_bit+0x75/0x80
>  [] ? wake_bit_function+0x0/0x40
>  [] ? pagevec_lookup_tag+0x27/0x40
>  [] write_cache_pages+0x1d5/0x440
>  [] ? __writepage+0x0/0x40
>  [] generic_writepages+0x24/0x30
>  [] jbd2_journal_commit_transaction+0x3e9/0x1490 [jbd2]
>  [] ? try_to_del_timer_sync+0x49/0xe0
>  [] kjournald2+0xb4/0x220 [jbd2]
>  [] ? autoremove_wake_function+0x0/0x40
>  [] ? kjournald2+0x0/0x220 [jbd2]
>  [] kthread+0x96/0xa0
>  [] child_rip+0xa/0x20
>  [] ? kthread+0x0/0xa0
>  [] ? child_rip+0x0/0x20
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] drivers: scsi: lpfc: Remove useless casting in lpfc_init.c

2013-10-16 Thread Geyslan G. Bem
Casting (void *) value returned by kzalloc is useless
as mentioned in Documentation/CodingStyle, Chap 14.

Signed-off-by: Geyslan G. Bem 
---
 drivers/scsi/lpfc/lpfc_init.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 647f5bf..bc417d5 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4733,9 +4733,8 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
}
 
if (!phba->sli.ring)
-   phba->sli.ring = (struct lpfc_sli_ring *)
-   kzalloc(LPFC_SLI3_MAX_RING *
-   sizeof(struct lpfc_sli_ring), GFP_KERNEL);
+   phba->sli.ring = kzalloc(LPFC_SLI3_MAX_RING *
+sizeof(struct lpfc_sli_ring), 
GFP_KERNEL);
if (!phba->sli.ring)
return -ENOMEM;
 
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] drivers: scsi: Remove useless casting in hpsa.c

2013-10-16 Thread Geyslan G. Bem
Casting (void *) value returned by kmalloc is useless
as mentioned in Documentation/CodingStyle, Chap 14.

Signed-off-by: Geyslan G. Bem 
---
 drivers/scsi/hpsa.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 891c86b..896a57d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3093,8 +3093,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, 
void __user *argp)
return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
-   ioc = (BIG_IOCTL_Command_struct *)
-   kmalloc(sizeof(*ioc), GFP_KERNEL);
+   ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
if (!ioc) {
status = -ENOMEM;
goto cleanup1;
-- 
1.8.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH][SCSI] megaraid_sas: Fix synchronization problem between sysPD IO path and AEN path

2013-10-16 Thread Sumit.Saxena
There is syncronization problem between sysPD IO path and AEN path. Driver 
maintains instance->pd_list[] array, which will get updated(by calling function 
megasas_get_pd_list[]), whenever any of below events occurs-

MR_EVT_PD_INSERTED
MR_EVT_PD_REMOVED
MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED
MR_EVT_FOREIGN_CFG_IMPORTED

At same time running sysPD IO will be accessing the same array 
instance->pd_list[], which is getting updated in AEN path, because
of this IO may not get correct PD info from instance->pd_list[] array.

Signed-off-by: Adam Radford 
Signed-off-by: Sumit Saxena 
---
diff --git a/drivers/scsi/megaraid/megaraid_sas.h 
b/drivers/scsi/megaraid/megaraid_sas.h
index 0c73ba4..e9e543c 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1531,6 +1531,7 @@ struct megasas_instance {
struct megasas_register_set __iomem *reg_set;
u32 *reply_post_host_index_addr[MR_MAX_MSIX_REG_ARRAY];
struct megasas_pd_list  pd_list[MEGASAS_MAX_PD];
+   struct megasas_pd_list  local_pd_list[MEGASAS_MAX_PD];
u8 ld_ids[MEGASAS_MAX_LD_IDS];
s8 init_id;
 
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c 
b/drivers/scsi/megaraid/megaraid_sas_base.c
index e62ff02..83ebc75 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3194,21 +3194,23 @@ megasas_get_pd_list(struct megasas_instance *instance)
 (le32_to_cpu(ci->count) <
  (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
 
-   memset(instance->pd_list, 0,
+   memset(instance->local_pd_list, 0,
MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
 
for (pd_index = 0; pd_index < le32_to_cpu(ci->count); 
pd_index++) {
 
-   instance->pd_list[le16_to_cpu(pd_addr->deviceId)].tid   
=
+   
instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].tid =
le16_to_cpu(pd_addr->deviceId);
-   
instance->pd_list[le16_to_cpu(pd_addr->deviceId)].driveType =
+   
instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].driveType   =
pd_addr->scsiDevType;
-   
instance->pd_list[le16_to_cpu(pd_addr->deviceId)].driveState=
+   
instance->local_pd_list[le16_to_cpu(pd_addr->deviceId)].driveState  =
MR_PD_STATE_SYSTEM;
pd_addr++;
}
}
 
+   memcpy(instance->pd_list, instance->local_pd_list,
+   sizeof(instance->pd_list));
pci_free_consistent(instance->pdev,
MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
ci, ci_h);

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Bug 63141] New: Linux Kernel will shows "Got wrong page" in kernel log when Linux kernel tries to send SCSI ModeSense command with Page code 0x08 (Caching Mode Page)

2013-10-16 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=63141

Bug ID: 63141
   Summary: Linux Kernel will shows "Got wrong page" in kernel log
when Linux kernel tries to send SCSI ModeSense command
with Page code 0x08 (Caching Mode Page)
   Product: IO/Storage
   Version: 2.5
Kernel Version: 3.6.11
  Hardware: All
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: low
  Priority: P1
 Component: SCSI
  Assignee: linux-scsi@vger.kernel.org
  Reporter: leoche...@gmail.com
Regression: No

Created attachment 111291
  --> https://bugzilla.kernel.org/attachment.cgi?id=111291&action=edit
SourceCodeComparsionBetween2.6.xAnd3.9.1

Reporter: Leo Chen (Li-Chung Chen)
Report Date: 10/16/13

Issue Descrition: In Linux kernel 3.6.11, sd.c file, host calls
sd_read_cache_type() function to read physical disk or volume cache type. This
function works properly on most physical disks but will fail to read the cache
type on LSI raid volume. The error message in Linux Kernel is "Got wrong page".

However, the Linux kernel works properly in kernel 2.6.x.

Suggestion: If we restore below codes from 2.6.x to 3.6.11 in
sd.c,sd_read_cache_type()function, then the kernel won't report "got wrong
page" in the log. 

/* Take headers and block descriptors into account */
len += data.header_length + data.block_descriptor_length;

I also referenced the SPC-4(SCSI Primary Commands - 4) specification from T10
to check if it's LSI firmware problem to response the wrong parameter length to
the host. According to the description in SPC below, it looks like LSI logical
volume doesn't voilate the specification to response the MODE DATA LENGTH value
to host.

[SPC-4 Description about the Mode Parameter]
When using the MODE SENSE command, the MODE DATA LENGTH field indicates the
length in bytes of the following
data that is available to be transferred. The mode data length does not include
the number of bytes in the MODE
DATA LENGTH field. 
[SPC-4 Description about the Mode Parameter]

Therefore, I'd like to suggest the Linux Kernel to add the code above to make
the kernel handle the cache reading properly.

-- 
You are receiving this mail because:
You are the assignee for the bug.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] target_core_alua: Referrals configfs integration

2013-10-16 Thread Hannes Reinecke
Referrals need an LBA map, which needs to be kept
consistent across all target port groups. So
instead of tying the map to the target port groups
I've implemented a single attribute containing the
entire map.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c  | 101 +++
 drivers/target/target_core_alua.h  |   8 ++
 drivers/target/target_core_configfs.c  | 171 +
 drivers/target/target_core_device.c|   1 +
 drivers/target/target_core_transport.c |  28 +-
 5 files changed, 308 insertions(+), 1 deletion(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 8f66146..9dd01ff 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -1340,6 +1340,107 @@ static int core_alua_set_tg_pt_secondary_state(
return 0;
 }
 
+struct t10_alua_lba_map *
+core_alua_allocate_lba_map(struct list_head *list,
+  u64 first_lba, u64 last_lba)
+{
+   struct t10_alua_lba_map *lba_map;
+
+   lba_map = kmem_cache_zalloc(t10_alua_lba_map_cache, GFP_KERNEL);
+   if (!lba_map) {
+   pr_err("Unable to allocate struct t10_alua_lba_map\n");
+   return ERR_PTR(-ENOMEM);
+   }
+   INIT_LIST_HEAD(&lba_map->lba_map_mem_list);
+   lba_map->lba_map_first_lba = first_lba;
+   lba_map->lba_map_last_lba = last_lba;
+
+   list_add_tail(&lba_map->lba_map_list, list);
+   return lba_map;
+}
+
+int
+core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *lba_map,
+  int pg_id, int state)
+{
+   struct t10_alua_lba_map_member *lba_map_mem;
+
+   list_for_each_entry(lba_map_mem, &lba_map->lba_map_mem_list,
+   lba_map_mem_list) {
+   if (lba_map_mem->lba_map_mem_alua_pg_id == pg_id) {
+   pr_err("Duplicate pg_id %d in lba_map\n", pg_id);
+   return -EINVAL;
+   }
+   }
+
+   lba_map_mem = kmem_cache_zalloc(t10_alua_lba_map_mem_cache, GFP_KERNEL);
+   if (!lba_map_mem) {
+   pr_err("Unable to allocate struct t10_alua_lba_map_mem\n");
+   return -ENOMEM;
+   }
+   lba_map_mem->lba_map_mem_alua_state = state;
+   lba_map_mem->lba_map_mem_alua_pg_id = pg_id;
+
+   list_add_tail(&lba_map_mem->lba_map_mem_list,
+ &lba_map->lba_map_mem_list);
+   return 0;
+}
+
+void
+core_alua_free_lba_map(struct list_head *lba_list)
+{
+   struct t10_alua_lba_map *lba_map, *lba_map_tmp;
+   struct t10_alua_lba_map_member *lba_map_mem, *lba_map_mem_tmp;
+
+   list_for_each_entry_safe(lba_map, lba_map_tmp, lba_list,
+lba_map_list) {
+   list_for_each_entry_safe(lba_map_mem, lba_map_mem_tmp,
+&lba_map->lba_map_mem_list,
+lba_map_mem_list) {
+   list_del(&lba_map_mem->lba_map_mem_list);
+   kmem_cache_free(t10_alua_lba_map_mem_cache,
+   lba_map_mem);
+   }
+   list_del(&lba_map->lba_map_list);
+   kmem_cache_free(t10_alua_lba_map_cache, lba_map);
+   }
+}
+
+void
+core_alua_set_lba_map(struct se_device *dev, struct list_head *lba_map_list,
+ int segment_size, int segment_mult)
+{
+   struct list_head old_lba_map_list;
+   struct t10_alua_tg_pt_gp *tg_pt_gp;
+   int activate = 0, supported;
+
+   INIT_LIST_HEAD(&old_lba_map_list);
+   spin_lock(&dev->t10_alua.lba_map_lock);
+   dev->t10_alua.lba_map_segment_size = segment_size;
+   dev->t10_alua.lba_map_segment_multiplier = segment_mult;
+   list_splice_init(&dev->t10_alua.lba_map_list, &old_lba_map_list);
+   if (lba_map_list) {
+   list_splice_init(lba_map_list, &dev->t10_alua.lba_map_list);
+   activate = 1;
+   }
+   spin_unlock(&dev->t10_alua.lba_map_lock);
+   spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+   list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list,
+   tg_pt_gp_list) {
+
+   if (!tg_pt_gp->tg_pt_gp_valid_id)
+   continue;
+   supported = tg_pt_gp->tg_pt_gp_alua_supported_states;
+   if (activate)
+   supported |= ALUA_LBD_SUP;
+   else
+   supported &= ~ALUA_LBD_SUP;
+   tg_pt_gp->tg_pt_gp_alua_supported_states = supported;
+   }
+   spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+   core_alua_free_lba_map(&old_lba_map_list);
+}
+
 struct t10_alua_lu_gp *
 core_alua_allocate_lu_gp(const char *name, int def_group)
 {
diff --git a/drivers/target/target_core_alua.h 
b/drivers/target/target_core_alua.h
index 47950cd..0a7d65e 100644
--- a/drivers/target/target_core_alua.h
+++ b/driv

[PATCH 1/2] target_core_alua: Referrals infrastructure

2013-10-16 Thread Hannes Reinecke
Add infrastructure for referrals.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 151 ++
 drivers/target/target_core_alua.h |   4 +-
 drivers/target/target_core_configfs.c |  12 ++-
 drivers/target/target_core_device.c   |   2 +
 drivers/target/target_core_sbc.c  |   5 +-
 drivers/target/target_core_spc.c  |  20 +
 include/scsi/scsi.h   |   1 +
 include/target/target_core_base.h |  18 
 8 files changed, 209 insertions(+), 4 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 166bee6..8f66146 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -56,6 +56,75 @@ static LIST_HEAD(lu_gps_list);
 struct t10_alua_lu_gp *default_lu_gp;
 
 /*
+ * REPORT REFERRALS
+ *
+ * See sbc3r35 section 5.23
+ */
+sense_reason_t
+target_emulate_report_referrals(struct se_cmd *cmd)
+{
+   struct se_device *dev = cmd->se_dev;
+   struct t10_alua_lba_map *map;
+   struct t10_alua_lba_map_member *map_mem;
+   unsigned char *buf;
+   u32 rd_len = 0, off;
+
+   if (cmd->data_length < 4) {
+   pr_warn("REPORT REFERRALS allocation length %u too"
+   " small\n", cmd->data_length);
+   return TCM_INVALID_CDB_FIELD;
+   }
+
+   buf = transport_kmap_data_sg(cmd);
+   if (!buf)
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+   off = 4;
+   spin_lock(&dev->t10_alua.lba_map_lock);
+   if (list_empty(&dev->t10_alua.lba_map_list)) {
+   spin_unlock(&dev->t10_alua.lba_map_lock);
+   transport_kunmap_data_sg(cmd);
+
+   return TCM_UNSUPPORTED_SCSI_OPCODE;
+   }
+
+   list_for_each_entry(map, &dev->t10_alua.lba_map_list,
+   lba_map_list) {
+   int desc_num = off + 3;
+   int pg_num;
+
+   off += 4;
+   put_unaligned_be64(map->lba_map_first_lba, &buf[off]);
+   off += 8;
+   put_unaligned_be64(map->lba_map_last_lba, &buf[off]);
+   off += 8;
+   rd_len += 20;
+   pg_num = 0;
+   list_for_each_entry(map_mem, &map->lba_map_mem_list,
+   lba_map_mem_list) {
+   buf[off++] = map_mem->lba_map_mem_alua_state & 0x0f;
+   off++;
+   buf[off++] = (map_mem->lba_map_mem_alua_pg_id >> 8) & 
0xff;
+   buf[off++] = (map_mem->lba_map_mem_alua_pg_id & 0xff);
+   rd_len += 4;
+   pg_num++;
+   }
+   buf[desc_num] = pg_num;
+   }
+   spin_unlock(&dev->t10_alua.lba_map_lock);
+
+   /*
+* Set the RETURN DATA LENGTH set in the header of the DataIN Payload
+*/
+   put_unaligned_be16(rd_len, &buf[2]);
+
+   transport_kunmap_data_sg(cmd);
+
+   target_complete_cmd(cmd, GOOD);
+   return 0;
+}
+
+/*
  * REPORT_TARGET_PORT_GROUPS
  *
  * See spc4r17 section 6.27
@@ -389,6 +458,80 @@ static inline int core_alua_state_nonoptimized(
return 0;
 }
 
+static inline int core_alua_state_lba_dependent(
+   struct se_cmd *cmd,
+   struct t10_alua_tg_pt_gp *tg_pt_gp,
+   u8 *alua_ascq)
+{
+   struct se_device *dev = cmd->se_dev;
+   u32 segment_size, segment_mult, sectors;
+   u64 lba;
+
+   /* Only need to check for cdb actually containing LBAs */
+   if (!cmd->se_cmd_flags & SCF_SCSI_DATA_CDB)
+   return 0;
+
+   spin_lock(&dev->t10_alua.lba_map_lock);
+   segment_size = dev->t10_alua.lba_map_segment_size;
+   segment_mult = dev->t10_alua.lba_map_segment_multiplier;
+   sectors = cmd->data_length / dev->dev_attrib.block_size;
+
+   lba = cmd->t_task_lba;
+   while (lba < cmd->t_task_lba + sectors) {
+   struct t10_alua_lba_map *cur_map = NULL, *map;
+   struct t10_alua_lba_map_member *map_mem;
+
+   list_for_each_entry(map, &dev->t10_alua.lba_map_list,
+   lba_map_list) {
+   u64 start_lba, last_lba;
+   u64 first_lba = map->lba_map_first_lba;
+
+   if (segment_mult) {
+   start_lba = lba % (segment_size * segment_mult);
+   last_lba = first_lba + segment_size - 1;
+   if (start_lba >= first_lba &&
+   start_lba <= last_lba) {
+   lba += segment_size;
+   cur_map = map;
+   break;
+   }
+   } else {
+   last_lba = map->lba_map_last_lba;
+   if (lba >= first_lba &&

[PATCH 0/2] TCM Referrals support

2013-10-16 Thread Hannes Reinecke
Hi Nic,

I've finally bitten the bullet and implemented referrals
support for TCM. It has been on my to-do list for a long
time, but finally I've gotten around to actually _do_ anything about it.

TCM now will enable referrals support when an appropriate
map is being fed into 'lba_map'. Format there is:
   
 ... 
  ...
  
 is the number of the first target port group,
 is a character denominating the ALUA access state:
'O' for 'Active/Optimized', 'A' for 'Active/Non-Optimized',
'S' for 'Standby', and 'U' for 'Unavailable'.
For further details see SBC-3, Section 'Referrals'.
  
Yes, I know, it's far from perfect and violates the
'one item per attribute' rule. But breaking this
down into several attributes and ensure the update
is done consistently _and_ atomically is beyond my
configfs skills. So there.

Hannes Reinecke (2):
  target_core_alua: Referrals infrastructure
  target_core_alua: Referrals configfs integration

 drivers/target/target_core_alua.c  | 252 +
 drivers/target/target_core_alua.h  |  12 +-
 drivers/target/target_core_configfs.c  | 183 +++-
 drivers/target/target_core_device.c|   3 +
 drivers/target/target_core_sbc.c   |   5 +-
 drivers/target/target_core_spc.c   |  20 +++
 drivers/target/target_core_transport.c |  28 +++-
 include/scsi/scsi.h|   1 +
 include/target/target_core_base.h  |  18 +++
 9 files changed, 517 insertions(+), 5 deletions(-)

-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: PROBLEM: special sense code asc,ascq=04h,0Ch abort scsi scan in the middle

2013-10-16 Thread vaughan
On 10/16/2013 02:52 PM, Hannes Reinecke wrote:
> But seeing that this approach raises quite some issues I've attached a
> different patch. Vaughan, could you test with that, too? Should be
> functionally equivalent to the previous one. Cheers, Hannes 
Of course. This one is more clear to express our intention than setting
PQ 3 to break out.

Vaughan
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/11] target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED

2013-10-16 Thread Hannes Reinecke
Rename ALUA_ACCESS_STATE_OPTMIZED to
ALUA_ACCESS_STATE_OPTIMIZED.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 10 +-
 drivers/target/target_core_alua.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 255e83c..593de80 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -561,12 +561,12 @@ target_alua_state_check(struct se_cmd *cmd)
nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
/*
-* Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional
+* Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional
 * statement so the compiler knows explicitly to check this case first.
 * For the Optimized ALUA access state case, we want to process the
 * incoming fabric cmd ASAP..
 */
-   if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTMIZED)
+   if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED)
return 0;
 
switch (out_alua_state) {
@@ -621,7 +621,7 @@ static sense_reason_t
 core_alua_check_transition(int state, int *primary)
 {
switch (state) {
-   case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
+   case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
case ALUA_ACCESS_STATE_STANDBY:
case ALUA_ACCESS_STATE_UNAVAILABLE:
@@ -649,7 +649,7 @@ core_alua_check_transition(int state, int *primary)
 static char *core_alua_dump_state(int state)
 {
switch (state) {
-   case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
+   case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
return "Active/Optimized";
case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
return "Active/NonOptimized";
@@ -1349,7 +1349,7 @@ struct t10_alua_tg_pt_gp 
*core_alua_allocate_tg_pt_gp(struct se_device *dev,
tg_pt_gp->tg_pt_gp_dev = dev;
tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN;
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
-   ALUA_ACCESS_STATE_ACTIVE_OPTMIZED);
+   ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
/*
 * Enable both explicit and implicit ALUA support by default
 */
diff --git a/drivers/target/target_core_alua.h 
b/drivers/target/target_core_alua.h
index e826a65..88e2e83 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -15,7 +15,7 @@
  *
  * from spc4r17 section 6.27 Table 245
  */
-#define ALUA_ACCESS_STATE_ACTIVE_OPTMIZED  0x0
+#define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED 0x0
 #define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED 0x1
 #define ALUA_ACCESS_STATE_STANDBY  0x2
 #define ALUA_ACCESS_STATE_UNAVAILABLE  0x3
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/11] target_core_alua: Validate ALUA state transition

2013-10-16 Thread Hannes Reinecke
As we now can modify the list of supported states we need to
validate the requested ALUA state when doing a state transition.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 85 ++-
 1 file changed, 56 insertions(+), 29 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index a16115e..a420778 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -41,7 +41,8 @@
 #include "target_core_alua.h"
 #include "target_core_ua.h"
 
-static sense_reason_t core_alua_check_transition(int state, int *primary);
+static sense_reason_t core_alua_check_transition(int state, int valid,
+int *primary);
 static int core_alua_set_tg_pt_secondary_state(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
struct se_port *port, int explicit, int offline);
@@ -210,7 +211,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
unsigned char *ptr;
sense_reason_t rc = TCM_NO_SENSE;
u32 len = 4; /* Skip over RESERVED area in header */
-   int alua_access_state, primary = 0;
+   int alua_access_state, primary = 0, valid_states;
u16 tg_pt_id, rtpi;
 
if (!l_port)
@@ -252,6 +253,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
goto out;
}
+   valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
 
ptr = &buf[4]; /* Skip over RESERVED area in header */
 
@@ -263,7 +265,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
 * the state is a primary or secondary target port asymmetric
 * access state.
 */
-   rc = core_alua_check_transition(alua_access_state, &primary);
+   rc = core_alua_check_transition(alua_access_state,
+   valid_states, &primary);
if (rc) {
/*
 * If the SET TARGET PORT GROUPS attempts to establish
@@ -614,21 +617,57 @@ out:
return 0;
 }
 
+static char *core_alua_dump_state(int state)
+{
+   switch (state) {
+   case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
+   return "Active/Optimized";
+   case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
+   return "Active/NonOptimized";
+   case ALUA_ACCESS_STATE_STANDBY:
+   return "Standby";
+   case ALUA_ACCESS_STATE_UNAVAILABLE:
+   return "Unavailable";
+   case ALUA_ACCESS_STATE_OFFLINE:
+   return "Offline";
+   case ALUA_ACCESS_STATE_TRANSITION:
+   return "Transitioning";
+   default:
+   return "Unknown";
+   }
+
+   return NULL;
+}
+
 /*
  * Check implicit and explicit ALUA state change request.
  */
 static sense_reason_t
-core_alua_check_transition(int state, int *primary)
+core_alua_check_transition(int state, int valid, int *primary)
 {
+   /*
+* OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
+* defined as primary target port asymmetric access states.
+*/
switch (state) {
case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
+   if (!(valid & ALUA_AO_SUP))
+   goto not_supported;
+   *primary = 1;
+   break;
case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
+   if (!(valid & ALUA_AN_SUP))
+   goto not_supported;
+   *primary = 1;
+   break;
case ALUA_ACCESS_STATE_STANDBY:
+   if (!(valid & ALUA_S_SUP))
+   goto not_supported;
+   *primary = 1;
+   break;
case ALUA_ACCESS_STATE_UNAVAILABLE:
-   /*
-* OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are
-* defined as primary target port asymmetric access states.
-*/
+   if (!(valid & ALUA_U_SUP))
+   goto not_supported;
*primary = 1;
break;
case ALUA_ACCESS_STATE_OFFLINE:
@@ -636,6 +675,8 @@ core_alua_check_transition(int state, int *primary)
 * OFFLINE state is defined as a secondary target port
 * asymmetric access state.
 */
+   if (!(valid & ALUA_O_SUP))
+   goto not_supported;
*primary = 0;
break;
default:
@@ -644,26 +685,11 @@ core_alua_check_transition(int state, int *primary)
}
 
return 0;
-}
 
-static char *core_alua_dump_state(int state)
-{
-   switch (state) {
-   case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
-   return "Active/Optimized";
-   case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
-   return "Active/NonOptimized"

[PATCH 08/11] target_core_alua: store old and pending ALUA state

2013-10-16 Thread Hannes Reinecke
During state transition we should be storing both the original
and the pending state.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 15 ++-
 include/target/target_core_base.h |  6 --
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index b1d08bf..33e3f23 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -804,12 +804,15 @@ static int core_alua_do_transition_tg_pt(
struct se_lun_acl *lacl;
struct se_port *port;
struct t10_alua_tg_pt_gp_member *mem;
-   int old_state = 0;
+
/*
 * Save the old primary ALUA access state, and set the current state
 * to ALUA_ACCESS_STATE_TRANSITION.
 */
-   old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
+   tg_pt_gp->tg_pt_gp_alua_previous_state =
+   atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
+   tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
+
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
ALUA_ACCESS_STATE_TRANSITION);
tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
@@ -890,13 +893,15 @@ static int core_alua_do_transition_tg_pt(
/*
 * Set the current primary ALUA access state to the requested new state
 */
-   atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
+   atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
+  tg_pt_gp->tg_pt_gp_alua_pending_state);
 
pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
" from primary access state %s to %s\n", (explicit) ? 
"explicit" :
"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
-   tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state),
-   core_alua_dump_state(new_state));
+   tg_pt_gp->tg_pt_gp_id,
+   core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state),
+   core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
 
return 0;
 }
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 933c59d..67b6ca2 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -282,8 +282,10 @@ struct t10_alua_lu_gp_member {
 struct t10_alua_tg_pt_gp {
u16 tg_pt_gp_id;
int tg_pt_gp_valid_id;
-   int tg_pt_gp_alua_supported_states;
-   int tg_pt_gp_alua_access_status;
+   u8  tg_pt_gp_alua_pending_state;
+   u8  tg_pt_gp_alua_previous_state;
+   u8  tg_pt_gp_alua_supported_states;
+   u8  tg_pt_gp_alua_access_status;
int tg_pt_gp_alua_access_type;
int tg_pt_gp_nonop_delay_msecs;
int tg_pt_gp_trans_delay_msecs;
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/11] target_core_mod: ALUA updates

2013-10-16 Thread Hannes Reinecke
Hi Nic,

here are some updates to TCM ALUA handling. Apart from some
minor fixes and spellchecks the main features are:
- Make supported states configurable:
  We should make the list of supported ALUA states configurable,
  as some setups would possibly like to support a small subset
  of ALUA states only.
- Asynchronous transitioning: I've switched 'transitioning'
  handling to use a workqueue, that should allow us to simulate
  asynchronous transitioning modes. IE TCM should now be capable
  of handling requests while in transitioning, and properly terminate
  these with the correct sense code.
- Include target device descriptor in VPD page 83
  For the ALUA device handler we'd need to identify the target device
  where a given target port belongs to. So include the respective
  values in the VPD page.

Hannes Reinecke (11):
  target core: rename (ex,im)plict -> (ex,im)plicit
  target_core_alua: Store supported ALUA states
  target_core_alua: Make supported states configurable
  target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED
  target_core_alua: spellcheck
  target_core_alua: Validate ALUA state transition
  target_core_alua: Allocate ALUA metadata on demand
  target_core_alua: store old and pending ALUA state
  target_core_alua: Use workqueue for ALUA transitioning
  target_core: simplify scsi_name_len calculation
  target_core_spc: Include target device descriptor in VPD page 83

 drivers/target/target_core_alua.c  | 456 -
 drivers/target/target_core_alua.h  |  36 ++-
 drivers/target/target_core_configfs.c  |  76 +-
 drivers/target/target_core_device.c|   6 +-
 drivers/target/target_core_file.c  |   2 +-
 drivers/target/target_core_pr.c|  24 +-
 drivers/target/target_core_spc.c   |  62 -
 drivers/target/target_core_transport.c |   4 +-
 drivers/target/target_core_ua.h|   2 +-
 include/target/target_core_base.h  |  14 +-
 10 files changed, 442 insertions(+), 240 deletions(-)

-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/11] target_core_alua: Make supported states configurable

2013-10-16 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_configfs.c | 50 +++
 1 file changed, 50 insertions(+)

diff --git a/drivers/target/target_core_configfs.c 
b/drivers/target/target_core_configfs.c
index d4c28a3..53e9e00 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -2131,6 +2131,55 @@ static ssize_t 
target_core_alua_tg_pt_gp_store_attr_alua_access_type(
 SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
 
 /*
+ * alua_supported_states
+ */
+static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_supported_states(
+   struct t10_alua_tg_pt_gp *tg_pt_gp,
+   char *page)
+{
+   return sprintf(page, "%02x\n",
+   tg_pt_gp->tg_pt_gp_alua_supported_states);
+}
+
+static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_supported_states(
+   struct t10_alua_tg_pt_gp *tg_pt_gp,
+   const char *page,
+   size_t count)
+{
+   unsigned long tmp;
+   int new_states, valid_states, ret;
+
+   if (!tg_pt_gp->tg_pt_gp_valid_id) {
+   pr_err("Unable to do set supported ALUA states on non"
+   " valid tg_pt_gp ID: %hu\n",
+   tg_pt_gp->tg_pt_gp_valid_id);
+   return -EINVAL;
+   }
+
+   ret = strict_strtoul(page, 0, &tmp);
+   if (ret < 0) {
+   pr_err("Unable to extract new supported ALUA states"
+   " from %s\n", page);
+   return -EINVAL;
+   }
+   new_states = (int)tmp;
+   valid_states = ALUA_T_SUP | ALUA_O_SUP | ALUA_LBD_SUP | \
+   ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+
+
+   if (new_states & ~valid_states) {
+   pr_err("Illegal supported ALUA states: 0x%02x\n",
+   new_states);
+   return -EINVAL;
+   }
+
+   tg_pt_gp->tg_pt_gp_alua_supported_states = new_states;
+   return count;
+}
+
+SE_DEV_ALUA_TG_PT_ATTR(alua_supported_states, S_IRUGO | S_IWUSR);
+
+/*
  * alua_write_metadata
  */
 static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata(
@@ -2350,6 +2399,7 @@ static struct configfs_attribute 
*target_core_alua_tg_pt_gp_attrs[] = {
&target_core_alua_tg_pt_gp_alua_access_state.attr,
&target_core_alua_tg_pt_gp_alua_access_status.attr,
&target_core_alua_tg_pt_gp_alua_access_type.attr,
+   &target_core_alua_tg_pt_gp_alua_supported_states.attr,
&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/11] target_core_alua: Use workqueue for ALUA transitioning

2013-10-16 Thread Hannes Reinecke
Use a workqueue for processing ALUA state transitions; this allows
us to process implicit delay properly.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 174 +++---
 include/target/target_core_base.h |   4 +
 2 files changed, 128 insertions(+), 50 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 33e3f23..166bee6 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -761,8 +761,7 @@ static int core_alua_write_tpg_metadata(
  * Called with tg_pt_gp->tg_pt_gp_md_mutex held
  */
 static int core_alua_update_tpg_primary_metadata(
-   struct t10_alua_tg_pt_gp *tg_pt_gp,
-   int primary_state)
+   struct t10_alua_tg_pt_gp *tg_pt_gp)
 {
unsigned char *md_buf;
struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
@@ -781,7 +780,8 @@ static int core_alua_update_tpg_primary_metadata(
"tg_pt_gp_id=%hu\n"
"alua_access_state=0x%02x\n"
"alua_access_status=0x%02x\n",
-   tg_pt_gp->tg_pt_gp_id, primary_state,
+   tg_pt_gp->tg_pt_gp_id,
+   tg_pt_gp->tg_pt_gp_alua_pending_state,
tg_pt_gp->tg_pt_gp_alua_access_status);
 
snprintf(path, ALUA_METADATA_PATH_LEN,
@@ -793,36 +793,17 @@ static int core_alua_update_tpg_primary_metadata(
return rc;
 }
 
-static int core_alua_do_transition_tg_pt(
-   struct t10_alua_tg_pt_gp *tg_pt_gp,
-   struct se_port *l_port,
-   struct se_node_acl *nacl,
-   int new_state,
-   int explicit)
+static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
 {
+   struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work,
+   struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work);
+   struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
struct se_dev_entry *se_deve;
struct se_lun_acl *lacl;
struct se_port *port;
struct t10_alua_tg_pt_gp_member *mem;
-
-   /*
-* Save the old primary ALUA access state, and set the current state
-* to ALUA_ACCESS_STATE_TRANSITION.
-*/
-   tg_pt_gp->tg_pt_gp_alua_previous_state =
-   atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
-   tg_pt_gp->tg_pt_gp_alua_pending_state = new_state;
-
-   atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
-   ALUA_ACCESS_STATE_TRANSITION);
-   tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
-   ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
-   ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
-   /*
-* Check for the optional ALUA primary state transition delay
-*/
-   if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0)
-   msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs);
+   bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status ==
+ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG);
 
spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list,
@@ -857,9 +838,12 @@ static int core_alua_do_transition_tg_pt(
if (!lacl)
continue;
 
-   if (explicit &&
-  (nacl != NULL) && (nacl == lacl->se_lun_nacl) &&
-  (l_port != NULL) && (l_port == port))
+   if ((tg_pt_gp->tg_pt_gp_alua_access_status ==
+ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
+  (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) &&
+   (tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) 
&&
+  (tg_pt_gp->tg_pt_gp_alua_port != NULL) &&
+   (tg_pt_gp->tg_pt_gp_alua_port == port))
continue;
 
core_scsi3_ua_allocate(lacl->se_lun_nacl,
@@ -887,7 +871,7 @@ static int core_alua_do_transition_tg_pt(
 */
if (tg_pt_gp->tg_pt_gp_write_metadata) {
mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex);
-   core_alua_update_tpg_primary_metadata(tg_pt_gp, new_state);
+   core_alua_update_tpg_primary_metadata(tg_pt_gp);
mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex);
}
/*
@@ -902,6 +886,87 @@ static int core_alua_do_transition_tg_pt(
tg_pt_gp->tg_pt_gp_id,
core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state),
core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
+   spin_lock(&dev->t10_alua.tg_pt_gps_lock);
+   atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
+   smp_mb__after_atomic_dec();
+   spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
+
+   if (tg_pt_gp->tg_pt_gp_transition_complete)
+   com

[PATCH 07/11] target_core_alua: Allocate ALUA metadata on demand

2013-10-16 Thread Hannes Reinecke
We should only allocate ALUA metadata if we're actually going
to write them.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 70 +--
 drivers/target/target_core_alua.h |  3 ++
 include/target/target_core_base.h |  3 --
 3 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index a420778..b1d08bf 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -762,16 +762,22 @@ static int core_alua_write_tpg_metadata(
  */
 static int core_alua_update_tpg_primary_metadata(
struct t10_alua_tg_pt_gp *tg_pt_gp,
-   int primary_state,
-   unsigned char *md_buf)
+   int primary_state)
 {
+   unsigned char *md_buf;
struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn;
char path[ALUA_METADATA_PATH_LEN];
-   int len;
+   int len, rc;
+
+   md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL);
+   if (!md_buf) {
+   pr_err("Unable to allocate buf for ALUA metadata\n");
+   return -ENOMEM;
+   }
 
memset(path, 0, ALUA_METADATA_PATH_LEN);
 
-   len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len,
+   len = snprintf(md_buf, ALUA_MD_BUF_LEN,
"tg_pt_gp_id=%hu\n"
"alua_access_state=0x%02x\n"
"alua_access_status=0x%02x\n",
@@ -782,14 +788,15 @@ static int core_alua_update_tpg_primary_metadata(
"/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0],
config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item));
 
-   return core_alua_write_tpg_metadata(path, md_buf, len);
+   rc = core_alua_write_tpg_metadata(path, md_buf, len);
+   kfree(md_buf);
+   return rc;
 }
 
 static int core_alua_do_transition_tg_pt(
struct t10_alua_tg_pt_gp *tg_pt_gp,
struct se_port *l_port,
struct se_node_acl *nacl,
-   unsigned char *md_buf,
int new_state,
int explicit)
 {
@@ -877,8 +884,7 @@ static int core_alua_do_transition_tg_pt(
 */
if (tg_pt_gp->tg_pt_gp_write_metadata) {
mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex);
-   core_alua_update_tpg_primary_metadata(tg_pt_gp,
-   new_state, md_buf);
+   core_alua_update_tpg_primary_metadata(tg_pt_gp, new_state);
mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex);
}
/*
@@ -909,19 +915,12 @@ int core_alua_do_port_transition(
struct t10_alua_lu_gp *lu_gp;
struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem;
struct t10_alua_tg_pt_gp *tg_pt_gp;
-   unsigned char *md_buf;
int primary, valid_states;
 
valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
if (core_alua_check_transition(new_state, valid_states, &primary) != 0)
return -EINVAL;
 
-   md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL);
-   if (!md_buf) {
-   pr_err("Unable to allocate buf for ALUA metadata\n");
-   return -ENOMEM;
-   }
-
local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem;
spin_lock(&local_lu_gp_mem->lu_gp_mem_lock);
lu_gp = local_lu_gp_mem->lu_gp;
@@ -939,10 +938,9 @@ int core_alua_do_port_transition(
 * success.
 */
core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
-   md_buf, new_state, explicit);
+   new_state, explicit);
atomic_dec(&lu_gp->lu_gp_ref_cnt);
smp_mb__after_atomic_dec();
-   kfree(md_buf);
return 0;
}
/*
@@ -992,7 +990,7 @@ int core_alua_do_port_transition(
 * success.
 */
core_alua_do_transition_tg_pt(tg_pt_gp, port,
-   nacl, md_buf, new_state, explicit);
+   nacl, new_state, explicit);
 
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
@@ -1014,7 +1012,6 @@ int core_alua_do_port_transition(
 
atomic_dec(&lu_gp->lu_gp_ref_cnt);
smp_mb__after_atomic_dec();
-   kfree(md_buf);
return 0;
 }
 
@@ -1023,13 +1020,18 @@ int core_alua_do_port_transition(
  */
 static int core_alua_update_tpg_secondary_metadata(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
-   struct se_port *port,
-   unsigned char *md_buf,
-   u32 md_buf_len)
+   struct se_port *port)
 {
+   unsigned char *md_buf;
struct se_portal_group *se_tpg = port->sep_tpg;
char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN];
-   int len;
+   int len, rc;
+
+   md_buf = kzallo

[PATCH 02/11] target_core_alua: Store supported ALUA states

2013-10-16 Thread Hannes Reinecke
The supported ALUA states might be different for individual
devices, so store it in a separate field.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 14 --
 drivers/target/target_core_alua.h | 11 +++
 include/target/target_core_base.h |  1 +
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 8297d37..255e83c 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd 
*cmd)
/*
 * Set supported ASYMMETRIC ACCESS State bits
 */
-   buf[off] = 0x80; /* T_SUP */
-   buf[off] |= 0x40; /* O_SUP */
-   buf[off] |= 0x8; /* U_SUP */
-   buf[off] |= 0x4; /* S_SUP */
-   buf[off] |= 0x2; /* AN_SUP */
-   buf[off++] |= 0x1; /* AO_SUP */
+   buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
/*
 * TARGET PORT GROUP
 */
@@ -1367,6 +1362,13 @@ struct t10_alua_tg_pt_gp 
*core_alua_allocate_tg_pt_gp(struct se_device *dev,
tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
tg_pt_gp->tg_pt_gp_implicit_trans_secs = 
ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
 
+   /*
+* Enable all supported states
+*/
+   tg_pt_gp->tg_pt_gp_alua_supported_states =
+   ALUA_T_SUP | ALUA_O_SUP | \
+   ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
+
if (def_group) {
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
tg_pt_gp->tg_pt_gp_id =
diff --git a/drivers/target/target_core_alua.h 
b/drivers/target/target_core_alua.h
index 74cf0c0..e826a65 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -23,6 +23,17 @@
 #define ALUA_ACCESS_STATE_TRANSITION   0xf
 
 /*
+ * from spc4r36j section 6.37 Table 306
+ */
+#define ALUA_T_SUP 0x80
+#define ALUA_O_SUP 0x40
+#define ALUA_LBD_SUP   0x10
+#define ALUA_U_SUP 0x08
+#define ALUA_S_SUP 0x04
+#define ALUA_AN_SUP0x02
+#define ALUA_AO_SUP0x01
+
+/*
  * REPORT_TARGET_PORT_GROUP STATUS CODE
  *
  * from spc4r17 section 6.27 Table 246
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 1c6e54d..21f4bd5 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -282,6 +282,7 @@ struct t10_alua_lu_gp_member {
 struct t10_alua_tg_pt_gp {
u16 tg_pt_gp_id;
int tg_pt_gp_valid_id;
+   int tg_pt_gp_alua_supported_states;
int tg_pt_gp_alua_access_status;
int tg_pt_gp_alua_access_type;
int tg_pt_gp_nonop_delay_msecs;
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/11] target_core_alua: spellcheck

2013-10-16 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 593de80..a16115e 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -325,7 +325,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
} else {
/*
-* Extact the RELATIVE TARGET PORT IDENTIFIER to 
identify
+* Extract the RELATIVE TARGET PORT IDENTIFIER to 
identify
 * the Target Port in question for the the incoming
 * SET_TARGET_PORT_GROUPS op.
 */
@@ -482,7 +482,7 @@ static inline int core_alua_state_transition(
u8 *alua_ascq)
 {
/*
-* Allowed CDBs for ALUA_ACCESS_STATE_TRANSITIO as defined by
+* Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by
 * spc4r17 section 5.9.2.5
 */
switch (cdb[0]) {
@@ -510,9 +510,9 @@ static inline int core_alua_state_transition(
 }
 
 /*
- * return 1: Is used to signal LUN not accecsable, and check condition/not 
ready
+ * return 1: Is used to signal LUN not accessible, and check condition/not 
ready
  * return 0: Used to signal success
- * reutrn -1: Used to signal failure, and invalid cdb field
+ * return -1: Used to signal failure, and invalid cdb field
  */
 sense_reason_t
 target_alua_state_check(struct se_cmd *cmd)
@@ -797,7 +797,7 @@ static int core_alua_do_transition_tg_pt(
 * change, a device server shall establish a unit attention
 * condition for the initiator port associated with every I_T
 * nexus with the additional sense code set to ASYMMETRIC
-* ACCESS STATE CHAGED.
+* ACCESS STATE CHANGED.
 *
 * After an explicit target port asymmetric access state
 * change, a device server shall establish a unit attention
@@ -941,7 +941,7 @@ int core_alua_do_port_transition(
continue;
/*
 * If the target behavior port asymmetric access state
-* is changed for any target port group accessiable via
+* is changed for any target port group accessible via
 * a logical unit within a LU group, the target port
 * behavior group asymmetric access states for the same
 * target port group accessible via other logical units
@@ -1227,7 +1227,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
 * struct se_device is released via core_alua_free_lu_gp_mem().
 *
 * If the passed lu_gp does NOT match the default_lu_gp, assume
-* we want to re-assocate a given lu_gp_mem with default_lu_gp.
+* we want to re-associate a given lu_gp_mem with default_lu_gp.
 */
spin_lock(&lu_gp_mem->lu_gp_mem_lock);
if (lu_gp != default_lu_gp)
@@ -1467,7 +1467,7 @@ void core_alua_free_tg_pt_gp(
 * been called from target_core_alua_drop_tg_pt_gp().
 *
 * Here we remove *tg_pt_gp from the global list so that
-* no assications *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
+* no associations *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
 * can be made while we are releasing struct t10_alua_tg_pt_gp.
 */
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
@@ -1503,7 +1503,7 @@ void core_alua_free_tg_pt_gp(
 * core_alua_free_tg_pt_gp_mem().
 *
 * If the passed tg_pt_gp does NOT match the default_tg_pt_gp,
-* assume we want to re-assocate a given tg_pt_gp_mem with
+* assume we want to re-associate a given tg_pt_gp_mem with
 * default_tg_pt_gp.
 */
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/11] target core: rename (ex,im)plict -> (ex,im)plicit

2013-10-16 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/target/target_core_alua.c  | 110 -
 drivers/target/target_core_alua.h  |  20 +++---
 drivers/target/target_core_configfs.c  |  26 
 drivers/target/target_core_device.c|   6 +-
 drivers/target/target_core_file.c  |   2 +-
 drivers/target/target_core_pr.c|  24 +++
 drivers/target/target_core_spc.c   |   6 +-
 drivers/target/target_core_transport.c |   4 +-
 drivers/target/target_core_ua.h|   2 +-
 include/target/target_core_base.h  |   2 +-
 10 files changed, 101 insertions(+), 101 deletions(-)

diff --git a/drivers/target/target_core_alua.c 
b/drivers/target/target_core_alua.c
index 4724410..8297d37 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -44,7 +44,7 @@
 static sense_reason_t core_alua_check_transition(int state, int *primary);
 static int core_alua_set_tg_pt_secondary_state(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
-   struct se_port *port, int explict, int offline);
+   struct se_port *port, int explicit, int offline);
 
 static u16 alua_lu_gps_counter;
 static u32 alua_lu_gps_count;
@@ -175,7 +175,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
if (ext_hdr != 0) {
buf[4] = 0x10;
/*
-* Set the implict transition time (in seconds) for the 
application
+* Set the implicit transition time (in seconds) for the 
application
 * client to use as a base for it's transition timeout value.
 *
 * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the 
LUN
@@ -188,7 +188,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
if (tg_pt_gp)
-   buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
+   buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
}
}
@@ -199,7 +199,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
 }
 
 /*
- * SET_TARGET_PORT_GROUPS for explict ALUA operation.
+ * SET_TARGET_PORT_GROUPS for explicit ALUA operation.
  *
  * See spc4r17 section 6.35
  */
@@ -232,7 +232,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
/*
-* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
+* Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed
 * for the local tg_pt_gp.
 */
l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
@@ -251,9 +251,9 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
}
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
 
-   if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) {
+   if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
-   " while TPGS_EXPLICT_ALUA is disabled\n");
+   " while TPGS_EXPLICIT_ALUA is disabled\n");
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
goto out;
}
@@ -620,7 +620,7 @@ out:
 }
 
 /*
- * Check implict and explict ALUA state change request.
+ * Check implicit and explicit ALUA state change request.
  */
 static sense_reason_t
 core_alua_check_transition(int state, int *primary)
@@ -676,10 +676,10 @@ char *core_alua_dump_status(int status)
switch (status) {
case ALUA_STATUS_NONE:
return "None";
-   case ALUA_STATUS_ALTERED_BY_EXPLICT_STPG:
-   return "Altered by Explict STPG";
-   case ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA:
-   return "Altered by Implict ALUA";
+   case ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG:
+   return "Altered by Explicit STPG";
+   case ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA:
+   return "Altered by Implicit ALUA";
default:
return "Unknown";
}
@@ -770,7 +770,7 @@ static int core_alua_do_transition_tg_pt(
struct se_node_acl *nacl,
unsigned char *md_buf,
int new_state,
-   int explict)
+   int explicit)
 {
struct se_dev_entry *se_deve;
struct se_lun_acl *lacl;
@@ -784,9 +784,9 @@ static int core_alua_do_transition_tg_pt(
old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
ALUA_ACCESS_STATE_TRANSITION);
-   tg_pt_gp->tg_pt_gp_alua_access_status = (explict) ?
-   ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
-

[PATCH 2/5] tcm_loop: Implement transport offline

2013-10-16 Thread Hannes Reinecke
Add attribute 'transport_status' to simulate link failure.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/loopback/tcm_loop.c | 53 +-
 drivers/target/loopback/tcm_loop.h |  4 +++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index 57d5a95..f81ebe4 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -178,7 +178,10 @@ static void tcm_loop_submission_work(struct work_struct 
*work)
set_host_byte(sc, DID_NO_CONNECT);
goto out_done;
}
-
+   if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
+   set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
+   goto out_done;
+   }
tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus) {
scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
@@ -1064,8 +1067,56 @@ check_newline:
 
 TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
 
+static ssize_t tcm_loop_tpg_show_transport_status(
+   struct se_portal_group *se_tpg,
+   char *page)
+{
+   struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
+   struct tcm_loop_tpg, tl_se_tpg);
+   const char *status = NULL;
+   ssize_t ret = -EINVAL;
+
+   switch (tl_tpg->tl_transport_status) {
+   case TCM_TRANSPORT_ONLINE:
+   status = "online";
+   break;
+   case TCM_TRANSPORT_OFFLINE:
+   status = "offline";
+   break;
+   default:
+   break;
+   }
+
+   if (status)
+   ret = snprintf(page, PAGE_SIZE, "%s\n", status);
+
+   return ret;
+}
+
+static ssize_t tcm_loop_tpg_store_transport_status(
+   struct se_portal_group *se_tpg,
+   const char *page,
+   size_t count)
+{
+   struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
+   struct tcm_loop_tpg, tl_se_tpg);
+
+   if (!strncmp(page, "online", 6)) {
+   tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
+   return count;
+   }
+   if (!strncmp(page, "offline", 7)) {
+   tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
+   return count;
+   }
+   return -EINVAL;
+}
+
+TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
+
 static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
&tcm_loop_tpg_nexus.attr,
+   &tcm_loop_tpg_transport_status.attr,
NULL,
 };
 
diff --git a/drivers/target/loopback/tcm_loop.h 
b/drivers/target/loopback/tcm_loop.h
index dd7a84e..56528f7 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -40,8 +40,12 @@ struct tcm_loop_nacl {
struct se_node_acl se_node_acl;
 };
 
+#define TCM_TRANSPORT_ONLINE 0
+#define TCM_TRANSPORT_OFFLINE 1
+
 struct tcm_loop_tpg {
unsigned short tl_tpgt;
+   unsigned short tl_transport_status;
atomic_t tl_tpg_port_count;
struct se_portal_group tl_se_tpg;
struct tcm_loop_hba *tl_hba;
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] tcm_loop: Implement target reset

2013-10-16 Thread Hannes Reinecke
Implement target reset by resetting the transport status.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/loopback/tcm_loop.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index febe166..d52c0aa 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -392,6 +392,32 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
 }
 
+static int tcm_loop_target_reset(struct scsi_cmnd *sc)
+{
+   struct tcm_loop_hba *tl_hba;
+   struct tcm_loop_tpg *tl_tpg;
+   int ret = FAILED;
+
+   /*
+* Locate the tcm_loop_hba_t pointer
+*/
+   tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
+   if (!tl_hba) {
+   pr_err("Unable to perform device reset without"
+   " active I_T Nexus\n");
+   return FAILED;
+   }
+   /*
+* Locate the tl_tpg pointer from TargetID in sc->device->id
+*/
+   tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
+   if (tl_tpg) {
+   tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
+   return SUCCESS;
+   }
+   return FAILED;
+}
+
 static int tcm_loop_slave_alloc(struct scsi_device *sd)
 {
set_bit(QUEUE_FLAG_BIDI, &sd->request_queue->queue_flags);
@@ -421,6 +447,7 @@ static struct scsi_host_template tcm_loop_driver_template = 
{
.change_queue_type  = tcm_loop_change_queue_type,
.eh_abort_handler = tcm_loop_abort_task,
.eh_device_reset_handler = tcm_loop_device_reset,
+   .eh_target_reset_handler = tcm_loop_target_reset,
.can_queue  = 1024,
.this_id= -1,
.sg_tablesize   = 256,
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] tcm_loop: Check for valid hba in tcm_loop_drop_nexus()

2013-10-16 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/target/loopback/tcm_loop.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index 0f6d69d..57d5a95 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -932,7 +932,10 @@ static int tcm_loop_drop_nexus(
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_hba *tl_hba = tpg->tl_hba;
 
-   tl_nexus = tpg->tl_hba->tl_nexus;
+   if (!tl_hba)
+   return -ENODEV;
+
+   tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus)
return -ENODEV;
 
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/5] Updates for tcm_loop

2013-10-16 Thread Hannes Reinecke
Hi Nic,

here are some updates to tcm_loop I've done during ALUA testing.
I've implemented a 'transport_state' attribute to simulate
transport failure and added command abort callbacks.

Hannes Reinecke (5):
  tcm_loop: Check for valid hba in tcm_loop_drop_nexus()
  tcm_loop: Implement transport offline
  tcm_loop: separate out tcm_loop_issue_tmr
  tcm_loop: TCQ and command abort support
  tcm_loop: Implement target reset

 drivers/target/loopback/tcm_loop.c | 233 +++--
 drivers/target/loopback/tcm_loop.h |   6 +
 include/target/target_core_base.h  |   1 +
 3 files changed, 204 insertions(+), 36 deletions(-)

-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] tcm_loop: TCQ and command abort support

2013-10-16 Thread Hannes Reinecke
Implement TCQ support, which enables us to do proper command
abort, too.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/loopback/tcm_loop.c | 71 +++---
 drivers/target/loopback/tcm_loop.h |  2 ++
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index 7232976..febe166 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -135,6 +135,21 @@ static int tcm_loop_change_queue_depth(
return sdev->queue_depth;
 }
 
+static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag)
+{
+   if (sdev->tagged_supported) {
+   scsi_set_tag_type(sdev, tag);
+
+   if (tag)
+   scsi_activate_tcq(sdev, sdev->queue_depth);
+   else
+   scsi_deactivate_tcq(sdev, sdev->queue_depth);
+   } else
+   tag = 0;
+
+   return tag;
+}
+
 /*
  * Locate the SAM Task Attr from struct scsi_cmnd *
  */
@@ -236,6 +251,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, 
struct scsi_cmnd *sc)
}
 
tl_cmd->sc = sc;
+   tl_cmd->sc_cmd_tag = sc->tag;
INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
queue_work(tcm_loop_workqueue, &tl_cmd->work);
return 0;
@@ -247,7 +263,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, 
struct scsi_cmnd *sc)
  */
 static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
  struct tcm_loop_nexus *tl_nexus,
- int lun, enum tcm_tmreq_table tmr)
+ int lun, int task, enum tcm_tmreq_table tmr)
 {
struct se_cmd *se_cmd = NULL;
struct se_session *se_sess;
@@ -283,6 +299,9 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
if (rc < 0)
goto release;
 
+   if (tmr == TMR_ABORT_TASK)
+   se_cmd->se_tmr_req->ref_task_tag = task;
+
/*
 * Locate the underlying TCM struct se_lun
 */
@@ -310,6 +329,36 @@ release:
return ret;
 }
 
+static int tcm_loop_abort_task(struct scsi_cmnd *sc)
+{
+   struct tcm_loop_hba *tl_hba;
+   struct tcm_loop_nexus *tl_nexus;
+   struct tcm_loop_tpg *tl_tpg;
+   int ret = FAILED;
+
+   /*
+* Locate the tcm_loop_hba_t pointer
+*/
+   tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
+   /*
+* Locate the tl_nexus and se_sess pointers
+*/
+   tl_nexus = tl_hba->tl_nexus;
+   if (!tl_nexus) {
+   pr_err("Unable to perform device reset without"
+   " active I_T Nexus\n");
+   return FAILED;
+   }
+
+   /*
+* Locate the tl_tpg pointer from TargetID in sc->device->id
+*/
+   tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
+   ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
+sc->tag, TMR_ABORT_TASK);
+   return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
+}
+
 /*
  * Called from SCSI EH process context to issue a LUN_RESET TMR
  * to struct scsi_device
@@ -338,8 +387,8 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 * Locate the tl_tpg pointer from TargetID in sc->device->id
 */
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
-   ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus,
-sc->device->lun, TMR_LUN_RESET);
+   ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
+0, TMR_LUN_RESET);
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
 }
 
@@ -351,6 +400,15 @@ static int tcm_loop_slave_alloc(struct scsi_device *sd)
 
 static int tcm_loop_slave_configure(struct scsi_device *sd)
 {
+   if (sd->tagged_supported) {
+   scsi_activate_tcq(sd, sd->queue_depth);
+   scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG,
+   sd->host->cmd_per_lun);
+   } else {
+   scsi_adjust_queue_depth(sd, 0,
+   sd->host->cmd_per_lun);
+   }
+
return 0;
 }
 
@@ -360,6 +418,8 @@ static struct scsi_host_template tcm_loop_driver_template = 
{
.name   = "TCM_Loopback",
.queuecommand   = tcm_loop_queuecommand,
.change_queue_depth = tcm_loop_change_queue_depth,
+   .change_queue_type  = tcm_loop_change_queue_type,
+   .eh_abort_handler = tcm_loop_abort_task,
.eh_device_reset_handler = tcm_loop_device_reset,
.can_queue  = 1024,
.this_id= -1,
@@ -719,7 +779,10 @@ static void tcm_loop_set_default_node_attributes(struct 
se_node_acl *se_acl)
 
 static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
 {
-   return 1;
+   struct tcm_loop_cmd *tl_cmd 

[PATCH 3/5] tcm_loop: separate out tcm_loop_issue_tmr

2013-10-16 Thread Hannes Reinecke
No functional change.

Signed-off-by: Hannes Reinecke 
---
 drivers/target/loopback/tcm_loop.c | 83 +++---
 include/target/target_core_base.h  |  1 +
 2 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index f81ebe4..7232976 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -245,41 +245,21 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, 
struct scsi_cmnd *sc)
  * Called from SCSI EH process context to issue a LUN_RESET TMR
  * to struct scsi_device
  */
-static int tcm_loop_device_reset(struct scsi_cmnd *sc)
+static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
+ struct tcm_loop_nexus *tl_nexus,
+ int lun, enum tcm_tmreq_table tmr)
 {
struct se_cmd *se_cmd = NULL;
-   struct se_portal_group *se_tpg;
struct se_session *se_sess;
+   struct se_portal_group *se_tpg;
struct tcm_loop_cmd *tl_cmd = NULL;
-   struct tcm_loop_hba *tl_hba;
-   struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_tmr *tl_tmr = NULL;
-   struct tcm_loop_tpg *tl_tpg;
-   int ret = FAILED, rc;
-   /*
-* Locate the tcm_loop_hba_t pointer
-*/
-   tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
-   /*
-* Locate the tl_nexus and se_sess pointers
-*/
-   tl_nexus = tl_hba->tl_nexus;
-   if (!tl_nexus) {
-   pr_err("Unable to perform device reset without"
-   " active I_T Nexus\n");
-   return FAILED;
-   }
-   se_sess = tl_nexus->se_sess;
-   /*
-* Locate the tl_tpg and se_tpg pointers from TargetID in sc->device->id
-*/
-   tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
-   se_tpg = &tl_tpg->tl_se_tpg;
+   int ret = TMR_FUNCTION_FAILED, rc;
 
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
if (!tl_cmd) {
pr_err("Unable to allocate memory for tl_cmd\n");
-   return FAILED;
+   return ret;
}
 
tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
@@ -290,6 +270,8 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
init_waitqueue_head(&tl_tmr->tl_tmr_wait);
 
se_cmd = &tl_cmd->tl_se_cmd;
+   se_tpg = &tl_tpg->tl_se_tpg;
+   se_sess = tl_nexus->se_sess;
/*
 * Initialize struct se_cmd descriptor from target_core_mod 
infrastructure
 */
@@ -297,17 +279,20 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
DMA_NONE, MSG_SIMPLE_TAG,
&tl_cmd->tl_sense_buf[0]);
 
-   rc = core_tmr_alloc_req(se_cmd, tl_tmr, TMR_LUN_RESET, GFP_KERNEL);
+   rc = core_tmr_alloc_req(se_cmd, tl_tmr, tmr, GFP_KERNEL);
if (rc < 0)
goto release;
+
/*
-* Locate the underlying TCM struct se_lun from sc->device->lun
+* Locate the underlying TCM struct se_lun
 */
-   if (transport_lookup_tmr_lun(se_cmd, sc->device->lun) < 0)
+   if (transport_lookup_tmr_lun(se_cmd, lun) < 0) {
+   ret = TMR_LUN_DOES_NOT_EXIST;
goto release;
+   }
/*
-* Queue the TMR to TCM Core and sleep waiting for 
tcm_loop_queue_tm_rsp()
-* to wake us up.
+* Queue the TMR to TCM Core and sleep waiting for
+* tcm_loop_queue_tm_rsp() to wake us up.
 */
transport_generic_handle_tmr(se_cmd);
wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
@@ -315,8 +300,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 * The TMR LUN_RESET has completed, check the response status and
 * then release allocations.
 */
-   ret = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
-   SUCCESS : FAILED;
+   ret = se_cmd->se_tmr_req->response;
 release:
if (se_cmd)
transport_generic_free_cmd(se_cmd, 1);
@@ -326,6 +310,39 @@ release:
return ret;
 }
 
+/*
+ * Called from SCSI EH process context to issue a LUN_RESET TMR
+ * to struct scsi_device
+ */
+static int tcm_loop_device_reset(struct scsi_cmnd *sc)
+{
+   struct tcm_loop_hba *tl_hba;
+   struct tcm_loop_nexus *tl_nexus;
+   struct tcm_loop_tpg *tl_tpg;
+   int ret = FAILED;
+
+   /*
+* Locate the tcm_loop_hba_t pointer
+*/
+   tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
+   /*
+* Locate the tl_nexus and se_sess pointers
+*/
+   tl_nexus = tl_hba->tl_nexus;
+   if (!tl_nexus) {
+   pr_err("Unable to perform device reset without"
+   " active I_T Nexus\n");
+   return FAILED;
+   }
+   /*
+* Locate the tl_tpg