[REGRESSION v4.3] scsi_dh: use-after-free when removing scsi device

2015-09-29 Thread Junichi Nomura
With v4.3-rc3, stress testing of SCSI device addition/removal quickly
trigger random crash in memory allocator (e.g. __kmalloc).  I found that
a commit 086b91d052eb ("scsi_dh: integrate into the core SCSI code")
moved the call of scsi_dh->detach() to very early part of sdev tear down
process (scsi_remove_device()). As a result, related data structure such
as alua_dh_data can be freed while rtpg/stpg are still in-flight.

Here is an example of crash log.  You can see strange rtpg log
'port group 25a43100' for 514:0:0:0 after 'Detached':

>> [  170.518427] sd 517:0:0:0: [sdd] Attached SCSI disk
>> [  170.528681] sd 514:0:0:0: alua: Detached
>> [  170.528720] sd 517:0:0:0: alua: Detached
>> [  170.528827] sd 515:0:0:0: alua: Detached
>> [  170.528922] sd 514:0:0:0: alua: port group 25a43100 state A non-preferred 
>> supports tolusna
>> [  170.528924] device-mapper: multipath: Failing path 8:16.
>> [  170.529059] device-mapper: table: 253:0: multipath: error getting device
>> [  170.529060] device-mapper: ioctl: error adding target to table
>> [  170.529212] device-mapper: multipath: Failing path 8:0.
>> [  170.540498] sd 516:0:0:0: alua: Detached
>> [  170.540543] sd 515:0:0:0: [sdb] Synchronizing SCSI cache
>> [  170.541849] sd 517:0:0:0: [sdd] Synchronizing SCSI cache
>> [  170.542393] sd 514:0:0:0: [sda] Synchronizing SCSI cache
>> [  170.546836] BUG: unable to handle kernel paging request at 
>> 00102800
>> [  170.548499] IP: [] kmem_cache_alloc_trace+0x7a/0x1f0
>> [  170.550069] sd 516:0:0:0: [sdc] Synchronizing SCSI cache
>> [  170.551540] PGD 0 
>> [  170.552686] Oops:  [#1] SMP 
>> [  170.553946] Modules linked in: dm_queue_length sd_mod iscsi_tcp 
>> libiscsi_tcp libiscsi scsi_transport_iscsi nls_utf8 isofs cirrus ttm 
>> drm_kms_helper syscopyarea crct10dif_pclmul sysfillrect crc32_pclmul sys 
>> imgblt ghash_clmulni_intel fb_sys_fops aesni_intel drm lrw gf128mul 
>> virtio_console glue_helper ablk_helper ppdev cryptd parport_pc i2c_piix4 
>> serio_raw pcspkr parport i2c_core virtio_balloon acpi_cpufreq xfs l ibcrc32c 
>> sr_mod cdrom ata_generic pata_acpi virtio_blk virtio_net crc32c_intel floppy 
>> ata_piix virtio_pci libata virtio_ring virtio sunrpc dm_mirror 
>> dm_region_hash dm_log dm_multipath dm_mod
>> [  170.564500] CPU: 2 PID: 2255 Comm: systemd-udevd Not tainted 4.3.0-rc3 #1
>> [  170.566078] Hardware name: 
>> [  170.567655] task: 88002c729580 ti: 8802212e8000 task.ti: 
>> 8802212e8000
>> [  170.569320] RIP: 0010:[]  [] 
>> kmem_cache_alloc_trace+0x7a/0x1f0
>> [  170.571208] RSP: 0018:8802212ebe40  EFLAGS: 00010282
>> [  170.572715] RAX:  RBX: 80d0 RCX:
>> 00017622
>> [  170.574461] RDX: 00017621 RSI: 80d0 RDI:
>> 880237001800
>> [  170.576148] RBP: 8802212ebe78 R08: 0001a160 R09:
>> 8800afda5460
>> [  170.577902] R10: 81206740 R11: 0202 R12:
>> 80d0
>> [  170.579530] R13: 880237001800 R14: 00102800 R15:
>> 880237001800
>> [  170.581276] FS:  7fd7236ae880() GS:88023fd0()
>> knlGS:
>> [  170.583110] CS:  0010 DS:  ES:  CR0: 80050033
>> [  170.584596] CR2: 00102800 CR3: 000225199000 CR4:
>> 001406e0
>> [  170.586320] Stack:
>> [  170.587495]  81206740 0088 8800bb1cec60
>> 8802212ebf28
>> [  170.589280]  0800 8802212ebf20 558c20687b50
>> 8802212ebe90
>> [  170.591131]  81206740 8800bb1cec60 8802212ebed8
>> 81206c56
>> [  170.592929] Call Trace:
>> [  170.594228]  [] ? alloc_pipe_info+0x20/0xb0
>> [  170.595895]  [] alloc_pipe_info+0x20/0xb0
>> [  170.597637]  [] create_pipe_files+0x56/0x230
>> [  170.599337]  [] ? __audit_syscall_entry+0xaf/0x100
>> [  170.601071]  [] __do_pipe_flags+0x34/0xe0
>> [  170.602688]  [] SyS_pipe2+0x2f/0xb0
>> [  170.604215]  [] entry_SYSCALL_64_fastpath+0x12/0x71
>> [  170.605863] Code: 4c 03 05 2a d3 e2 7e 4d 8b 30 49 8b 40 10 4d 85 f6 0f 
>> 84 22 01 00 00 48 85 c0 0f 84 19 01 00 00 49 63 47 20 48 8d 4a 01 4d 8b 07 
>> <49> 8b 1c 06 4c 89 f0 65 49 0f c7 08 0f 94 c0 84 c0 74 b9 49 63 
>> [  170.610895] RIP  [] kmem_cache_alloc_trace+0x7a/0x1f0
>> [  170.612728]  RSP 
>> [  170.614244] CR2: 00102800
>> [  170.615745] ---[ end trace 02faa1e1a864f6bd ]---
>> [  170.617351] Kernel panic - not syncing: Fatal exception
>> [  170.619462] Kernel Offset: disabled
>> [  170.620946] ---[ end Kernel panic - not syncing: Fatal exception


Attached below is a sample reproducer for ALUA capable storage.

--- cut here --
#!/bin/bash

# Set appropriate values for your storage
hostno=2
host=host${hostno}
dev=${hostno}:0:0:0

service multipathd stop
multipath -F

n=1
while true; do
echo "== loop $n ==" > /dev/kmsg

echo "-- scan $host --" > /dev/kmsg
echo '- - -' > /sys/class/scsi_host/${host}/scan

echo "-- activate $dev --" > /dev/kmsg
   

Re: [PATCH v4 32/32] cxlflash: Fix to avoid potential deadlock on EEH

2015-09-29 Thread Daniel Axtens
"Matthew R. Ochs"  writes:

> Ioctl threads that use scsi_execute() can run for an excessive amount
> of time due to the fact that they have lengthy timeouts and retry logic
> built in. Under normal operation this is not an issue. However, once EEH
> enters the picture, a long execution time coupled with the possibility
> that a timeout can trigger entry to the driver via registered reset
> callbacks becomes a liability.
>
> In particular, a deadlock can occur when an EEH event is encountered
> while in running in scsi_execute(). As part of the recovery, the EEH
> handler drains all currently running ioctls, waiting until they have
> completed before proceeding with a reset. As the scsi_execute()'s are
> situated on the ioctl path, the EEH handler will wait until they (and
> the remainder of the ioctl handler they're associated with) have
> completed. Normally this would not be much of an issue aside from the
> longer recovery period. Unfortunately, the scsi_execute() triggers a
> reset when it times out. The reset handler will see that the device is
> already being reset and wait until that reset completed. This creates
> a condition where the EEH handler becomes stuck, infinitely waiting for
> the ioctl thread to complete.
>
> To avoid this behavior, temporarily unmark the scsi_execute() threads
> as an ioctl thread by releasing the ioctl read semaphore. This allows
> the EEH handler to proceed with a recovery while the thread is still
> running. Once the scsi_execute() returns, the ioctl read semaphore is
> reacquired and the adapter state is rechecked in case it changed while
> inside of scsi_execute(). The state check will wait if the adapter is
> still being recovered or returns a failure if the recovery failed. In
> the event that the adapter reset failed, the failure is simply returned
> as the ioctl would be unable to continue.

Yep, looks good.

Reviewed-by: Daniel Axtens 

>
> Reported-by: Brian King 
> Signed-off-by: Matthew R. Ochs 
> Signed-off-by: Manoj N. Kumar 
> ---
>  drivers/scsi/cxlflash/superpipe.c | 30 +-
>  drivers/scsi/cxlflash/superpipe.h |  2 ++
>  drivers/scsi/cxlflash/vlun.c  | 29 +
>  3 files changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/cxlflash/superpipe.c 
> b/drivers/scsi/cxlflash/superpipe.c
> index f625e07..8af7cdc 100644
> --- a/drivers/scsi/cxlflash/superpipe.c
> +++ b/drivers/scsi/cxlflash/superpipe.c
> @@ -283,6 +283,24 @@ out:
>   * @sdev:SCSI device associated with LUN.
>   * @lli: LUN destined for capacity request.
>   *
> + * The READ_CAP16 can take quite a while to complete. Should an EEH occur 
> while
> + * in scsi_execute(), the EEH handler will attempt to recover. As part of the
> + * recovery, the handler drains all currently running ioctls, waiting until 
> they
> + * have completed before proceeding with a reset. As this routine is used on 
> the
> + * ioctl path, this can create a condition where the EEH handler becomes 
> stuck,
> + * infinitely waiting for this ioctl thread. To avoid this behavior, 
> temporarily
> + * unmark this thread as an ioctl thread by releasing the ioctl read 
> semaphore.
> + * This will allow the EEH handler to proceed with a recovery while this 
> thread
> + * is still running. Once the scsi_execute() returns, reacquire the ioctl 
> read
> + * semaphore and check the adapter state in case it changed while inside of
> + * scsi_execute(). The state check will wait if the adapter is still being
> + * recovered or return a failure if the recovery failed. In the event that 
> the
> + * adapter reset failed, simply return the failure as the ioctl would be 
> unable
> + * to continue.
> + *
> + * Note that the above puts a requirement on this routine to only be called 
> on
> + * an ioctl thread.
> + *
>   * Return: 0 on success, -errno on failure
>   */
>  static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
> @@ -314,8 +332,18 @@ retry:
>   dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__,
>   retry_cnt ? "re" : "", scsi_cmd[0]);
>  
> + /* Drop the ioctl read semahpore across lengthy call */
> + up_read(&cfg->ioctl_rwsem);
>   result = scsi_execute(sdev, scsi_cmd, DMA_FROM_DEVICE, cmd_buf,
> CMD_BUFSIZE, sense_buf, to, CMD_RETRIES, 0, NULL);
> + down_read(&cfg->ioctl_rwsem);
> + rc = check_state(cfg);
> + if (rc) {
> + dev_err(dev, "%s: Failed state! result=0x08%X\n",
> + __func__, result);
> + rc = -ENODEV;
> + goto out;
> + }
>  
>   if (driver_byte(result) == DRIVER_SENSE) {
>   result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
> @@ -1221,7 +1249,7 @@ static const struct file_operations null_fops = {
>   *
>   * Return: 0 on success, -errno on failure
>   */
> -static int check_state(struct cxlflash_cfg *cfg)
> +int check_state(struct cxlflash_cfg *cfg)
>  {
>  

Re: [PATCH v4 30/32] cxlflash: Fix to avoid corrupting adapter fops

2015-09-29 Thread Daniel Axtens
"Matthew R. Ochs"  writes:

> The corruption that this fix remedies is due to the fact that the fops
> is initially defaulted to values found within a static structure. When
> the fops is handed down to the CXL services later in the attach path,
> certain services are patched. The fops structure remains correct until
> the user count drops to 0 and the fops is reset, triggering the process
> to repeat again. The user counts are tightly coupled with the creation
> and deletion of the user context. If multiple users perform a disk
> attach at the same time, when the user count is currently 0, some users
> can be in the middle of obtaining a file descriptor and have not yet
> reached the context creation code that [in addition to creating the
> context] increments the user count. Subsequent users coming in to
> perform the attach see that the user count is still 0, and reinitialize
> the fops, temporarily removing the patched fops. The users that are in
> the middle obtaining their file descriptor may then receive an invalid
> descriptor.
>
> The fix simply removes the user count altogether and moves the fops
> initialization to probe time such that it is only performed one time
> for the life of the adapter. In the future, if the CXL services adopt
> a private member for their context, that could be used to store the
> adapter structure reference and cxlflash could revert to a model that
> does not require an embedded fops.

Yep, this looks good.

We have discussed adding a private data field to a cxl context, and will
no doubt revisit the question at some point in the future :)

Reviewed-by: Daniel Axtens 

>
> Signed-off-by: Matthew R. Ochs 
> Signed-off-by: Manoj N. Kumar 
> ---
>  drivers/scsi/cxlflash/common.h|  3 +--
>  drivers/scsi/cxlflash/main.c  |  1 +
>  drivers/scsi/cxlflash/superpipe.c | 11 +--
>  3 files changed, 3 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
> index bbfe711..c11cd19 100644
> --- a/drivers/scsi/cxlflash/common.h
> +++ b/drivers/scsi/cxlflash/common.h
> @@ -21,6 +21,7 @@
>  #include 
>  #include 
>  
> +extern const struct file_operations cxlflash_cxl_fops;
>  
>  #define MAX_CONTEXT  CXLFLASH_MAX_CONTEXT   /* num contexts per afu */
>  
> @@ -115,8 +116,6 @@ struct cxlflash_cfg {
>   struct list_head ctx_err_recovery; /* contexts w/ recovery pending */
>   struct file_operations cxl_fops;
>  
> - atomic_t num_user_contexts;
> -
>   /* Parameters that are LUN table related */
>   int last_lun_index[CXLFLASH_NUM_FC_PORTS];
>   int promote_lun_index;
> diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
> index be78906..38e7edc 100644
> --- a/drivers/scsi/cxlflash/main.c
> +++ b/drivers/scsi/cxlflash/main.c
> @@ -2386,6 +2386,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
>  
>   cfg->init_state = INIT_STATE_NONE;
>   cfg->dev = pdev;
> + cfg->cxl_fops = cxlflash_cxl_fops;
>  
>   /*
>* The promoted LUNs move to the top of the LUN table. The rest stay
> diff --git a/drivers/scsi/cxlflash/superpipe.c 
> b/drivers/scsi/cxlflash/superpipe.c
> index 3cc8609..f625e07 100644
> --- a/drivers/scsi/cxlflash/superpipe.c
> +++ b/drivers/scsi/cxlflash/superpipe.c
> @@ -712,7 +712,6 @@ static void destroy_context(struct cxlflash_cfg *cfg,
>   kfree(ctxi->rht_needs_ws);
>   kfree(ctxi->rht_lun);
>   kfree(ctxi);
> - atomic_dec_if_positive(&cfg->num_user_contexts);
>  }
>  
>  /**
> @@ -769,7 +768,6 @@ static struct ctx_info *create_context(struct 
> cxlflash_cfg *cfg,
>   INIT_LIST_HEAD(&ctxi->luns);
>   INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
>  
> - atomic_inc(&cfg->num_user_contexts);
>   mutex_lock(&ctxi->mutex);
>  out:
>   return ctxi;
> @@ -1164,10 +1162,7 @@ out:
>   return rc;
>  }
>  
> -/*
> - * Local fops for adapter file descriptor
> - */
> -static const struct file_operations cxlflash_cxl_fops = {
> +const struct file_operations cxlflash_cxl_fops = {
>   .owner = THIS_MODULE,
>   .mmap = cxlflash_cxl_mmap,
>   .release = cxlflash_cxl_release,
> @@ -1286,10 +1281,6 @@ static int cxlflash_disk_attach(struct scsi_device 
> *sdev,
>  
>   int fd = -1;
>  
> - /* On first attach set fileops */
> - if (atomic_read(&cfg->num_user_contexts) == 0)
> - cfg->cxl_fops = cxlflash_cxl_fops;
> -
>   if (attach->num_interrupts > 4) {
>   dev_dbg(dev, "%s: Cannot support this many interrupts %llu\n",
>   __func__, attach->num_interrupts);
> -- 
> 2.1.0


signature.asc
Description: PGP signature


Re: [PATCH v4 29/32] cxlflash: Fix to double the delay each time

2015-09-29 Thread Daniel Axtens
"Matthew R. Ochs"  writes:

>> On Sep 28, 2015, at 8:40 PM, Daniel Axtens  wrote:
>> 
>> -BEGIN PGP SIGNED MESSAGE-
>> Hash: SHA512
>> 
>> "Matthew R. Ochs"  writes:
>> 
>>> From: Manoj Kumar 
>>> 
>>> The operator used to double the delay is incorrect and
>>> does not result in delay doubling.
>>> 
>>> To fix, use a left shift instead of the XOR operator.
>>> 
>> I can see that the patch is correct, but this commit message is a bit
>> confusing. What delay? In what circumstances are you doubling it? Why?
>
> This is the response delay while resetting the master context. The reset
> is performed by writing a bit and then waiting for it to clear. While waiting
> for it to clear, the code relaxes the delta between MMIO reads.

OK. If you do a v5, please include this in the commit message.

Regards,
Daniel
--
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] hpsa: add in sas transport

2015-09-29 Thread Don Brace
From: Kevin Barnett 

customers want lsscsi -t to show sas addresses when
enumerating sas devices. The sas addresses are used
mainly to light drive LEDs for location.

Signed-off-by: Don Brace 
---
 drivers/scsi/hpsa.c |  704 ++-
 drivers/scsi/hpsa.h |   37 ++
 drivers/scsi/hpsa_cmd.h |   14 +
 3 files changed, 677 insertions(+), 78 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 3b35de0..ae811a7 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -41,6 +41,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -205,6 +206,16 @@ static struct board_type products[] = {
{0x103C, "Unknown Smart Array", &SA5_access},
 };
 
+static struct scsi_transport_template *hpsa_sas_transport_template;
+static int hpsa_add_sas_host(struct ctlr_info *h);
+static void hpsa_delete_sas_host(struct ctlr_info *h);
+static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node,
+   struct hpsa_scsi_dev_t *device);
+static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device);
+static struct hpsa_scsi_dev_t
+   *hpsa_find_device_by_sas_rphy(struct ctlr_info *h,
+   struct sas_rphy *rphy);
+
 #define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy)
 static const struct scsi_cmnd hpsa_cmd_busy;
 #define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle)
@@ -275,6 +286,8 @@ static void hpsa_command_resubmit_worker(struct work_struct 
*work);
 static u32 lockup_detected(struct ctlr_info *h);
 static int detect_controller_lockup(struct ctlr_info *h);
 static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device);
+static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
+   struct ReportExtendedLUNdata *buf, int bufsize);
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -617,6 +630,11 @@ static const char * const raid_label[] = { "0", "4", 
"1(+0)", "5", "5+1", "6",
 #define HPSA_RAID_ADM  6   /* also used for RAID 1+0 ADM */
 #define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
 
+static inline bool is_logical_device(struct hpsa_scsi_dev_t *device)
+{
+   return !device->physical_device;
+}
+
 static ssize_t raid_level_show(struct device *dev,
 struct device_attribute *attr, char *buf)
 {
@@ -637,7 +655,7 @@ static ssize_t raid_level_show(struct device *dev,
}
 
/* Is this even a logical drive? */
-   if (!is_logical_dev_addr_mode(hdev->scsi3addr)) {
+   if (!is_logical_device(hdev)) {
spin_unlock_irqrestore(&h->lock, flags);
l = snprintf(buf, PAGE_SIZE, "N/A\n");
return l;
@@ -771,8 +789,8 @@ static ssize_t path_info_show(struct device *dev,
scsi_device_type(hdev->devtype));
 
if (is_ext_target(h, hdev) ||
-   (hdev->devtype == TYPE_RAID) ||
-   is_logical_dev_addr_mode(hdev->scsi3addr)) {
+   hdev->devtype == TYPE_RAID ||
+   is_logical_device(hdev)) {
output_len += snprintf(path[i] + output_len,
PATH_STRING_LEN, "%s\n",
active);
@@ -791,8 +809,7 @@ static ssize_t path_info_show(struct device *dev,
PATH_STRING_LEN,
"PORT: %.2s ",
phys_connector);
-   if (hdev->devtype == TYPE_DISK &&
-   hdev->expose_state != HPSA_DO_NOT_EXPOSE) {
+   if (hdev->devtype == TYPE_DISK && hdev->expose_device) {
if (box == 0 || box == 0xFF) {
output_len += snprintf(path[i] + output_len,
PATH_STRING_LEN,
@@ -1148,7 +1165,7 @@ static inline void hpsa_show_dev_msg(const char *level, 
struct ctlr_info *h,
"RAID-?" : raid_label[dev->raid_level],
dev->offload_config ? '+' : '-',
dev->offload_enabled ? '+' : '-',
-   dev->expose_state);
+   dev->expose_device);
 }
 
 /* Add an entry into h->dev[] array. */
@@ -1221,7 +1238,7 @@ lun_assigned:
added[*nadded] = device;
(*nadded)++;
hpsa_show_dev_msg(KERN_INFO, h, device,
-   device->expose_state & HPSA_SCSI_ADD ? "added" : "masked");
+   device->expose_device ? "added" : "masked");
device->offload_to_be_enabled = device->offload_enabled;
device->offload_enabled = 0;
return 0;
@@ -1579,7 +1596,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info 
*h,
for (j = 0; j < ndevices; j++) {
if (dev[j]->devtype != TYPE_DISK)
continue;
- 

[PATCH] hpsa update

2015-09-29 Thread Don Brace
This patch is based on Linus's tree

I could use some help with this patch.

We are adding in the sas transport layer for our HBA devices. 
I am having issues removing the sas transport entries during driver
unload. The entries are removed in what appears to be the proper order
but I am getting a bunch of warnings that look like what is shown below.

I do not see these warnings with 3.10 kernels but I do see them with
4.3-rc2+.

I have searched the lkml mailing list for resolution and found a 
fix for a similar issue:
http://marc.info/?l=linux-scsi&m=143743743518987&w=2

But this did not resolve my problem.

I am attaching the patch and the console logs. Can anyone give me some
advice with this issue?

Typical warning message: (Seen for both port and end_device objects)

[  247.567655] WARNING: CPU: 52 PID: 14975 at fs/sysfs/group.c:224 
sysfs_remove_group+0x8d/0x90()
[  247.611154] sysfs group 81a73000 not found for kobject 'port-5:0'
[  247.645110] Modules linked in: hpsa(OE-) scsi_transport_sas ip6t_rpfilter 
ip6t_REJECT nf_reject_ipv6 nf_conntrack_ipv6 nf_defrag_ipv6 ipt_REJECT 
nf_reject_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack cfg80211 
nf_conntrack rfkill ebtable_nat ebtable_broute bridge stp llc ebtable_filter 
ebtables ip6table_mangle ip6table_security ip6table_raw ip6table_filter 
ip6_tables iptable_mangle iptable_security iptable_raw iptable_filter ip_tables 
sg x86_pkg_temp_thermal coretemp kvm_intel kvm crct10dif_pclmul crc32_pclmul 
nfsd crc32c_intel ghash_clmulni_intel aesni_intel lrw gf128mul auth_rpcgss 
ipmi_devintf hpilo hpwdt glue_helper sb_edac nfs_acl iTCO_wdt ablk_helper lockd 
cryptd iTCO_vendor_support edac_core serio_raw ioatdma shpchp pcspkr ipmi_si 
lpc_ich wmi mfd_core dca ipmi_msghandler grace pcc_cpufreq
[  248.001829]  acpi_power_meter acpi_cpufreq sunrpc uinput xfs libcrc32c 
sd_mod mgag200 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt 
fb_sys_fops ttm drm usb_storage tg3 ptp i2c_core pps_core dm_mirror 
dm_region_hash dm_log dm_mod
[  248.102395] CPU: 52 PID: 14975 Comm: rmmod Tainted: G   OE   
4.3.0-rc2+ #1
[  248.140420] Hardware name: HP ProLiant DL580 Gen8, BIOS P79 05/06/2015
[  248.172430]   dce8a349 8808582afb78 
81312230
[  248.209532]  8808582afbc0 8808582afbb0 8107ae26 

[  248.246473]  81a73000 881858a55838 881858a50c00 
881858a50f10
[  248.283094] Call Trace:
[  248.295019]  [] dump_stack+0x44/0x64
[  248.320346]  [] warn_slowpath_common+0x86/0xc0
[  248.351167]  [] warn_slowpath_fmt+0x5c/0x80
[  248.379273]  [] ? kernfs_find_and_get_ns+0x48/0x60
[  248.410729]  [] sysfs_remove_group+0x8d/0x90
[  248.439875]  [] dpm_sysfs_remove+0x57/0x60
[  248.468564]  [] device_del+0x58/0x260
[  248.494859]  [] ? device_remove_file+0x19/0x20
[  248.524099]  [] 
attribute_container_class_device_del+0x1a/0x20
[  248.560407]  [] transport_remove_classdev+0x4e/0x60
[  248.591673]  [] ? transport_add_class_device+0x40/0x40
[  248.626510]  [] 
attribute_container_device_trigger+0xce/0xe0
[  248.661392]  [] transport_remove_device+0x15/0x20
[  248.692653]  [] sas_port_delete+0x123/0x150 
[scsi_transport_sas]
[  248.732777]  [] hpsa_free_sas_port+0x42/0xc0 [hpsa]
[  248.769411]  [] hpsa_free_sas_node.part.58+0x7c/0xb0 [hpsa]
[  248.805243]  [] hpsa_remove_one+0x1aa/0x1f0 [hpsa]
[  248.836752]  [] pci_device_remove+0x39/0xc0
[  248.864460]  [] __device_release_driver+0x96/0x130
[  248.894875]  [] driver_detach+0xb5/0xc0
[  248.920994]  [] bus_remove_driver+0x55/0xd0
[  248.949451]  [] driver_unregister+0x2c/0x50
[  248.977606]  [] pci_unregister_driver+0x2a/0x80
[  249.007758]  [] hpsa_cleanup+0x10/0x219 [hpsa]
[  249.037334]  [] SyS_delete_module+0x18d/0x220
[  249.066208]  [] ? syscall_return_slowpath+0x55/0x150
[  249.098215]  [] entry_SYSCALL_64_fastpath+0x12/0x71
[  249.130809] ---[ end trace da8892bb8b64bbf0 ]---

---

Kevin Barnett (1):
  hpsa: add in sas transport


 drivers/scsi/hpsa.c |  704 ++-
 drivers/scsi/hpsa.h |   37 ++
 drivers/scsi/hpsa_cmd.h |   14 +
 3 files changed, 677 insertions(+), 78 deletions(-)

--
Signature
--
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 v4 12/32] cxlflash: Fix to avoid spamming the kernel log

2015-09-29 Thread Matthew R. Ochs
> On Sep 29, 2015, at 12:05 AM, Andrew Donnellan  
> wrote:
> On 26/09/15 09:15, Matthew R. Ochs wrote:
>> During run-time the driver can be very chatty and spam the system
>> kernel log. Various print statements can be limited and/or moved
>> to development-only mode. Additionally, numerous prints can be
>> converted to trace the corresponding device.
>> 
>> The following changes were made:
>>  - pr_debug to pr_devel
>>  - pr_debug to pr_debug_ratelimited
>>  - pr_err to dev_err
>>  - pr_debug to dev_dbg
>> 
>> Signed-off-by: Matthew R. Ochs 
>> Signed-off-by: Manoj N. Kumar 
>> Reviewed-by: Brian King 
> 
> Reviewed-by: Andrew Donnellan 
> 
> Changes mostly look fine, further comments below.
> 
>> --- a/drivers/scsi/cxlflash/main.c
>> +++ b/drivers/scsi/cxlflash/main.c
>> @@ -58,8 +58,8 @@ static struct afu_cmd *cmd_checkout(struct afu *afu)
>>  cmd = &afu->cmd[k];
>> 
>>  if (!atomic_dec_if_positive(&cmd->free)) {
>> -pr_debug("%s: returning found index=%d\n",
>> - __func__, cmd->slot);
>> +pr_devel("%s: returning found index=%d cmd=%p\n",
>> + __func__, cmd->slot, cmd);
> 
>>  pr_debug("%s: cmd failed afu_rc=%d scsi_rc=%d fc_rc=%d "
>> - "afu_extra=0x%X, scsi_entra=0x%X, fc_extra=0x%X\n",
>> + "afu_extra=0x%X, scsi_extra=0x%X, fc_extra=0x%X\n",
>>   __func__, ioasa->rc.afu_rc, ioasa->rc.scsi_rc,
>>   ioasa->rc.fc_rc, ioasa->afu_extra, ioasa->scsi_extra,
>>   ioasa->fc_extra);
> 
> Minor nitpicking: mention that you fix these in the commit message.

Noted for the future.

>> @@ -240,9 +240,9 @@ static void cmd_complete(struct afu_cmd *cmd)
>>  cmd_is_tmf = cmd->cmd_tmf;
>>  cmd_checkin(cmd); /* Don't use cmd after here */
>> 
>> -pr_debug("%s: calling scsi_set_resid, scp=%p "
>> - "result=%X resid=%d\n", __func__,
>> - scp, scp->result, resid);
>> +pr_debug_ratelimited("%s: calling scsi_done scp=%p result=%X "
>> + "ioasc=%d\n", __func__, scp, scp->result,
>> + cmd->sa.ioasc);
>> 
>>  scsi_set_resid(scp, resid);
>>  scsi_dma_unmap(scp);
> 
> Why has the message changed from scsi_set_resid to scsi_done, and should the 
> message be moved to immediately before the scsi_done call?

In a later patch in the series the scsi_set_resid() is actually moved.

--
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 v4 29/32] cxlflash: Fix to double the delay each time

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 8:40 PM, Daniel Axtens  wrote:
> 
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA512
> 
> "Matthew R. Ochs"  writes:
> 
>> From: Manoj Kumar 
>> 
>> The operator used to double the delay is incorrect and
>> does not result in delay doubling.
>> 
>> To fix, use a left shift instead of the XOR operator.
>> 
> I can see that the patch is correct, but this commit message is a bit
> confusing. What delay? In what circumstances are you doubling it? Why?

This is the response delay while resetting the master context. The reset
is performed by writing a bit and then waiting for it to clear. While waiting
for it to clear, the code relaxes the delta between MMIO reads.



--
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 v4 23/32] cxlflash: Fix function prolog parameters and return codes

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 11:36 PM, Andrew Donnellan  
> wrote:
> On 26/09/15 09:18, Matthew R. Ochs wrote:
>> 
>>   */
>>  static int send_tmf(struct afu *afu, struct scsi_cmnd *scp, u64 tmfcmd)
>>  {
>> @@ -491,9 +490,7 @@ static const char *cxlflash_driver_info(struct Scsi_Host 
>> *host)
>>   * @host:   SCSI host associated with device.
>>   * @scp:SCSI command to send.
>>   *
>> - * Return:
>> - *  0 on success
>> - *  SCSI_MLQUEUE_HOST_BUSY when host is busy
>> + * Return: 0 on success or SCSI_MLQUEUE_HOST_BUSY
>>   */
> 
> I'd prefer it to say "SCSI_MLQUEUE_HOST_BUSY on failure". (Aesthetically I 
> prefer having it on a separate line, but that's just personal preference.)
> 
> As an aside, while checking the correctness of this, I found that the comment 
> for cxlflash_send_cmd() states that it returns -1 on failure, when the only 
> error value it actually returns is SCSI_MLQUEUE_HOST_BUSY. If you send a v5 
> you might want to fix this.

I'll make a note of this.

--
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 v4 27/32] cxlflash: Fix to prevent stale AFU RRQ

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 8:36 PM, Daniel Axtens  wrote:
> 
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA512
> 
> "Matthew R. Ochs"  writes:
> 
>> Following an adapter reset, the AFU RRQ that resides in host memory
>> holds stale data. This can lead to a condition where the RRQ interrupt
>> handler tries to process stale entries and/or endlessly loops due to an
>> out of sync generation bit.
>> 
>> To fix, the AFU RRQ in host memory needs to be cleared after each reset.
> 
> This looks good. Do you need anything to bail out of cxlflash_rrq_irq if
> the data goes stale or to all Fs while that function is running?

We're not performing an MMIO here, so I'm not sure how the all Fs check
would apply. We're also protected fairly well by the generation bit. I suppose
we could look at adding some type of 'max iterations' count to protect against
a runaway handler but that would be in a future patch.


--
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 v4 25/32] cxlflash: Fix to prevent EEH recovery failure

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 8:25 PM, Daniel Axtens  wrote:
> 
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA512
> 
> "Matthew R. Ochs"  writes:
> 
> 
>> The process_sense() routine can perform a read capacity which
>> can take some time to complete. If an EEH occurs while waiting
>> on the read capacity, the EEH handler is unable to obtain the
>> context's mutex in order to put the context in an error state.
>> The EEH handler will sit and wait until the context is free,
>> but this wait can last longer than the EEH handler tolerates,
>> leading to a failed recovery.
> 
> I'm not quite clear on what you mean by the EEH handler timing
> out. AFAIK there's nothing in eehd and the EEH core that times out if a
> driver doesn't respond - indeed, it's pretty easy to hang eehd with a
> misbehaving driver.
> 
> Are you referring to your own internal timeouts?
> cxlflash_wait_for_pci_err_recovery and anything else that uses
> CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT?

Reading through this again I can see how this is misleading. This is
actually similar and related to the deadlock scenario described in
"Fix to avoid potential deadlock on EEH". Without this fix, you'd end
up in a similar situation but deadlocked on the context mutex instead
of the ioctl semaphore.

--
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 v4 32/32] cxlflash: Fix to avoid potential deadlock on EEH

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 6:41 PM, Brian King  wrote:
> On 09/25/2015 06:19 PM, Matthew R. Ochs wrote:
>> static int write_same16(struct scsi_device *sdev,
>> @@ -433,9 +451,20 @@ static int write_same16(struct scsi_device *sdev,
>>  put_unaligned_be32(ws_limit < left ? ws_limit : left,
>> &scsi_cmd[10]);
>> 
>> +/* Drop the ioctl read semahpore across lengthy call */
>> +up_read(&cfg->ioctl_rwsem);
>>  result = scsi_execute(sdev, scsi_cmd, DMA_TO_DEVICE, cmd_buf,
>>CMD_BUFSIZE, sense_buf, to, CMD_RETRIES,
>>0, NULL);
>> +down_read(&cfg->ioctl_rwsem);
>> +rc = check_state(cfg);
>> +if (rc) {
>> +dev_err(dev, "%s: Failed state! result=0x08%X\n",
>> +__func__, result);
>> +rc = -ENODEV;
> 
> Since check_state only returns 0 or -ENODEV, this is a bit redundant, but not 
> worth redoing the
> patch in my mind.

Agreed. This occurred to me the other day after submitting this patch when I was
reviewing the state locking code. Will look at revising in a future patch.

Thanks again for reviewing.

--
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 v4 17/32] cxlflash: Remove dual port online dependency

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 6:37 PM, Daniel Axtens  wrote:
> 
> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA512
> 
> Hi,
> 
>> static int afu_set_wwpn(struct afu *afu, int port, u64 *fc_regs, u64 wwpn)
>> {
>> -int ret = 0;
>> +int rc = 0;
> I realise it's nice to have things consistent, but making this change
> now makes the rest of the patch quite difficult to follow.

Next time I will try to separate out a change like this.

> 
>> 
>>  set_port_offline(fc_regs);
>> 
>> @@ -1038,33 +1038,26 @@ static int afu_set_wwpn(struct afu *afu, int port, 
>> u64 *fc_regs, u64 wwpn)
>> FC_PORT_STATUS_RETRY_CNT)) {
>>  pr_debug("%s: wait on port %d to go offline timed out\n",
>>   __func__, port);
>> -ret = -1; /* but continue on to leave the port back online */
>> +rc = -1; /* but continue on to leave the port back online */
>>  }
>> 
>> -if (ret == 0)
>> +if (rc == 0)
>>  writeq_be(wwpn, &fc_regs[FC_PNAME / 8]);
>> 
>> +/* Always return success after programming WWPN */
>> +rc = 0;
>> +
>>  set_port_online(fc_regs);
>> 
>>  if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US,
>>FC_PORT_STATUS_RETRY_CNT)) {
>>  pr_debug("%s: wait on port %d to go online timed out\n",
>>   __func__, port);
>> -ret = -1;
>> -
>> -/*
>> - * Override for internal lun!!!
>> - */
>> -if (afu->internal_lun) {
>> -pr_debug("%s: Overriding port %d online timeout!!!\n",
>> - __func__, port);
>> -ret = 0;
>> -}
>>  }
>> 
>> -pr_debug("%s: returning rc=%d\n", __func__, ret);
>> +pr_debug("%s: returning rc=%d\n", __func__, rc);
> I'm not sure I fully understand the flow of this function, but it looks
> like you set rc=0 regardless of how things actually go: is this ever
> going to print a return value other than zero?

Correct, this function behaves more like a void for the time being. The
overall goal of this is to allow a card to configure even when the link is
down. At some later point when the link is transitioned to 'up', a link state
change interrupt will trigger the port configuration. I left this with a return
code for right now in case we need to alter the behavior again (based
upon testing) and actually return a value other than 0.

--
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 v4 08/32] cxlflash: Fix to avoid CXL services during EEH

2015-09-29 Thread Matthew R. Ochs
> On Sep 28, 2015, at 6:05 PM, Daniel Axtens  wrote:
> 
> You have two versions of check_state() below, which is a bit
> confusing. It looks like you've moved the function and also added the
> up/down of the read semaphore. I assume that's all that changed?

Correct.

It was originally moved to meet a dependency due to it being defined statically.

> 
>> 
>> /**
>> + * check_state() - checks and responds to the current adapter state
>> + * @cfg:Internal structure associated with the host.
>> + *
>> + * This routine can block and should only be used on process context.
>> + * It assumes that the caller is an ioctl thread and holding the ioctl
>> + * read semaphore. This is temporarily let up across the wait to allow
>> + * for draining actively running ioctls. Also note that when waking up
>> + * from waiting in reset, the state is unknown and must be checked again
>> + * before proceeding.
>> + *
>> + * Return: 0 on success, -errno on failure
>> + */
>> +static int check_state(struct cxlflash_cfg *cfg)
>> +{
>> +struct device *dev = &cfg->dev->dev;
>> +int rc = 0;
>> +
>> +retry:
>> +switch (cfg->state) {
>> +case STATE_LIMBO:
>> +dev_dbg(dev, "%s: Limbo state, going to wait...\n", __func__);
>> +up_read(&cfg->ioctl_rwsem);
>> +rc = wait_event_interruptible(cfg->limbo_waitq,
>> +  cfg->state != STATE_LIMBO);
>> +down_read(&cfg->ioctl_rwsem);
>> +if (unlikely(rc))
>> +break;
>> +goto retry;
>> +case STATE_FAILTERM:
>> +dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
>> +rc = -ENODEV;
>> +break;
>> +default:
>> +break;
>> +}
>> +
>> +return rc;
>> +}
>> +
>> +/**
>>  * cxlflash_disk_attach() - attach a LUN to a context
>>  * @sdev:SCSI device associated with LUN.
>>  * @attach:  Attach ioctl data structure.
>> @@ -1523,41 +1563,6 @@ err1:
>> }
>> 
>> /**
>> - * check_state() - checks and responds to the current adapter state
>> - * @cfg:Internal structure associated with the host.
>> - *
>> - * This routine can block and should only be used on process context.
>> - * Note that when waking up from waiting in limbo, the state is unknown
>> - * and must be checked again before proceeding.
>> - *
>> - * Return: 0 on success, -errno on failure
>> - */
>> -static int check_state(struct cxlflash_cfg *cfg)
>> -{
>> -struct device *dev = &cfg->dev->dev;
>> -int rc = 0;
>> -
>> -retry:
>> -switch (cfg->state) {
>> -case STATE_LIMBO:
>> -dev_dbg(dev, "%s: Limbo, going to wait...\n", __func__);
>> -rc = wait_event_interruptible(cfg->limbo_waitq,
>> -  cfg->state != STATE_LIMBO);
>> -if (unlikely(rc))
>> -break;
>> -goto retry;
>> -case STATE_FAILTERM:
>> -dev_dbg(dev, "%s: Failed/Terminating!\n", __func__);
>> -rc = -ENODEV;
>> -break;
>> -default:
>> -break;
>> -}
>> -
>> -return rc;
>> -}
>> -
>> -/**
>>  * cxlflash_afu_recover() - initiates AFU recovery
>>  * @sdev:SCSI device associated with LUN.
>>  * @recover: Recover ioctl data structure.
>> @@ -1646,9 +1651,14 @@ retry_recover:
>>  /* Test if in error state */
>>  reg = readq_be(&afu->ctrl_map->mbox_r);
>>  if (reg == -1) {
>> -dev_dbg(dev, "%s: MMIO read fail! Wait for recovery...\n",
>> -__func__);
>> -mutex_unlock(&ctxi->mutex);
>> +dev_dbg(dev, "%s: MMIO fail, wait for recovery.\n", __func__);
>> +
>> +/*
>> + * Before checking the state, put back the context obtained with
>> + * get_context() as it is no longer needed and sleep for a short
>> + * period of time (see prolog notes).
>> + */
>> +put_context(ctxi);
> 
> Is this needed for the drain to work? It looks like it fixes a
> refcounting bug in the function, but I'm not sure I understand how it
> interacts with the rest of this patch.

This was simply some "while I'm here" refactoring as the commit originally
included a change here. The main point of this change was to replace the
mutex_unlock() with put_context(), which is a wrapper around the unlocking
of the context's mutex.
> 
> Anyway, the patch overall looks good to me, and makes your driver
> interact with CXL's EEH support in the way I intended when I wrote it.

Thanks for reviewing.

--
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: twa generates WARNING upon boot

2015-09-29 Thread Tóth Attila
2015.Szeptember 29.(K) 20:33 időpontban James Bottomley ezt írta:
> On Tue, 2015-09-29 at 20:25 +0200, "Tóth Attila" wrote:
>> 2015.Szeptember 29.(K) 20:02 időpontban James Bottomley ezt írta:
>> > On Tue, 2015-09-29 at 10:37 -0700, James Bottomley wrote:
>> >> On Tue, 2015-09-29 at 18:49 +0200, "Tóth Attila" wrote:
>> >> > 2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
>> >> > > On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila"
>> 
>> >> > > wrote:
>> >> > >> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X
>> >> > >>
>> >> > >
>> >> > > Can you re-try with Christoph's patch:
>> >> > >
>> >> > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de
>> >> >
>> >> > As I've told this patch has been already included in the kernel I'm
>> >> using
>> >> > (4.1.7-hardened-r1, which is based on 4.1.7).
>> >> > Out of curiosity I've reverted the patch and the WARNING no longer
>> >> appears
>> >> > during boot...
>> >>
>> >> Ah, it looks like there's a bug in the patch, it doesn't take into
>> >> account that the driver has a minimum sg map length and it copies for
>> >> things under that, so we're likely unmapping something that wasn't
>> >> mapped.   It's slightly hard to fix given that the indicator flag
>> we'd
>> >> use for this is gone in that patch; does this fix the warning?
>> >
>> > Actually, strike that, it would still barf on internally generated
>> > commands (and it's recursively calling twa_scsi_dma_unmap).  This does
>> a
>> > partial revert of the state check which should pick up all cases the
>> > input didn't go through the mapping.
>>
>> Just to be clear before I try something out.
>> In this latter patch you are resurrecting TW_PHASE_SGLIST, which has
>> been
>> ment to be removed in Christoph's patch from the header.
>> I guess I have to reintroduce those phase defines on top of the changes
>> below in your latest email.
>> Or please let me know what should I exactly try out.
>
> Heh, sorry forgot the header change.  This should be the complete patch
> attached.

After applying your latest patch I can see no more WARNINGs upon reboot!

Please note, that apart from the culprit 3w-9xxx commit
(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de),
two other parent commits were introducing similar changes to 3w- and
3w-sas drivers
(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9cd9554615cba14f0877cc9972a6537ad2bdde61,
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=579d69bc1fd56d5af5761969aa529d1d1c188300).
Those two may also need similar treatment.

Many thanks:
Dw.
-- 
dr Tóth Attila, Radiológus, 06-20-825-8057
Attila Toth MD, Radiologist, +36-20-825-8057

> ---
>
> diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
> index add419d..751ed66 100644
> --- a/drivers/scsi/3w-9xxx.c
> +++ b/drivers/scsi/3w-9xxx.c
> @@ -151,7 +151,13 @@ static void
> twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
>  static char *twa_string_lookup(twa_message_type *table, unsigned int
> aen_code);
>
>  /* Functions */
> +static void twa_scsi_dma_unmap(struct scsi_cmnd *SCpnt)
> +{
> + if (SCpnt->SCp.phase == TW_PHASE_SGLIST)
> + scsi_dma_unmap(SCpnt);
> +}
>
> +
>  /* Show some statistics about the card */
>  static ssize_t twa_show_stats(struct device *dev,
> struct device_attribute *attr, char *buf)
> @@ -1339,7 +1345,7 @@ static irqreturn_t twa_interrupt(int irq, void
> *dev_instance)
>   }
>
>   /* Now complete the io */
> - scsi_dma_unmap(cmd);
> + twa_scsi_dma_unmap(cmd);
>   cmd->scsi_done(cmd);
>   tw_dev->state[request_id] = TW_S_COMPLETED;
>   twa_free_request_id(tw_dev, request_id);
> @@ -1582,7 +1588,7 @@ static int
> twa_reset_device_extension(TW_Device_Extension *tw_dev)
>   struct scsi_cmnd *cmd = tw_dev->srb[i];
>
>   cmd->result = (DID_RESET << 16);
> - scsi_dma_unmap(cmd);
> + twa_scsi_dma_unmap(cmd);
>   cmd->scsi_done(cmd);
>   }
>   }
> @@ -1762,15 +1768,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd
> *SCpnt, void (*done)(struct scsi_
>   /* Save the scsi command for use by the ISR */
>   tw_dev->srb[request_id] = SCpnt;
>
> + /* Initialize phase to zero */
> + SCpnt->SCp.phase = TW_PHASE_INITIAL;
> +
>   retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
>   switch (retval) {
>   case SCSI_MLQUEUE_HOST_BUSY:
> - scsi_dma_unmap(SCpnt);
> + twa_scsi_dma_unmap(SCpnt);
>

Re: [PATCHv5 00/36] asynchronous ALUA device handler

2015-09-29 Thread Bart Van Assche

On 09/29/2015 03:47 AM, Hannes Reinecke wrote:

here the next round of my update to the ALUA device handler.


Hello Hannes,

Sorry but this with this version I see an initiator kernel lockup 
shortly after the initiator system had been booted. I have attached the 
output of echo t > /proc/sysrq-trigger to this e-mail.


Thanks,

Bart.


netconsole-log.txt.gz
Description: application/gzip


Re: twa generates WARNING upon boot

2015-09-29 Thread James Bottomley
On Tue, 2015-09-29 at 20:25 +0200, "Tóth Attila" wrote:
> 2015.Szeptember 29.(K) 20:02 időpontban James Bottomley ezt írta:
> > On Tue, 2015-09-29 at 10:37 -0700, James Bottomley wrote:
> >> On Tue, 2015-09-29 at 18:49 +0200, "Tóth Attila" wrote:
> >> > 2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
> >> > > On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila" 
> >> > > wrote:
> >> > >> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X
> >> > >>
> >> > >
> >> > > Can you re-try with Christoph's patch:
> >> > >
> >> > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de
> >> >
> >> > As I've told this patch has been already included in the kernel I'm
> >> using
> >> > (4.1.7-hardened-r1, which is based on 4.1.7).
> >> > Out of curiosity I've reverted the patch and the WARNING no longer
> >> appears
> >> > during boot...
> >>
> >> Ah, it looks like there's a bug in the patch, it doesn't take into
> >> account that the driver has a minimum sg map length and it copies for
> >> things under that, so we're likely unmapping something that wasn't
> >> mapped.   It's slightly hard to fix given that the indicator flag we'd
> >> use for this is gone in that patch; does this fix the warning?
> >
> > Actually, strike that, it would still barf on internally generated
> > commands (and it's recursively calling twa_scsi_dma_unmap).  This does a
> > partial revert of the state check which should pick up all cases the
> > input didn't go through the mapping.
> 
> Just to be clear before I try something out.
> In this latter patch you are resurrecting TW_PHASE_SGLIST, which has been
> ment to be removed in Christoph's patch from the header.
> I guess I have to reintroduce those phase defines on top of the changes
> below in your latest email.
> Or please let me know what should I exactly try out.

Heh, sorry forgot the header change.  This should be the complete patch
attached.

James

---

diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index add419d..751ed66 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -151,7 +151,13 @@ static void 
twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
 
 /* Functions */
+static void twa_scsi_dma_unmap(struct scsi_cmnd *SCpnt)
+{
+   if (SCpnt->SCp.phase == TW_PHASE_SGLIST)
+   scsi_dma_unmap(SCpnt);
+}
 
+  
 /* Show some statistics about the card */
 static ssize_t twa_show_stats(struct device *dev,
  struct device_attribute *attr, char *buf)
@@ -1339,7 +1345,7 @@ static irqreturn_t twa_interrupt(int irq, void 
*dev_instance)
}
 
/* Now complete the io */
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd);
cmd->scsi_done(cmd);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
@@ -1582,7 +1588,7 @@ static int twa_reset_device_extension(TW_Device_Extension 
*tw_dev)
struct scsi_cmnd *cmd = tw_dev->srb[i];
 
cmd->result = (DID_RESET << 16);
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd);
cmd->scsi_done(cmd);
}
}
@@ -1762,15 +1768,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, 
void (*done)(struct scsi_
/* Save the scsi command for use by the ISR */
tw_dev->srb[request_id] = SCpnt;
 
+   /* Initialize phase to zero */
+   SCpnt->SCp.phase = TW_PHASE_INITIAL;
+
retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
switch (retval) {
case SCSI_MLQUEUE_HOST_BUSY:
-   scsi_dma_unmap(SCpnt);
+   twa_scsi_dma_unmap(SCpnt);
twa_free_request_id(tw_dev, request_id);
break;
case 1:
SCpnt->result = (DID_ERROR << 16);
-   scsi_dma_unmap(SCpnt);
+   twa_scsi_dma_unmap(SCpnt);
done(SCpnt);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
@@ -1845,6 +1854,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension 
*tw_dev, int request_id,
if (sg_count < 0)
goto out;
 
+   srb->SCp.phase = TW_PHASE_SGLIST;
+
scsi_for_each_sg(srb, sg, sg_count, i) {
command_packet->sg_list[i].address = 
TW_CPU_TO_SGL(sg_dma_address(sg));
command_packet->sg_li

Re: twa generates WARNING upon boot

2015-09-29 Thread Tóth Attila
2015.Szeptember 29.(K) 20:02 időpontban James Bottomley ezt írta:
> On Tue, 2015-09-29 at 10:37 -0700, James Bottomley wrote:
>> On Tue, 2015-09-29 at 18:49 +0200, "Tóth Attila" wrote:
>> > 2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
>> > > On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila" 
>> > > wrote:
>> > >> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X
>> > >>
>> > >
>> > > Can you re-try with Christoph's patch:
>> > >
>> > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de
>> >
>> > As I've told this patch has been already included in the kernel I'm
>> using
>> > (4.1.7-hardened-r1, which is based on 4.1.7).
>> > Out of curiosity I've reverted the patch and the WARNING no longer
>> appears
>> > during boot...
>>
>> Ah, it looks like there's a bug in the patch, it doesn't take into
>> account that the driver has a minimum sg map length and it copies for
>> things under that, so we're likely unmapping something that wasn't
>> mapped.   It's slightly hard to fix given that the indicator flag we'd
>> use for this is gone in that patch; does this fix the warning?
>
> Actually, strike that, it would still barf on internally generated
> commands (and it's recursively calling twa_scsi_dma_unmap).  This does a
> partial revert of the state check which should pick up all cases the
> input didn't go through the mapping.

Just to be clear before I try something out.
In this latter patch you are resurrecting TW_PHASE_SGLIST, which has been
ment to be removed in Christoph's patch from the header.
I guess I have to reintroduce those phase defines on top of the changes
below in your latest email.
Or please let me know what should I exactly try out.

Thanks: Dw.
-- 
dr Tóth Attila, Radiológus, 06-20-825-8057
Attila Toth MD, Radiologist, +36-20-825-8057

>
> diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
> index add419d..751ed66 100644
> --- a/drivers/scsi/3w-9xxx.c
> +++ b/drivers/scsi/3w-9xxx.c
> @@ -151,7 +151,13 @@ static void
> twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
>  static char *twa_string_lookup(twa_message_type *table, unsigned int
> aen_code);
>
>  /* Functions */
> +static void twa_scsi_dma_unmap(struct scsi_cmnd *SCpnt)
> +{
> + if (SCpnt->SCp.phase == TW_PHASE_SGLIST)
> + scsi_dma_unmap(SCpnt);
> +}
>
> +
>  /* Show some statistics about the card */
>  static ssize_t twa_show_stats(struct device *dev,
> struct device_attribute *attr, char *buf)
> @@ -1339,7 +1345,7 @@ static irqreturn_t twa_interrupt(int irq, void
> *dev_instance)
>   }
>
>   /* Now complete the io */
> - scsi_dma_unmap(cmd);
> + twa_scsi_dma_unmap(cmd);
>   cmd->scsi_done(cmd);
>   tw_dev->state[request_id] = TW_S_COMPLETED;
>   twa_free_request_id(tw_dev, request_id);
> @@ -1582,7 +1588,7 @@ static int
> twa_reset_device_extension(TW_Device_Extension *tw_dev)
>   struct scsi_cmnd *cmd = tw_dev->srb[i];
>
>   cmd->result = (DID_RESET << 16);
> - scsi_dma_unmap(cmd);
> + twa_scsi_dma_unmap(cmd);
>   cmd->scsi_done(cmd);
>   }
>   }
> @@ -1762,15 +1768,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd
> *SCpnt, void (*done)(struct scsi_
>   /* Save the scsi command for use by the ISR */
>   tw_dev->srb[request_id] = SCpnt;
>
> + /* Initialize phase to zero */
> + SCpnt->SCp.phase = TW_PHASE_INITIAL;
> +
>   retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
>   switch (retval) {
>   case SCSI_MLQUEUE_HOST_BUSY:
> - scsi_dma_unmap(SCpnt);
> + twa_scsi_dma_unmap(SCpnt);
>   twa_free_request_id(tw_dev, request_id);
>   break;
>   case 1:
>   SCpnt->result = (DID_ERROR << 16);
> - scsi_dma_unmap(SCpnt);
> + twa_scsi_dma_unmap(SCpnt);
>   done(SCpnt);
>   tw_dev->state[request_id] = TW_S_COMPLETED;
>   twa_free_request_id(tw_dev, request_id);
> @@ -1845,6 +1854,8 @@ static int
> twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
>   if (sg_count < 0)
>   goto out;
>
> + srb->SCp.phase = TW_PHASE_SGLIST;
> +
>   scsi_for_each_sg(srb, sg, sg_count, i) {
>   command_packet->sg_list[i].address =
> TW_CPU_TO_SGL(sg_dma_address(sg));
>   command_packet->sg_list[i].length = 
> cpu_to_le32(sg_dma_len(sg));
>
>


--
To unsubscribe fro

Re: twa generates WARNING upon boot

2015-09-29 Thread James Bottomley
On Tue, 2015-09-29 at 10:37 -0700, James Bottomley wrote:
> On Tue, 2015-09-29 at 18:49 +0200, "Tóth Attila" wrote:
> > 2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
> > > On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila" 
> > > wrote:
> > >> Here is a current trace I see after booting that kernel:
> > >> [ cut here ]
> > >> WARNING: CPU: 0 PID: 1 at drivers/iommu/intel-iommu.c:3214
> > >> intel_unmap+0x186/0x1f0()
> > >> Driver unmaps unmatched page at PFN 0
> > >> Modules linked in:
> > >> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.1.7-hardened-r1 #2
> > >> Hardware name: System manufacturer System Product Name/Z8P(N)E-D12(X),
> > >> BIOS 130206/25/2012
> > >>  ab40bd6b   ab21608f
> > >>  880237c03ca8 a4ed0fa6 15d2 880237c03d00
> > >>  880237c03ce8 a40ad9a0  ab21608f
> > >> Call Trace:
> > >>[] dump_stack+0x45/0x5d
> > >>  [] warn_slowpath_common+0x80/0xc0
> > >>  [] warn_slowpath_fmt+0x64/0x90
> > >>  [] intel_unmap+0x186/0x1f0
> > >>  [] intel_unmap_sg+0x1a/0x30
> > >>  [] scsi_dma_unmap+0x73/0x90
> > >>  [] twa_interrupt+0x493/0x780
> > >>  [] handle_irq_event_percpu+0x7a/0x130
> > >>  [] handle_irq_event+0x39/0x60
> > >>  [] handle_fasteoi_irq+0x89/0x1a0
> > >>  [] handle_irq+0x85/0x160
> > >>  [] do_IRQ+0x4c/0x100
> > >>  [] common_interrupt+0x97/0x97
> > >>[] ?
> > >> default_send_IPI_mask_allbutself_phys+0xbc/0x100
> > >>  [] physflat_send_IPI_allbutself+0x19/0x30
> > >>  [] native_send_call_func_ipi+0x108/0x140
> > >>  [] ? proc_dma_show+0x70/0x70
> > >>  [] smp_call_function_many+0x1c4/0x270
> > >>  [] kick_all_cpus_sync+0x21/0x30
> > >>  [] __do_tune_cpucache+0x56/0x4d0
> > >>  [] ? string.isra.3+0x47/0x100
> > >>  [] do_tune_cpucache+0x37/0xb0
> > >>  [] enable_cpucache+0x65/0x130
> > >>  [] setup_cpu_cache+0x173/0x270
> > >>  [] __kmem_cache_create+0x262/0x360
> > >>  [] do_kmem_cache_create+0x92/0x1d0
> > >>  [] kmem_cache_create+0x11e/0x1d0
> > >>  [] ? twa_init+0x36/0x36
> > >>  [] init_sd+0xd7/0x198
> > >>  [] do_one_initcall+0x94/0x1a0
> > >>  [] kernel_init_freeable+0x183/0x22f
> > >>  [] ? rest_init+0x80/0x80
> > >>  [] kernel_init+0x9/0xf0
> > >>  [] ret_from_fork+0x3e/0x70
> > >>  [] ? rest_init+0x80/0x80
> > >> ---[ end trace a39a5826ea41aa47 ]---
> > >>
> > >> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X motherboard.
> > >>
> > >
> > > Can you re-try with Christoph's patch:
> > >
> > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de
> > 
> > As I've told this patch has been already included in the kernel I'm using
> > (4.1.7-hardened-r1, which is based on 4.1.7).
> > Out of curiosity I've reverted the patch and the WARNING no longer appears
> > during boot...
> 
> Ah, it looks like there's a bug in the patch, it doesn't take into
> account that the driver has a minimum sg map length and it copies for
> things under that, so we're likely unmapping something that wasn't
> mapped.   It's slightly hard to fix given that the indicator flag we'd
> use for this is gone in that patch; does this fix the warning?

Actually, strike that, it would still barf on internally generated
commands (and it's recursively calling twa_scsi_dma_unmap).  This does a
partial revert of the state check which should pick up all cases the
input didn't go through the mapping.

James

---

diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index add419d..751ed66 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -151,7 +151,13 @@ static void 
twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
 
 /* Functions */
+static void twa_scsi_dma_unmap(struct scsi_cmnd *SCpnt)
+{
+   if (SCpnt->SCp.phase == TW_PHASE_SGLIST)
+   scsi_dma_unmap(SCpnt);
+}
 
+  
 /* Show some statistics about the card */
 static ssize_t twa_show_stats(struct device *dev,
  struct device_attribute *attr, char *buf)
@@ -1339,7 +1345,7 @@ static irqreturn_t twa_interrupt(int irq, void 
*dev_instance)
}
 
/* Now complete the io */
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd);
cmd->scsi_done(cmd);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
@@ -1582,7 +1588,7 @@ static int twa_reset_device_extension(TW_Device_Extension 
*tw_dev)
struct scsi_cmnd *cmd = tw_dev->srb[i];
 
cmd->result = (DID_RESET << 16);
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd);
  

RE: [PATCH V8 9/9] aacraid: Update driver version

2015-09-29 Thread Harry Yang
Hi James,

Would you help with this subject? Our customers are waiting for the approval of 
this patch. Please let us know if there is anything which we can to accelerate 
it.

BTW, we have another patch ready for submission and we have been waiting for 
current patch approved before next submission. Can we submit it before current 
patch approved? Again, our customers are making this request.

Thanks in advance.

Harry

-Original Message-
From: Mahesh Rajashekhara 
Sent: Tuesday, September 29, 2015 2:50 AM
To: jbottom...@parallels.com; linux-scsi@vger.kernel.org
Cc: the...@redhat.com; Murthy Bhat; Karthikeya Sunkesula; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: RE: [PATCH V8 9/9] aacraid: Update driver version

Hi James,

Can you please let me know the status of V8 patch set.

Thanks,
Mahesh


-Original Message-
From: Mahesh Rajashekhara 
Sent: Wednesday, September 09, 2015 6:51 PM
To: Mahesh Rajashekhara; jbottom...@parallels.com; linux-scsi@vger.kernel.org
Cc: the...@redhat.com; Murthy Bhat; Karthikeya Sunkesula; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: RE: [PATCH V8 9/9] aacraid: Update driver version

Hi James,

Please let me know the status of V8 patchset.

Thanks,
Mahesh

-Original Message-
From: Mahesh Rajashekhara [mailto:mahesh.rajashekh...@pmcs.com] 
Sent: Friday, August 28, 2015 4:09 PM
To: jbottom...@parallels.com; linux-scsi@vger.kernel.org
Cc: the...@redhat.com; Murthy Bhat; Karthikeya Sunkesula; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: [PATCH V8 9/9] aacraid: Update driver version

Reviewed-by: Tomas Henzl 
Reviewed-by: Murthy Bhat 
Reviewed-by: Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h 
index 2de5ebc..074878b 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -62,7 +62,7 @@ enum {
 #definePMC_GLOBAL_INT_BIT0 0x0001
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 40709
+# define AAC_DRIVER_BUILD 41010
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
--
1.9.3

--
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: twa generates WARNING upon boot

2015-09-29 Thread James Bottomley
On Tue, 2015-09-29 at 18:49 +0200, "Tóth Attila" wrote:
> 2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
> > On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila" 
> > wrote:
> >> Here is a current trace I see after booting that kernel:
> >> [ cut here ]
> >> WARNING: CPU: 0 PID: 1 at drivers/iommu/intel-iommu.c:3214
> >> intel_unmap+0x186/0x1f0()
> >> Driver unmaps unmatched page at PFN 0
> >> Modules linked in:
> >> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.1.7-hardened-r1 #2
> >> Hardware name: System manufacturer System Product Name/Z8P(N)E-D12(X),
> >> BIOS 130206/25/2012
> >>  ab40bd6b   ab21608f
> >>  880237c03ca8 a4ed0fa6 15d2 880237c03d00
> >>  880237c03ce8 a40ad9a0  ab21608f
> >> Call Trace:
> >>[] dump_stack+0x45/0x5d
> >>  [] warn_slowpath_common+0x80/0xc0
> >>  [] warn_slowpath_fmt+0x64/0x90
> >>  [] intel_unmap+0x186/0x1f0
> >>  [] intel_unmap_sg+0x1a/0x30
> >>  [] scsi_dma_unmap+0x73/0x90
> >>  [] twa_interrupt+0x493/0x780
> >>  [] handle_irq_event_percpu+0x7a/0x130
> >>  [] handle_irq_event+0x39/0x60
> >>  [] handle_fasteoi_irq+0x89/0x1a0
> >>  [] handle_irq+0x85/0x160
> >>  [] do_IRQ+0x4c/0x100
> >>  [] common_interrupt+0x97/0x97
> >>[] ?
> >> default_send_IPI_mask_allbutself_phys+0xbc/0x100
> >>  [] physflat_send_IPI_allbutself+0x19/0x30
> >>  [] native_send_call_func_ipi+0x108/0x140
> >>  [] ? proc_dma_show+0x70/0x70
> >>  [] smp_call_function_many+0x1c4/0x270
> >>  [] kick_all_cpus_sync+0x21/0x30
> >>  [] __do_tune_cpucache+0x56/0x4d0
> >>  [] ? string.isra.3+0x47/0x100
> >>  [] do_tune_cpucache+0x37/0xb0
> >>  [] enable_cpucache+0x65/0x130
> >>  [] setup_cpu_cache+0x173/0x270
> >>  [] __kmem_cache_create+0x262/0x360
> >>  [] do_kmem_cache_create+0x92/0x1d0
> >>  [] kmem_cache_create+0x11e/0x1d0
> >>  [] ? twa_init+0x36/0x36
> >>  [] init_sd+0xd7/0x198
> >>  [] do_one_initcall+0x94/0x1a0
> >>  [] kernel_init_freeable+0x183/0x22f
> >>  [] ? rest_init+0x80/0x80
> >>  [] kernel_init+0x9/0xf0
> >>  [] ret_from_fork+0x3e/0x70
> >>  [] ? rest_init+0x80/0x80
> >> ---[ end trace a39a5826ea41aa47 ]---
> >>
> >> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X motherboard.
> >>
> >
> > Can you re-try with Christoph's patch:
> >
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de
> 
> As I've told this patch has been already included in the kernel I'm using
> (4.1.7-hardened-r1, which is based on 4.1.7).
> Out of curiosity I've reverted the patch and the WARNING no longer appears
> during boot...

Ah, it looks like there's a bug in the patch, it doesn't take into
account that the driver has a minimum sg map length and it copies for
things under that, so we're likely unmapping something that wasn't
mapped.   It's slightly hard to fix given that the indicator flag we'd
use for this is gone in that patch; does this fix the warning?

James

---

diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index add419d..4c2c476 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -151,7 +151,19 @@ static void 
twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
 
 /* Functions */
+static void twa_scsi_dma_unmap(struct scsi_cmnd *SCpnt, int request_id)
+{
+   TW_Device_Extension *tw_dev = (TW_Device_Extension 
*)SCpnt->device->host->hostdata;
+   TW_Command_Apache *command_packet = 
&tw_dev->command_packet_virt[request_id]->command.newcommand;
+
+   if (command_packet->sg_list[0].address == 
TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]))
+   /* command is copied not mapped */
+   return;
+
+   twa_scsi_dma_unmap(SCpnt, request_id);
+}
 
+  
 /* Show some statistics about the card */
 static ssize_t twa_show_stats(struct device *dev,
  struct device_attribute *attr, char *buf)
@@ -1339,7 +1351,7 @@ static irqreturn_t twa_interrupt(int irq, void 
*dev_instance)
}
 
/* Now complete the io */
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd, request_id);
cmd->scsi_done(cmd);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
@@ -1582,7 +1594,7 @@ static int twa_reset_device_extension(TW_Device_Extension 
*tw_dev)
struct scsi_cmnd *cmd = tw_dev->srb[i];
 
cmd->result = (DID_RESET << 16);
-   scsi_dma_unmap(cmd);
+   twa_scsi_dma_unmap(cmd, i);
cmd->scsi_done(cmd);
}

Re: twa generates WARNING upon boot

2015-09-29 Thread Tóth Attila
2015.Szeptember 27.(V) 23:19 időpontban adam radford ezt írta:
> On Sun, Sep 27, 2015 at 4:56 AM, "Tóth Attila" 
> wrote:
>> Here is a current trace I see after booting that kernel:
>> [ cut here ]
>> WARNING: CPU: 0 PID: 1 at drivers/iommu/intel-iommu.c:3214
>> intel_unmap+0x186/0x1f0()
>> Driver unmaps unmatched page at PFN 0
>> Modules linked in:
>> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.1.7-hardened-r1 #2
>> Hardware name: System manufacturer System Product Name/Z8P(N)E-D12(X),
>> BIOS 130206/25/2012
>>  ab40bd6b   ab21608f
>>  880237c03ca8 a4ed0fa6 15d2 880237c03d00
>>  880237c03ce8 a40ad9a0  ab21608f
>> Call Trace:
>>[] dump_stack+0x45/0x5d
>>  [] warn_slowpath_common+0x80/0xc0
>>  [] warn_slowpath_fmt+0x64/0x90
>>  [] intel_unmap+0x186/0x1f0
>>  [] intel_unmap_sg+0x1a/0x30
>>  [] scsi_dma_unmap+0x73/0x90
>>  [] twa_interrupt+0x493/0x780
>>  [] handle_irq_event_percpu+0x7a/0x130
>>  [] handle_irq_event+0x39/0x60
>>  [] handle_fasteoi_irq+0x89/0x1a0
>>  [] handle_irq+0x85/0x160
>>  [] do_IRQ+0x4c/0x100
>>  [] common_interrupt+0x97/0x97
>>[] ?
>> default_send_IPI_mask_allbutself_phys+0xbc/0x100
>>  [] physflat_send_IPI_allbutself+0x19/0x30
>>  [] native_send_call_func_ipi+0x108/0x140
>>  [] ? proc_dma_show+0x70/0x70
>>  [] smp_call_function_many+0x1c4/0x270
>>  [] kick_all_cpus_sync+0x21/0x30
>>  [] __do_tune_cpucache+0x56/0x4d0
>>  [] ? string.isra.3+0x47/0x100
>>  [] do_tune_cpucache+0x37/0xb0
>>  [] enable_cpucache+0x65/0x130
>>  [] setup_cpu_cache+0x173/0x270
>>  [] __kmem_cache_create+0x262/0x360
>>  [] do_kmem_cache_create+0x92/0x1d0
>>  [] kmem_cache_create+0x11e/0x1d0
>>  [] ? twa_init+0x36/0x36
>>  [] init_sd+0xd7/0x198
>>  [] do_one_initcall+0x94/0x1a0
>>  [] kernel_init_freeable+0x183/0x22f
>>  [] ? rest_init+0x80/0x80
>>  [] kernel_init+0x9/0xf0
>>  [] ret_from_fork+0x3e/0x70
>>  [] ? rest_init+0x80/0x80
>> ---[ end trace a39a5826ea41aa47 ]---
>>
>> The 3ware card is a 9650SE-12ML running in a Asus Z8PE-D12X motherboard.
>>
>
> Can you re-try with Christoph's patch:
>
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=118c855b5623f3e2e6204f02623d88c09e0c34de

As I've told this patch has been already included in the kernel I'm using
(4.1.7-hardened-r1, which is based on 4.1.7).
Out of curiosity I've reverted the patch and the WARNING no longer appears
during boot...

Thx: Dw.
-- 
dr Tóth Attila, Radiológus, 06-20-825-8057
Attila Toth MD, Radiologist, +36-20-825-8057



> --
> 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


[Bug 101011] Kernel Oops when disconnecting a mounted ext4 usb stick

2015-09-29 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=101011

--- Comment #14 from Ronny Standtke  ---
> The revert is upstream as commit bdfe0cbd746aa9

Thanks for the info! I will apply the revert to 4.2.1.

> Especially if you are receiving paid support from the distribution, they are 
> much more likely to listen to you.  :-)

It's the other way around. I am maintaining a distribution and get paid for
supporting it. :-)

-- 
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


Re: [PATCH 33/36] scsi: Add 'access_state' attribute

2015-09-29 Thread kbuild test robot
Hi Hannes,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please 
ignore]

reproduce:
  # apt-get install sparse
  make ARCH=x86_64 allmodconfig
  make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> drivers/scsi/scsi_sysfs.c:98:12: sparse: symbol 'scsi_access_state_name' was 
>> not declared. Should it be static?
   drivers/scsi/scsi_sysfs.c:230:25: sparse: symbol 'dev_attr_hstate' was not 
declared. Should it be static?
   drivers/scsi/scsi_sysfs.c:405:24: sparse: symbol 'scsi_shost_attr_group' was 
not declared. Should it be static?
   drivers/scsi/scsi_sysfs.c:806:1: sparse: incompatible types in comparison 
expression (different address spaces)
   drivers/scsi/scsi_sysfs.c:807:1: sparse: incompatible types in comparison 
expression (different address spaces)

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
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 31/36] scsi: rescan VPD attributes

2015-09-29 Thread kbuild test robot
Hi Hannes,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please 
ignore]


coccinelle warnings: (new ones prefixed by >>)

>> drivers/scsi/scsi.c:888:3-8: WARNING: NULL check before freeing functions 
>> like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not 
>> needed. Maybe consider reorganizing relevant code to avoid passing NULL 
>> values.

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
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: fix ifnullfree.cocci warnings

2015-09-29 Thread kbuild test robot
drivers/scsi/scsi.c:888:3-8: WARNING: NULL check before freeing functions like 
kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. 
Maybe consider reorganizing relevant code to avoid passing NULL values.

 NULL check before some freeing functions is not needed.

 Based on checkpatch warning
 "kfree(NULL) is safe this check is probably not required"
 and kfreeaddr.cocci by Julia Lawall.

Generated by: scripts/coccinelle/free/ifnullfree.cocci

CC: Hannes Reinecke 
Signed-off-by: Fengguang Wu 
---

 scsi.c |3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -884,8 +884,7 @@ retry_pg83:
rcu_assign_pointer(sdev->vpd_pg83, vpd_buf);
mutex_unlock(&sdev->inquiry_mutex);
synchronize_rcu();
-   if (orig_vpd_buf)
-   kfree(orig_vpd_buf);
+   kfree(orig_vpd_buf);
}
 }
 
--
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 31/36] scsi: rescan VPD attributes

2015-09-29 Thread kbuild test robot
Hi Hannes,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please 
ignore]

reproduce:
  # apt-get install sparse
  make ARCH=x86_64 allmodconfig
  make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> drivers/scsi/scsi_lib.c:3181:20: sparse: incompatible types in comparison 
>> expression (different address spaces)
   drivers/scsi/scsi_lib.c:3311:20: sparse: incompatible types in comparison 
expression (different address spaces)
--
   drivers/scsi/scsi_sysfs.c:202:25: sparse: symbol 'dev_attr_hstate' was not 
declared. Should it be static?
   drivers/scsi/scsi_sysfs.c:377:24: sparse: symbol 'scsi_shost_attr_group' was 
not declared. Should it be static?
>> drivers/scsi/scsi_sysfs.c:778:1: sparse: incompatible types in comparison 
>> expression (different address spaces)
   drivers/scsi/scsi_sysfs.c:779:1: sparse: incompatible types in comparison 
expression (different address spaces)
--
>> drivers/scsi/ses.c:564:20: sparse: incompatible types in comparison 
>> expression (different address spaces)

vim +3181 drivers/scsi/scsi_lib.c

  3165   * Copies a unique device identification into @id based
  3166   * on the information in the VPD page 0x83 of the device.
  3167   * The string will be formatted as a SCSI name string.
  3168   *
  3169   * Returns the length of the identification or error on failure.
  3170   * If the identifier is longer than the supplied buffer the actual
  3171   * identifier length is returned and the buffer is not zero-padded.
  3172   */
  3173  int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
  3174  {
  3175  u8 cur_id_type = 0xff;
  3176  u8 cur_id_size = 0;
  3177  unsigned char *d, *cur_id_str, *vpd_pg83;
  3178  int id_size = -EAGAIN;
  3179  
  3180  rcu_read_lock();
> 3181  vpd_pg83 = rcu_dereference(sdev->vpd_pg83);
  3182  if (!vpd_pg83) {
  3183  rcu_read_unlock();
  3184  return -ENXIO;
  3185  }
  3186  
  3187  /*
  3188   * Look for the correct descriptor.
  3189   * Order of preference for lun descriptor:

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
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/3] scsi: Some miscellaneous fixes

2015-09-29 Thread Vitaly Kuznetsov
"K. Y. Srinivasan"  writes:

[...]

>
> Vitaly Kuznetsov (2):
>   scsi_scan: don't dump trace when scsi_prep_async_scan() is called
> twice
>   scsi: introduce short_inquiry flag for broken host adapters

James,

I'm sorry for the annoyance but when I asked about these patches last
time you said we don't have them reviewed. Is it OK now when we have
signed-off-by: from K. Y. or do we need to ask someone else?

Thanks,

-- 
  Vitaly
--
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 27/36] scsi_dh_alua: Use workqueue for RTPG

2015-09-29 Thread kbuild test robot
Hi Hannes,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please 
ignore]

reproduce:
  # apt-get install sparse
  make ARCH=x86_64 allmodconfig
  make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   drivers/scsi/device_handler/scsi_dh_alua.c:142:16: sparse: Variable length 
array is used.
   drivers/scsi/device_handler/scsi_dh_alua.c:171:16: sparse: Variable length 
array is used.
   drivers/scsi/device_handler/scsi_dh_alua.c:194:24: sparse: symbol 
'alua_lookup_pg' was not declared. Should it be static?
   drivers/scsi/device_handler/scsi_dh_alua.c:222:24: sparse: symbol 
'alua_get_pg' was not declared. Should it be static?
>> drivers/scsi/device_handler/scsi_dh_alua.c:856:14: sparse: incompatible 
>> types in comparison expression (different address spaces)
   drivers/scsi/device_handler/scsi_dh_alua.c:900:14: sparse: incompatible 
types in comparison expression (different address spaces)
   drivers/scsi/device_handler/scsi_dh_alua.c:935:14: sparse: incompatible 
types in comparison expression (different address spaces)

vim +856 drivers/scsi/device_handler/scsi_dh_alua.c

   840  struct alua_dh_data *h = sdev->handler_data;
   841  struct alua_port_group *pg = NULL;
   842  unsigned int optimize = 0, argc;
   843  const char *p = params;
   844  int result = SCSI_DH_OK;
   845  unsigned long flags;
   846  
   847  if ((sscanf(params, "%u", &argc) != 1) || (argc != 1))
   848  return -EINVAL;
   849  
   850  while (*p++)
   851  ;
   852  if ((sscanf(p, "%u", &optimize) != 1) || (optimize > 1))
   853  return -EINVAL;
   854  
   855  rcu_read_lock();
 > 856  pg = rcu_dereference(h->pg);
   857  if (!pg) {
   858  rcu_read_unlock();
   859  return -ENXIO;
   860  }
   861  spin_lock_irqsave(&pg->lock, flags);
   862  if (optimize)
   863  pg->flags |= ALUA_OPTIMIZE_STPG;
   864  else

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
--
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 26/36] revert "scsi_dh_alua: ALUA hander attach should succeed while TPG is transitioning"

2015-09-29 Thread Hannes Reinecke
This reverts commit a8e5a2d593cbfccf530c3382c2c328d2edaa7b66

Obsoleted by the next patch.

Reviewed-by: Ewan Milne 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 31 --
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 1755591..4113b76 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -91,7 +91,7 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_CURRENT 0
 #define ALUA_POLICY_SWITCH_ALL 1
 
-static int alua_rtpg(struct scsi_device *, struct alua_port_group *, int);
+static int alua_rtpg(struct scsi_device *, struct alua_port_group *);
 static char print_alua_state(int);
 
 static void release_port_group(struct kref *kref)
@@ -336,7 +336,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h,
if (!h->pg)
return SCSI_DH_NOMEM;
 
-   return alua_rtpg(sdev, h->pg, 0);
+   return alua_rtpg(sdev, h->pg);
 }
 
 static char print_alua_state(int state)
@@ -419,13 +419,12 @@ static int alua_check_sense(struct scsi_device *sdev,
 /*
  * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
  * @sdev: the device to be evaluated.
- * @wait_for_transition: if nonzero, wait ALUA_FAILOVER_TIMEOUT seconds for 
device to exit transitioning state
  *
  * Evaluate the Target Port Group State.
  * Returns SCSI_DH_DEV_OFFLINED if the path is
  * found to be unusable.
  */
-static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int 
wait_for_transition)
+static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
 {
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
@@ -516,8 +515,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
else
pg->transition_tmo = ALUA_FAILOVER_TIMEOUT;
 
-   if (wait_for_transition &&
-   (orig_transition_tmo != pg->transition_tmo)) {
+   if (orig_transition_tmo != pg->transition_tmo) {
sdev_printk(KERN_INFO, sdev,
"%s: transition timeout set to %d seconds\n",
ALUA_DH_NAME, pg->transition_tmo);
@@ -555,19 +553,14 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
 
switch (pg->state) {
case TPGS_STATE_TRANSITIONING:
-   if (wait_for_transition) {
-   if (time_before(jiffies, expiry)) {
-   /* State transition, retry */
-   interval += 2000;
-   msleep(interval);
-   goto retry;
-   }
-   err = SCSI_DH_RETRY;
-   } else {
-   err = SCSI_DH_OK;
+   if (time_before(jiffies, expiry)) {
+   /* State transition, retry */
+   interval += 2000;
+   msleep(interval);
+   goto retry;
}
-
/* Transitioning time exceeded, set port to standby */
+   err = SCSI_DH_RETRY;
pg->state = TPGS_STATE_STANDBY;
break;
case TPGS_STATE_OFFLINE:
@@ -727,14 +720,14 @@ static int alua_activate(struct scsi_device *sdev,
if (optimize_stpg)
h->pg->flags |= ALUA_OPTIMIZE_STPG;
 
-   err = alua_rtpg(sdev, h->pg, 1);
+   err = alua_rtpg(sdev, h->pg);
if (err != SCSI_DH_OK) {
kref_put(&h->pg->kref, release_port_group);
goto out;
}
err = alua_stpg(sdev, h->pg);
if (err == SCSI_DH_RETRY)
-   err = alua_rtpg(sdev, h->pg, 1);
+   err = alua_rtpg(sdev, h->pg);
kref_put(&h->pg->kref, release_port_group);
 out:
if (fn)
-- 
1.8.5.6

--
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 24/36] scsi: Add scsi_vpd_tpg_id()

2015-09-29 Thread Hannes Reinecke
Implement scsi_vpd_tpg_id() to extract the target
port group id and the relative port id from
SCSI VPD page 0x83.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_lib.c| 42 ++
 include/scsi/scsi_device.h |  1 +
 2 files changed, 43 insertions(+)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index de3dcef..fd4203c 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -3286,3 +3287,44 @@ next_desig:
return id_size;
 }
 EXPORT_SYMBOL(scsi_vpd_lun_id);
+
+/*
+ * scsi_vpd_tpg_id - return a target port group identifier
+ * @sdev: SCSI device
+ *
+ * Returns the Target Port Group identifier from the information
+ * froom VPD page 0x83 of the device.
+ *
+ * Returns the identifier or error on failure.
+ */
+int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
+{
+   unsigned char *d;
+   int group_id = -EAGAIN, rel_port = -1;
+
+   if (!sdev->vpd_pg83)
+   return -ENXIO;
+
+   d = sdev->vpd_pg83 + 4;
+   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+   switch (d[1] & 0xf) {
+   case 0x4:
+   /* Relative target port */
+   rel_port = get_unaligned_be16(&d[6]);
+   break;
+   case 0x5:
+   /* Target port group */
+   group_id = get_unaligned_be16(&d[6]);
+   break;
+   default:
+   break;
+   }
+   d += d[3] + 4;
+   }
+
+   if (group_id >= 0 && rel_id && rel_port != -1)
+   *rel_id = rel_port;
+
+   return group_id;
+}
+EXPORT_SYMBOL(scsi_vpd_tpg_id);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 6a9e6b2..cc6e763 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -415,6 +415,7 @@ static inline int scsi_execute_req(struct scsi_device *sdev,
 extern void sdev_disable_disk_events(struct scsi_device *sdev);
 extern void sdev_enable_disk_events(struct scsi_device *sdev);
 extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t);
+extern int scsi_vpd_tpg_id(struct scsi_device *, int *);
 
 #ifdef CONFIG_PM
 extern int scsi_autopm_get_device(struct scsi_device *);
-- 
1.8.5.6

--
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 18/36] scsi_dh_alua: rework alua_check_tpgs() to return the tpgs mode

2015-09-29 Thread Hannes Reinecke
Instead of returning an error code in alua_check_tpgs() we should
rather return the tpgs mode directly and have a cleanup syntax.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 25 +++--
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index b72cea6..c6fcfa5 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -167,24 +167,23 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
  * Examine the TPGS setting of the sdev to find out if ALUA
  * is supported.
  */
-static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_tpgs(struct scsi_device *sdev)
 {
-   int err = SCSI_DH_OK;
+   int tpgs = TPGS_MODE_NONE;
 
/*
 * ALUA support for non-disk devices is fraught with
 * difficulties, so disable it for now.
 */
if (sdev->type != TYPE_DISK) {
-   h->tpgs = TPGS_MODE_NONE;
sdev_printk(KERN_INFO, sdev,
"%s: disable for non-disk devices\n",
ALUA_DH_NAME);
-   return SCSI_DH_DEV_UNSUPP;
+   return tpgs;
}
 
-   h->tpgs = scsi_device_tpgs(sdev);
-   switch (h->tpgs) {
+   tpgs = scsi_device_tpgs(sdev);
+   switch (tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
sdev_printk(KERN_INFO, sdev,
"%s: supports implicit and explicit TPGS\n",
@@ -201,18 +200,16 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
case TPGS_MODE_NONE:
sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
ALUA_DH_NAME);
-   err = SCSI_DH_DEV_UNSUPP;
break;
default:
sdev_printk(KERN_INFO, sdev,
"%s: unsupported TPGS setting %d\n",
-   ALUA_DH_NAME, h->tpgs);
-   h->tpgs = TPGS_MODE_NONE;
-   err = SCSI_DH_DEV_UNSUPP;
+   ALUA_DH_NAME, tpgs);
+   tpgs = TPGS_MODE_NONE;
break;
}
 
-   return err;
+   return tpgs;
 }
 
 /*
@@ -587,10 +584,10 @@ static unsigned alua_stpg(struct scsi_device *sdev, 
struct alua_dh_data *h)
  */
 static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
 {
-   int err;
+   int err = SCSI_DH_DEV_UNSUPP;
 
-   err = alua_check_tpgs(sdev, h);
-   if (err != SCSI_DH_OK)
+   h->tpgs = alua_check_tpgs(sdev);
+   if (h->tpgs == TPGS_MODE_NONE)
goto out;
 
err = alua_check_vpd(sdev, h);
-- 
1.8.5.6

--
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 36/36] scsi_dh_alua: Update version to 2.0

2015-09-29 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 12e6ce9..98adc11 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -30,7 +30,7 @@
 #include 
 
 #define ALUA_DH_NAME "alua"
-#define ALUA_DH_VER "1.3"
+#define ALUA_DH_VER "2.0"
 
 #define TPGS_SUPPORT_NONE  0x00
 #define TPGS_SUPPORT_OPTIMIZED 0x01
-- 
1.8.5.6

--
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 33/36] scsi: Add 'access_state' attribute

2015-09-29 Thread Hannes Reinecke
Add an 'access_state' attribute to struct scsi_device to
display the asymmetric LUN access state.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_scan.c   |  1 +
 drivers/scsi/scsi_sysfs.c  | 49 ++
 include/scsi/scsi_device.h |  1 +
 include/scsi/scsi_proto.h  | 13 
 4 files changed, 64 insertions(+)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 5d3e2ae..76e771e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -230,6 +230,7 @@ static struct scsi_device *scsi_alloc_sdev(struct 
scsi_target *starget,
sdev->lun = lun;
sdev->channel = starget->channel;
sdev->sdev_state = SDEV_CREATED;
+   sdev->access_state = SCSI_ACCESS_STATE_UNKNOWN;
INIT_LIST_HEAD(&sdev->siblings);
INIT_LIST_HEAD(&sdev->same_target_siblings);
INIT_LIST_HEAD(&sdev->cmd_list);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 37799dc..38e157a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -81,6 +81,34 @@ const char *scsi_host_state_name(enum scsi_host_state state)
return name;
 }
 
+static const struct {
+   enum scsi_access_state  value;
+   char*name;
+} sdev_access_states[] = {
+   { SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" },
+   { SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" },
+   { SCSI_ACCESS_STATE_STANDBY, "standby" },
+   { SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" },
+   { SCSI_ACCESS_STATE_LBA, "lba-dependent" },
+   { SCSI_ACCESS_STATE_OFFLINE, "offline" },
+   { SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" },
+   { SCSI_ACCESS_STATE_UNKNOWN, "unknown" },
+};
+
+const char *scsi_access_state_name(enum scsi_access_state state)
+{
+   int i;
+   char *name = NULL;
+
+   for (i = 0; i < ARRAY_SIZE(sdev_access_states); i++) {
+   if (sdev_access_states[i].value == state) {
+   name = sdev_access_states[i].name;
+   break;
+   }
+   }
+   return name;
+}
+
 static int check_set(unsigned long long *val, char *src)
 {
char *last;
@@ -932,6 +960,26 @@ sdev_store_dh_state(struct device *dev, struct 
device_attribute *attr,
 
 static DEVICE_ATTR(dh_state, S_IRUGO | S_IWUSR, sdev_show_dh_state,
   sdev_store_dh_state);
+
+static ssize_t
+sdev_show_access_state(struct device *dev,
+  struct device_attribute *attr,
+  char *buf)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+   enum scsi_access_state access_state;
+   bool pref = false;
+
+   if (sdev->access_state & SCSI_ACCESS_STATE_PREFERRED)
+   pref = true;
+
+   access_state = (sdev->access_state & SCSI_ACCESS_STATE_MASK);
+
+   return snprintf(buf, 32, "%s%s\n",
+   scsi_access_state_name(access_state),
+   pref ? " preferred" :"");
+}
+static DEVICE_ATTR(access_state, S_IRUGO, sdev_show_access_state, NULL);
 #endif
 
 static ssize_t
@@ -1005,6 +1053,7 @@ static struct attribute *scsi_sdev_attrs[] = {
&dev_attr_queue_type.attr,
 #ifdef CONFIG_SCSI_DH
&dev_attr_dh_state.attr,
+   &dev_attr_access_state.attr,
 #endif
&dev_attr_queue_ramp_up_period.attr,
REF_EVT(media_change),
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index cfc23a4..666359f 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -200,6 +200,7 @@ struct scsi_device {
struct scsi_device_handler *handler;
void*handler_data;
 
+   enum scsi_access_state  access_state;
enum scsi_device_state sdev_state;
unsigned long   sdev_data[0];
 } __attribute__((aligned(sizeof(unsigned long;
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index a9fbf1b..80e85e7 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -277,5 +277,18 @@ struct scsi_lun {
__u8 scsi_lun[8];
 };
 
+/* SPC asymmetric access states */
+enum scsi_access_state {
+   SCSI_ACCESS_STATE_OPTIMAL = 0,
+   SCSI_ACCESS_STATE_ACTIVE,
+   SCSI_ACCESS_STATE_STANDBY,
+   SCSI_ACCESS_STATE_UNAVAILABLE,
+   SCSI_ACCESS_STATE_LBA,
+   SCSI_ACCESS_STATE_OFFLINE = 0xe,
+   SCSI_ACCESS_STATE_TRANSITIONING = 0xf,
+   SCSI_ACCESS_STATE_UNKNOWN = 0x70,
+};
+#define SCSI_ACCESS_STATE_MASK 0x0f
+#define SCSI_ACCESS_STATE_PREFERRED 0x80
 
 #endif /* _SCSI_PROTO_H_ */
-- 
1.8.5.6

--
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 35/36] scsi_dh_alua: update 'access_state' field

2015-09-29 Thread Hannes Reinecke
Track attached SCSI devices and update the 'access_state' field
whenever an ALUA state change has been detected.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index d9c7b42..12e6ce9 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +73,7 @@ static struct workqueue_struct *kaluad_wq;
 struct alua_port_group {
struct kref kref;
struct list_headnode;
+   struct list_headdh_list;
unsigned char   device_id_str[256];
int device_id_len;
int group_id;
@@ -89,6 +91,7 @@ struct alua_port_group {
 };
 
 struct alua_dh_data {
+   struct list_headnode;
struct alua_port_group  *pg;
int rel_port;
spinlock_t  pg_lock;
@@ -243,6 +246,7 @@ struct alua_port_group *alua_get_pg(struct scsi_device 
*sdev,
INIT_DELAYED_WORK(&pg->rtpg_work, alua_rtpg_work);
INIT_LIST_HEAD(&pg->rtpg_list);
INIT_LIST_HEAD(&pg->node);
+   INIT_LIST_HEAD(&pg->dh_list);
spin_lock_init(&pg->lock);
 
/* Re-check list again to catch concurrent updates */
@@ -371,13 +375,26 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h,
old_pg = pg;
/* port_group has changed. Update to new port group */
if (h->pg != pg) {
+   unsigned long flags;
+
old_pg = h->pg;
rcu_assign_pointer(h->pg, pg);
+   spin_lock_irqsave(&old_pg->lock, flags);
+   list_del_rcu(&h->node);
+   spin_unlock_irqrestore(&old_pg->lock, flags);
+   spin_lock_irqsave(&pg->lock, flags);
+   list_add_rcu(&h->node, &pg->dh_list);
+   spin_unlock_irqrestore(&pg->lock, flags);
h->pg->expiry = 0;
pg_found = true;
}
} else {
+   unsigned long flags;
+
rcu_assign_pointer(h->pg, pg);
+   spin_lock_irqsave(&pg->lock, flags);
+   list_add_rcu(&h->node, &pg->dh_list);
+   spin_unlock_irqrestore(&pg->lock, flags);
pg_found = true;
}
alua_rtpg_queue(h->pg, sdev, NULL, true);
@@ -629,6 +646,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
 
spin_lock_irqsave(&port_group_lock, flags);
list_for_each_entry(tmp_pg, &port_group_list, node) {
+   struct alua_dh_data *h;
+
if (tmp_pg->group_id != group_id)
continue;
if (tmp_pg->device_id_len != pg->device_id_len)
@@ -638,6 +657,12 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
continue;
tmp_pg->state = desc[0] & 0x0f;
tmp_pg->pref = desc[0] >> 7;
+   rcu_read_lock();
+   list_for_each_entry_rcu(h, &tmp_pg->dh_list, node) {
+   if (h->sdev)
+   h->sdev->access_state = desc[0];
+   }
+   rcu_read_unlock();
if (tmp_pg == pg)
valid_states = desc[1];
}
@@ -1054,6 +1079,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
h->rel_port = -1;
h->init_error = SCSI_DH_OK;
h->sdev = sdev;
+   INIT_LIST_HEAD(&h->node);
 
mutex_init(&h->init_mutex);
err = alua_initialize(sdev, h);
@@ -1084,6 +1110,9 @@ static void alua_bus_detach(struct scsi_device *sdev)
h->sdev = NULL;
spin_unlock(&h->pg_lock);
if (pg) {
+   spin_lock(&pg->lock);
+   list_del_rcu(&h->node);
+   spin_unlock(&pg->lock);
synchronize_rcu();
if (pg->rtpg_sdev)
flush_delayed_work(&pg->rtpg_work);
-- 
1.8.5.6

--
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 30/36] scsi_dh_alua: Send TEST UNIT READY to poll for transitioning

2015-09-29 Thread Hannes Reinecke
Sending a 'REPORT TARGET PORT GROUP' command is a costly operation,
as the array has to gather information about all ports.
So instead of using RTPG to poll for a status update when a port
is in transitioning we should be sending a TEST UNIT READY, and
wait for the sense code to report success.

Signed-off-by: Hannes Reinecke 
Reviewed-by: Ewan Milne 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 37 ++
 1 file changed, 37 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index dd8682e..7476c8a 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -490,6 +490,30 @@ static int alua_check_sense(struct scsi_device *sdev,
 }
 
 /*
+ * alua_tur - Send a TEST UNIT READY
+ * @sdev: device to which the TEST UNIT READY command should be send
+ *
+ * Send a TEST UNIT READY to @sdev to figure out the device state
+ * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING,
+ * SCSI_DH_OK if no error occured, and SCSI_DH_IO otherwise.
+ */
+static int alua_tur(struct scsi_device *sdev)
+{
+   struct scsi_sense_hdr sense_hdr;
+   int retval;
+
+   retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ,
+ ALUA_FAILOVER_RETRIES, &sense_hdr);
+   if (sense_hdr.sense_key == NOT_READY &&
+   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
+   return SCSI_DH_RETRY;
+   else if (retval)
+   return SCSI_DH_IO;
+   else
+   return SCSI_DH_OK;
+}
+
+/*
  * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
  * @sdev: the device to be evaluated.
  *
@@ -750,7 +774,20 @@ static void alua_rtpg_work(struct work_struct *work)
}
pg->flags |= ALUA_PG_RUNNING;
if (pg->flags & ALUA_PG_RUN_RTPG) {
+   int state = pg->state;
+
spin_unlock_irqrestore(&pg->lock, flags);
+   if (state == TPGS_STATE_TRANSITIONING) {
+   if (alua_tur(sdev) == SCSI_DH_RETRY) {
+   spin_lock_irqsave(&pg->lock, flags);
+   pg->flags &= ~ALUA_PG_RUNNING;
+   spin_unlock_irqrestore(&pg->lock, flags);
+   queue_delayed_work(kaluad_wq, &pg->rtpg_work,
+  pg->interval * HZ);
+   return;
+   }
+   /* Send RTPG on failure or if TUR indicates SUCCESS */
+   }
err = alua_rtpg(sdev, pg);
spin_lock_irqsave(&pg->lock, flags);
if (err == SCSI_DH_RETRY) {
-- 
1.8.5.6

--
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 32/36] scsi_dh: add 'rescan' callback

2015-09-29 Thread Hannes Reinecke
If a device needs to be rescanned the device_handler might need
to be rechecked, too.
So add a 'rescan' callback to the device handler and call it
upon scsi_rescan_device().

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 8 
 drivers/scsi/scsi_lib.c| 1 +
 drivers/scsi/scsi_scan.c   | 8 +++-
 include/scsi/scsi_dh.h | 1 +
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7476c8a..4ed889b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1038,6 +1038,13 @@ static int alua_prep_fn(struct scsi_device *sdev, struct 
request *req)
 
 }
 
+static void alua_rescan(struct scsi_device *sdev)
+{
+   struct alua_dh_data *h = sdev->handler_data;
+
+   alua_initialize(sdev, h);
+}
+
 /*
  * alua_bus_attach - Attach device handler
  * @sdev: device to be attached to
@@ -1102,6 +1109,7 @@ static struct scsi_device_handler alua_dh = {
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
+   .rescan = alua_rescan,
.set_params = alua_set_params,
 };
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b069b1e..fef76d9 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2699,6 +2699,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, 
struct scsi_event *evt)
envp[idx++] = "SDEV_MEDIA_CHANGE=1";
break;
case SDEV_EVT_INQUIRY_CHANGE_REPORTED:
+   scsi_rescan_device(&sdev->sdev_gendev);
envp[idx++] = "SDEV_UA=INQUIRY_DATA_HAS_CHANGED";
break;
case SDEV_EVT_CAPACITY_CHANGE_REPORTED:
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 190d743..5d3e2ae 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -43,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "scsi_priv.h"
@@ -1516,9 +1517,14 @@ EXPORT_SYMBOL(scsi_add_device);
 
 void scsi_rescan_device(struct device *dev)
 {
+   struct scsi_device *sdev = to_scsi_device(dev);
+
device_lock(dev);
 
-   scsi_attach_vpd(to_scsi_device(dev));
+   scsi_attach_vpd(sdev);
+
+   if (sdev->handler && sdev->handler->rescan)
+   sdev->handler->rescan(sdev);
 
if (dev->driver && try_module_get(dev->driver->owner)) {
struct scsi_driver *drv = to_scsi_driver(dev->driver);
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
index 7e184c6..c7bba2b 100644
--- a/include/scsi/scsi_dh.h
+++ b/include/scsi/scsi_dh.h
@@ -71,6 +71,7 @@ struct scsi_device_handler {
int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *);
+   void (*rescan)(struct scsi_device *);
 };
 
 #ifdef CONFIG_SCSI_DH
-- 
1.8.5.6

--
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 31/36] scsi: rescan VPD attributes

2015-09-29 Thread Hannes Reinecke
This patch implements a VPD page rescan if the 'rescan' sysfs
attribute is triggered.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi.c| 20 +---
 drivers/scsi/scsi_lib.c| 27 ++-
 drivers/scsi/scsi_scan.c   |  4 
 drivers/scsi/scsi_sysfs.c  |  8 ++--
 drivers/scsi/ses.c | 13 +
 include/scsi/scsi_device.h |  1 +
 6 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 207d6a7..f1c0fb5 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -803,7 +803,7 @@ void scsi_attach_vpd(struct scsi_device *sdev)
int vpd_len = SCSI_VPD_PG_LEN;
int pg80_supported = 0;
int pg83_supported = 0;
-   unsigned char *vpd_buf;
+   unsigned char *vpd_buf, *orig_vpd_buf = NULL;
 
if (sdev->skip_vpd_pages)
return;
@@ -849,8 +849,16 @@ retry_pg80:
kfree(vpd_buf);
goto retry_pg80;
}
+   mutex_lock(&sdev->inquiry_mutex);
+   orig_vpd_buf = sdev->vpd_pg80;
sdev->vpd_pg80_len = result;
-   sdev->vpd_pg80 = vpd_buf;
+   rcu_assign_pointer(sdev->vpd_pg80, vpd_buf);
+   mutex_unlock(&sdev->inquiry_mutex);
+   synchronize_rcu();
+   if (orig_vpd_buf) {
+   kfree(orig_vpd_buf);
+   orig_vpd_buf = NULL;
+   }
vpd_len = SCSI_VPD_PG_LEN;
}
 
@@ -870,8 +878,14 @@ retry_pg83:
kfree(vpd_buf);
goto retry_pg83;
}
+   mutex_lock(&sdev->inquiry_mutex);
+   orig_vpd_buf = sdev->vpd_pg83;
sdev->vpd_pg83_len = result;
-   sdev->vpd_pg83 = vpd_buf;
+   rcu_assign_pointer(sdev->vpd_pg83, vpd_buf);
+   mutex_unlock(&sdev->inquiry_mutex);
+   synchronize_rcu();
+   if (orig_vpd_buf)
+   kfree(orig_vpd_buf);
}
 }
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fd4203c..b069b1e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3174,11 +3174,15 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, 
size_t id_len)
 {
u8 cur_id_type = 0xff;
u8 cur_id_size = 0;
-   unsigned char *d, *cur_id_str;
+   unsigned char *d, *cur_id_str, *vpd_pg83;
int id_size = -EAGAIN;
 
-   if (!sdev->vpd_pg83)
+   rcu_read_lock();
+   vpd_pg83 = rcu_dereference(sdev->vpd_pg83);
+   if (!vpd_pg83) {
+   rcu_read_unlock();
return -ENXIO;
+   }
 
/*
 * Look for the correct descriptor.
@@ -3198,8 +3202,8 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, 
size_t id_len)
return -EINVAL;
 
memset(id, 0, id_len);
-   d = sdev->vpd_pg83 + 4;
-   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+   d = vpd_pg83 + 4;
+   while (d < vpd_pg83 + sdev->vpd_pg83_len) {
/* Skip designators not referring to the LUN */
if ((d[1] & 0x30) != 0x00)
goto next_desig;
@@ -3283,6 +3287,7 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, 
size_t id_len)
 next_desig:
d += d[3] + 4;
}
+   rcu_read_unlock();
 
return id_size;
 }
@@ -3299,14 +3304,17 @@ EXPORT_SYMBOL(scsi_vpd_lun_id);
  */
 int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
 {
-   unsigned char *d;
+   unsigned char *d, *vpd_pg83;
int group_id = -EAGAIN, rel_port = -1;
 
-   if (!sdev->vpd_pg83)
+   rcu_read_lock();
+   vpd_pg83 = rcu_dereference(sdev->vpd_pg83);
+   if (!vpd_pg83) {
+   rcu_read_unlock();
return -ENXIO;
-
-   d = sdev->vpd_pg83 + 4;
-   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+   }
+   d = vpd_pg83 + 4;
+   while (d < vpd_pg83 + sdev->vpd_pg83_len) {
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
@@ -3321,6 +3329,7 @@ int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
}
d += d[3] + 4;
}
+   rcu_read_unlock();
 
if (group_id >= 0 && rel_id && rel_port != -1)
*rel_id = rel_port;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f9f3f82..190d743 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -235,6 +235,7 @@ static struct scsi_device *scsi_alloc_sdev(struct 
scsi_target *starget,
INIT_LIST_HEAD(&sdev->starved_entry);
INIT_LIST_HEAD(&sdev->event_list);
spin_lock_init(&sdev->list_lock);
+   mutex_init(&sdev->inquiry_mutex);
INIT_WORK(&sdev->event_work, scsi_evt_thread);
INIT_WORK(&sdev->reque

[PATCH 34/36] scsi_dh_alua: use common definitions for ALUA state

2015-09-29 Thread Hannes Reinecke
scsi_proto.h now contains definitions for the ALUA state,
so we don't have to carry them in the device handler.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 62 +-
 1 file changed, 27 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4ed889b..d9c7b42 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -31,14 +31,6 @@
 #define ALUA_DH_NAME "alua"
 #define ALUA_DH_VER "1.3"
 
-#define TPGS_STATE_OPTIMIZED   0x0
-#define TPGS_STATE_NONOPTIMIZED0x1
-#define TPGS_STATE_STANDBY 0x2
-#define TPGS_STATE_UNAVAILABLE 0x3
-#define TPGS_STATE_LBA_DEPENDENT   0x4
-#define TPGS_STATE_OFFLINE 0xe
-#define TPGS_STATE_TRANSITIONING   0xf
-
 #define TPGS_SUPPORT_NONE  0x00
 #define TPGS_SUPPORT_OPTIMIZED 0x01
 #define TPGS_SUPPORT_NONOPTIMIZED  0x02
@@ -177,7 +169,7 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
 
/* Prepare the data buffer */
memset(stpg_data, 0, stpg_len);
-   stpg_data[4] = TPGS_STATE_OPTIMIZED & 0x0f;
+   stpg_data[4] = SCSI_ACCESS_STATE_OPTIMAL & 0x0f;
put_unaligned_be16(group_id, &stpg_data[6]);
 
/* Prepare the command. */
@@ -244,7 +236,7 @@ struct alua_port_group *alua_get_pg(struct scsi_device 
*sdev,
pg->device_id_len = id_size;
pg->group_id = group_id;
pg->tpgs = tpgs;
-   pg->state = TPGS_STATE_OPTIMIZED;
+   pg->state = SCSI_ACCESS_STATE_OPTIMAL;
if (optimize_stpg)
pg->flags |= ALUA_OPTIMIZE_STPG;
kref_init(&pg->kref);
@@ -402,22 +394,22 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h,
return SCSI_DH_OK;
 }
 
-static char print_alua_state(int state)
+static char print_alua_state(enum scsi_access_state state)
 {
switch (state) {
-   case TPGS_STATE_OPTIMIZED:
+   case SCSI_ACCESS_STATE_OPTIMAL:
return 'A';
-   case TPGS_STATE_NONOPTIMIZED:
+   case SCSI_ACCESS_STATE_ACTIVE:
return 'N';
-   case TPGS_STATE_STANDBY:
+   case SCSI_ACCESS_STATE_STANDBY:
return 'S';
-   case TPGS_STATE_UNAVAILABLE:
+   case SCSI_ACCESS_STATE_UNAVAILABLE:
return 'U';
-   case TPGS_STATE_LBA_DEPENDENT:
+   case SCSI_ACCESS_STATE_LBA:
return 'L';
-   case TPGS_STATE_OFFLINE:
+   case SCSI_ACCESS_STATE_OFFLINE:
return 'O';
-   case TPGS_STATE_TRANSITIONING:
+   case SCSI_ACCESS_STATE_TRANSITIONING:
return 'T';
default:
return 'X';
@@ -666,7 +658,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
 
switch (pg->state) {
-   case TPGS_STATE_TRANSITIONING:
+   case SCSI_ACCESS_STATE_TRANSITIONING:
if (time_before(jiffies, pg->expiry)) {
/* State transition, retry */
pg->interval = 2;
@@ -674,11 +666,11 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
} else {
/* Transitioning time exceeded, set port to standby */
err = SCSI_DH_IO;
-   pg->state = TPGS_STATE_STANDBY;
+   pg->state = SCSI_ACCESS_STATE_STANDBY;
pg->expiry = 0;
}
break;
-   case TPGS_STATE_OFFLINE:
+   case SCSI_ACCESS_STATE_OFFLINE:
/* Path unusable */
err = SCSI_DH_DEV_OFFLINED;
pg->expiry = 0;
@@ -710,21 +702,21 @@ static unsigned alua_stpg(struct scsi_device *sdev, 
struct alua_port_group *pg)
return SCSI_DH_RETRY;
}
switch (pg->state) {
-   case TPGS_STATE_OPTIMIZED:
+   case SCSI_ACCESS_STATE_OPTIMAL:
return SCSI_DH_OK;
-   case TPGS_STATE_NONOPTIMIZED:
+   case SCSI_ACCESS_STATE_ACTIVE:
if ((pg->flags & ALUA_OPTIMIZE_STPG) &&
!pg->pref &&
(pg->tpgs & TPGS_MODE_IMPLICIT))
return SCSI_DH_OK;
break;
-   case TPGS_STATE_STANDBY:
-   case TPGS_STATE_UNAVAILABLE:
+   case SCSI_ACCESS_STATE_STANDBY:
+   case SCSI_ACCESS_STATE_UNAVAILABLE:
break;
-   case TPGS_STATE_OFFLINE:
+   case SCSI_ACCESS_STATE_OFFLINE:
return SCSI_DH_IO;
break;
-   case TPGS_STATE_TRANSITIONING:
+   case SCSI_ACCESS_STATE_TRANSITIONING:
break;
default:
sdev_printk(KERN_INFO, sdev,
@@ -734,7 +726,7 @@ static unsigned alua_stpg(struct scsi_device *sdev

[PATCH 29/36] scsi_dh_alua: update all port states

2015-09-29 Thread Hannes Reinecke
When we read in the target port group state we should be
updating all affected port groups, otherwise we risk
running out of sync.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 31 +-
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 21f0d20..dd8682e 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -500,11 +500,13 @@ static int alua_check_sense(struct scsi_device *sdev,
 static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
 {
struct scsi_sense_hdr sense_hdr;
+   struct alua_port_group *tmp_pg;
int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
-   unsigned char *ucp, *buff;
+   unsigned char *desc, *buff;
unsigned err, retval;
unsigned int tpg_desc_tbl_off;
unsigned char orig_transition_tmo;
+   unsigned long flags;
 
if (!pg->expiry) {
if (!pg->transition_tmo)
@@ -604,16 +606,27 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
else
tpg_desc_tbl_off = 4;
 
-   for (k = tpg_desc_tbl_off, ucp = buff + tpg_desc_tbl_off;
+   for (k = tpg_desc_tbl_off, desc = buff + tpg_desc_tbl_off;
 k < len;
-k += off, ucp += off) {
-
-   if (pg->group_id == get_unaligned_be16(&ucp[2])) {
-   pg->state = ucp[0] & 0x0f;
-   pg->pref = ucp[0] >> 7;
-   valid_states = ucp[1];
+k += off, desc += off) {
+   u16 group_id = get_unaligned_be16(&desc[2]);
+
+   spin_lock_irqsave(&port_group_lock, flags);
+   list_for_each_entry(tmp_pg, &port_group_list, node) {
+   if (tmp_pg->group_id != group_id)
+   continue;
+   if (tmp_pg->device_id_len != pg->device_id_len)
+   continue;
+   if (strncmp(tmp_pg->device_id_str, pg->device_id_str,
+   tmp_pg->device_id_len))
+   continue;
+   tmp_pg->state = desc[0] & 0x0f;
+   tmp_pg->pref = desc[0] >> 7;
+   if (tmp_pg == pg)
+   valid_states = desc[1];
}
-   off = 8 + (ucp[7] * 4);
+   spin_unlock_irqrestore(&port_group_lock, flags);
+   off = 8 + (desc[7] * 4);
}
 
sdev_printk(KERN_INFO, sdev,
-- 
1.8.5.6

--
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 20/36] scsi_dh_alua: allocate RTPG buffer separately

2015-09-29 Thread Hannes Reinecke
The RTPG buffer will only evaluated within alua_rtpg(),
so we can allocate it locally there and avoid having to
put it into the global structure.

Reviewed-by: Ewan Milne 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 56 +++---
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index f3b455f..5908ef2 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -56,7 +56,7 @@
 #define TPGS_MODE_IMPLICIT 0x1
 #define TPGS_MODE_EXPLICIT 0x2
 
-#define ALUA_INQUIRY_SIZE  36
+#define ALUA_RTPG_SIZE 128
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
 
@@ -75,9 +75,6 @@ struct alua_port_group {
int state;
int pref;
unsignedflags; /* used for optimizing STPG */
-   unsigned char   inq[ALUA_INQUIRY_SIZE];
-   unsigned char   *buff;
-   int bufflen;
unsigned char   transition_tmo;
 };
 
@@ -96,21 +93,6 @@ struct alua_dh_data {
 static char print_alua_state(int);
 static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
-static int realloc_buffer(struct alua_port_group *pg, unsigned len)
-{
-   if (pg->buff && pg->buff != pg->inq)
-   kfree(pg->buff);
-
-   pg->buff = kmalloc(len, GFP_NOIO);
-   if (!pg->buff) {
-   pg->buff = pg->inq;
-   pg->bufflen = ALUA_INQUIRY_SIZE;
-   return 1;
-   }
-   pg->bufflen = len;
-   return 0;
-}
-
 static void release_port_group(struct kref *kref)
 {
struct alua_port_group *pg;
@@ -120,8 +102,6 @@ static void release_port_group(struct kref *kref)
spin_lock(&port_group_lock);
list_del(&pg->node);
spin_unlock(&port_group_lock);
-   if (pg->buff && pg->inq != pg->buff)
-   kfree(pg->buff);
kfree(pg);
 }
 
@@ -206,8 +186,6 @@ struct alua_port_group *alua_get_pg(struct scsi_device 
*sdev,
return NULL;
}
pg->group_id = group_id;
-   pg->buff = pg->inq;
-   pg->bufflen = ALUA_INQUIRY_SIZE;
pg->tpgs = tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
kref_init(&pg->kref);
@@ -433,8 +411,8 @@ static int alua_check_sense(struct scsi_device *sdev,
 static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int 
wait_for_transition)
 {
struct scsi_sense_hdr sense_hdr;
-   int len, k, off, valid_states = 0;
-   unsigned char *ucp;
+   int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
+   unsigned char *ucp, *buff;
unsigned err, retval;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
@@ -445,15 +423,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
else
expiry = round_jiffies_up(jiffies + pg->transition_tmo * HZ);
 
+   buff = kzalloc(bufflen, GFP_KERNEL);
+   if (!buff)
+   return SCSI_DH_DEV_TEMP_BUSY;
+
  retry:
-   retval = submit_rtpg(sdev, pg->buff, pg->bufflen,
-&sense_hdr, pg->flags);
+   retval = submit_rtpg(sdev, buff, bufflen, &sense_hdr, pg->flags);
 
if (retval) {
if (!scsi_sense_valid(&sense_hdr)) {
sdev_printk(KERN_INFO, sdev,
"%s: rtpg failed, result %d\n",
ALUA_DH_NAME, retval);
+   kfree(buff);
if (driver_byte(retval) == DRIVER_ERROR)
return SCSI_DH_DEV_TEMP_BUSY;
return SCSI_DH_IO;
@@ -484,14 +466,18 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n",
ALUA_DH_NAME);
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
+   kfree(buff);
return SCSI_DH_IO;
}
 
-   len = get_unaligned_be32(&pg->buff[0]) + 4;
+   len = get_unaligned_be32(&buff[0]) + 4;
 
-   if (len > pg->bufflen) {
+   if (len > bufflen) {
/* Resubmit with the correct length */
-   if (realloc_buffer(pg, len)) {
+   kfree(buff);
+   bufflen = len;
+   buff = kmalloc(bufflen, GFP_KERNEL);
+   if (!buff) {
sdev_printk(KERN_WARNING, sdev,
"%s: kmalloc buffer failed\n",__func__);
/* Temporary failure, bypass */
@@ -501,9 +487,8 @@ static int alua_rtpg(struct scsi_device *sdev, str

[PATCH 21/36] scsi_dh_alua: simplify sense code handling

2015-09-29 Thread Hannes Reinecke
Most sense code is already handled in the generic
code, so we shouldn't be adding special cases here.
However, when doing so we need to check for
unit attention whenever we're sending an internal
command.

Reviewed-by: Ewan Milne 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 36 +-
 1 file changed, 10 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 5908ef2..398ea81 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -91,7 +91,6 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_ALL 1
 
 static char print_alua_state(int);
-static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
 static void release_port_group(struct kref *kref)
 {
@@ -332,28 +331,6 @@ static int alua_check_sense(struct scsi_device *sdev,
 * LUN Not Accessible - ALUA state transition
 */
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0b)
-   /*
-* LUN Not Accessible -- Target port in standby state
-*/
-   return SUCCESS;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0c)
-   /*
-* LUN Not Accessible -- Target port in unavailable 
state
-*/
-   return SUCCESS;
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x12)
-   /*
-* LUN Not Ready -- Offline
-*/
-   return SUCCESS;
-   if (sdev->allow_restart &&
-   sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x02)
-   /*
-* if the device is not started, we need to wake
-* the error handler to start the motor
-*/
-   return FAILED;
break;
case UNIT_ATTENTION:
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
@@ -455,9 +432,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg, int w
pg->flags |= ALUA_RTPG_EXT_HDR_UNSUPP;
goto retry;
}
-
-   err = alua_check_sense(sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) {
+   /*
+* Retry on ALUA state transition or if any
+* UNIT ATTENTION occurred.
+*/
+   if (sense_hdr.sense_key == NOT_READY &&
+   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
+   err = SCSI_DH_RETRY;
+   else if (sense_hdr.sense_key == UNIT_ATTENTION)
+   err = SCSI_DH_RETRY;
+   if (err == SCSI_DH_RETRY && time_before(jiffies, expiry)) {
sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n",
ALUA_DH_NAME);
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
-- 
1.8.5.6

--
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 28/36] scsi_dh_alua: Recheck state on unit attention

2015-09-29 Thread Hannes Reinecke
When we receive a unit attention code of 'ALUA state changed'
we should recheck the state, as it might be due to an implicit
ALUA state transition. This allows us to return NEEDS_RETRY
instead of ADD_TO_MLQUEUE, allowing to terminate the retries
after a certain time.
At the same time a workqueue item might already be queued, which
should be started immediately to avoid any delays.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 58 --
 1 file changed, 47 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 1b7153f..21f0d20 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -117,7 +117,8 @@ struct alua_queue_data {
 static void alua_rtpg_work(struct work_struct *work);
 static void alua_rtpg_queue(struct alua_port_group *pg,
struct scsi_device *sdev,
-   struct alua_queue_data *qdata);
+   struct alua_queue_data *qdata, bool force);
+static void alua_check(struct scsi_device *sdev, bool force);
 
 static void release_port_group(struct kref *kref)
 {
@@ -387,7 +388,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h,
rcu_assign_pointer(h->pg, pg);
pg_found = true;
}
-   alua_rtpg_queue(h->pg, sdev, NULL);
+   alua_rtpg_queue(h->pg, sdev, NULL, true);
spin_unlock(&h->pg_lock);
 
if (pg_found)
@@ -428,18 +429,24 @@ static int alua_check_sense(struct scsi_device *sdev,
 {
switch (sense_hdr->sense_key) {
case NOT_READY:
-   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a)
+   if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) {
/*
 * LUN Not Accessible - ALUA state transition
 */
-   return ADD_TO_MLQUEUE;
+   alua_check(sdev, false);
+   return NEEDS_RETRY;
+   }
break;
case UNIT_ATTENTION:
-   if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
+   if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) {
/*
-* Power On, Reset, or Bus Device Reset, just retry.
+* Power On, Reset, or Bus Device Reset.
+* Might have obscured a state transition,
+* so schedule a recheck.
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
+   }
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x04)
/*
 * Device internal reset
@@ -450,16 +457,20 @@ static int alua_check_sense(struct scsi_device *sdev,
 * Mode Parameters Changed
 */
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
+   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
/*
 * ALUA state changed
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
-   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07)
+   }
+   if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
/*
 * Implicit ALUA state transition failed
 */
+   alua_check(sdev, true);
return ADD_TO_MLQUEUE;
+   }
if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x03)
/*
 * Inquiry data has changed
@@ -775,7 +786,7 @@ static void alua_rtpg_work(struct work_struct *work)
 
 static void alua_rtpg_queue(struct alua_port_group *pg,
struct scsi_device *sdev,
-   struct alua_queue_data *qdata)
+   struct alua_queue_data *qdata, bool force)
 {
int start_queue = 0;
unsigned long flags;
@@ -795,7 +806,9 @@ static void alua_rtpg_queue(struct alua_port_group *pg,
pg->rtpg_sdev = sdev;
scsi_device_get(sdev);
start_queue = 1;
-   }
+   } else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force)
+   start_queue = 1;
+
spin_unlock_irqrestore(&pg->lock, flags);
 
if (start_queue &&
@@ -910,7 +923,7 @@ static int alua_activate(struct scsi_device *sdev,
kref_get(&pg->kref);
rcu_read_unlock();
 
-   alua_rtpg_queue(pg, sdev, qdata);
+   alua_rtpg_queue(pg, sdev, qdata, true);
kref_put(&pg-

[PATCH 23/36] scsi_dh_alua: use unique device id

2015-09-29 Thread Hannes Reinecke
Use scsi_vpd_lun_id() to assign a unique device identification
to the alua port group structure.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 65 --
 1 file changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 398ea81..e2e6177 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -70,6 +70,8 @@ static DEFINE_SPINLOCK(port_group_lock);
 struct alua_port_group {
struct kref kref;
struct list_headnode;
+   unsigned char   device_id_str[256];
+   int device_id_len;
int group_id;
int tpgs;
int state;
@@ -163,6 +165,25 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
  ALUA_FAILOVER_RETRIES, NULL, req_flags);
 }
 
+struct alua_port_group *alua_lookup_pg(char *id_str, size_t id_size,
+  int group_id)
+{
+   struct alua_port_group *pg = NULL;
+
+   list_for_each_entry(pg, &port_group_list, node) {
+   if (pg->group_id != group_id)
+   continue;
+   if (pg->device_id_len != id_size)
+   continue;
+   if (strncmp(pg->device_id_str, id_str, id_size))
+   continue;
+   kref_get(&pg->kref);
+   return pg;
+   }
+
+   return NULL;
+}
+
 /*
  * alua_get_pg - Allocate a new port_group structure
  * @sdev: scsi device
@@ -173,9 +194,16 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
  * device.
  */
 struct alua_port_group *alua_get_pg(struct scsi_device *sdev,
-   int group_id, int tpgs)
+   int group_id, int tpgs,
+   char *id_str, size_t id_size)
 {
-   struct alua_port_group *pg = NULL;
+   struct alua_port_group *pg = NULL, *tmp_pg;
+
+   spin_lock(&port_group_lock);
+   pg = alua_lookup_pg(id_str, id_size, group_id);
+   spin_unlock(&port_group_lock);
+   if (pg)
+   return pg;
 
pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
if (!pg) {
@@ -184,11 +212,22 @@ struct alua_port_group *alua_get_pg(struct scsi_device 
*sdev,
ALUA_DH_NAME);
return NULL;
}
+   strncpy(pg->device_id_str, id_str, sizeof(pg->device_id_str));
+
+   pg->device_id_len = id_size;
pg->group_id = group_id;
pg->tpgs = tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
kref_init(&pg->kref);
+
+   /* Re-check list again to catch concurrent updates */
spin_lock(&port_group_lock);
+   tmp_pg = alua_lookup_pg(id_str, id_size, group_id);
+   if (tmp_pg) {
+   spin_unlock(&port_group_lock);
+   kfree(pg);
+   return tmp_pg;
+   }
list_add(&pg->node, &port_group_list);
spin_unlock(&port_group_lock);
 
@@ -614,6 +653,8 @@ static unsigned alua_stpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
 static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
 {
int err = SCSI_DH_DEV_UNSUPP, tpgs;
+   char device_id_str[256];
+   int device_id_len;
 
tpgs = alua_check_tpgs(sdev);
if (tpgs == TPGS_MODE_NONE)
@@ -623,7 +664,25 @@ static int alua_initialize(struct scsi_device *sdev, 
struct alua_dh_data *h)
if (err != SCSI_DH_OK)
goto out;
 
-   h->pg = alua_get_pg(sdev, h->group_id, tpgs);
+   device_id_len = scsi_vpd_lun_id(sdev, device_id_str,
+   sizeof(device_id_str));
+   if (device_id_len <= 0) {
+   /*
+* Internal error: TPGS supported but no device
+* identifcation found. Disable ALUA support.
+*/
+   sdev_printk(KERN_INFO, sdev,
+   "%s: No device descriptors found\n",
+   ALUA_DH_NAME);
+   goto out;
+   }
+   sdev_printk(KERN_INFO, sdev,
+   "%s: device %s port group %02x "
+   "rel port %02x\n", ALUA_DH_NAME,
+   device_id_str, h->group_id, h->rel_port);
+
+   h->pg = alua_get_pg(sdev, h->group_id, tpgs,
+   device_id_str, device_id_len);
if (!h->pg) {
err = SCSI_DH_NOMEM;
goto out;
-- 
1.8.5.6

--
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 27/36] scsi_dh_alua: Use workqueue for RTPG

2015-09-29 Thread Hannes Reinecke
The current ALUA device_handler has two drawbacks:
- We're sending a 'SET TARGET PORT GROUP' command to every LUN,
  disregarding the fact that several LUNs might be in a port group
  and will be automatically switched whenever _any_ LUN within
  that port group receives the command.
- Whenever a LUN is in 'transitioning' mode we cannot block I/O
  to that LUN, instead the controller has to abort the command.
  This leads to increased traffic across the wire and heavy load
  on the controller during switchover.

With this patch the RTPG handling is moved to a per-portgroup
workqueue. This reduces the number of 'REPORT TARGET PORT GROUP'
and 'SET TARGET PORT GROUPS' sent to the controller as we're sending
them now per port group, and not per device as previously.
It also allows us to block I/O to any LUN / port group found to be
in 'transitioning' ALUA mode, as the workqueue item will be requeued
until the controller moves out of transitioning.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 327 +++--
 1 file changed, 267 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4113b76..1b7153f 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -59,13 +59,23 @@
 #define ALUA_RTPG_SIZE 128
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
+#define ALUA_RTPG_DELAY_MSECS  5
 
 /* device handler flags */
-#define ALUA_OPTIMIZE_STPG 1
-#define ALUA_RTPG_EXT_HDR_UNSUPP   2
+#define ALUA_OPTIMIZE_STPG 0x01
+#define ALUA_RTPG_EXT_HDR_UNSUPP   0x02
+/* State machine flags */
+#define ALUA_PG_RUN_RTPG   0x10
+#define ALUA_PG_RUN_STPG   0x20
+#define ALUA_PG_RUNNING0x40
+
+static uint optimize_stpg;
+module_param(optimize_stpg, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(optimize_stpg, "Allow use of a non-optimized path, rather 
than sending a STPG, when implicit TPGS is supported (0=No,1=Yes). Default is 
0.");
 
 static LIST_HEAD(port_group_list);
 static DEFINE_SPINLOCK(port_group_lock);
+static struct workqueue_struct *kaluad_wq;
 
 struct alua_port_group {
struct kref kref;
@@ -78,12 +88,25 @@ struct alua_port_group {
int pref;
unsignedflags; /* used for optimizing STPG */
unsigned char   transition_tmo;
+   unsigned long   expiry;
+   unsigned long   interval;
+   struct delayed_work rtpg_work;
+   spinlock_t  lock;
+   struct list_headrtpg_list;
+   struct scsi_device  *rtpg_sdev;
 };
 
 struct alua_dh_data {
struct alua_port_group  *pg;
int rel_port;
+   spinlock_t  pg_lock;
struct scsi_device  *sdev;
+   int init_error;
+   struct mutexinit_mutex;
+};
+
+struct alua_queue_data {
+   struct list_headentry;
activate_complete   callback_fn;
void*callback_data;
 };
@@ -91,8 +114,10 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_CURRENT 0
 #define ALUA_POLICY_SWITCH_ALL 1
 
-static int alua_rtpg(struct scsi_device *, struct alua_port_group *);
-static char print_alua_state(int);
+static void alua_rtpg_work(struct work_struct *work);
+static void alua_rtpg_queue(struct alua_port_group *pg,
+   struct scsi_device *sdev,
+   struct alua_queue_data *qdata);
 
 static void release_port_group(struct kref *kref)
 {
@@ -103,6 +128,7 @@ static void release_port_group(struct kref *kref)
spin_lock(&port_group_lock);
list_del(&pg->node);
spin_unlock(&port_group_lock);
+   WARN_ON(pg->rtpg_sdev);
kfree(pg);
 }
 
@@ -168,7 +194,7 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
 struct alua_port_group *alua_lookup_pg(char *id_str, size_t id_size,
   int group_id)
 {
-   struct alua_port_group *pg = NULL;
+   struct alua_port_group *pg;
 
list_for_each_entry(pg, &port_group_list, node) {
if (pg->group_id != group_id)
@@ -218,18 +244,26 @@ struct alua_port_group *alua_get_pg(struct scsi_device 
*sdev,
pg->group_id = group_id;
pg->tpgs = tpgs;
pg->state = TPGS_STATE_OPTIMIZED;
+   if (optimize_stpg)
+   pg->flags |= ALUA_OPTIMIZE_STPG;
kref_init(&pg->kref);
+   INIT_DELAYED_WORK(&pg->rtpg_work, alua_rtpg_work);
+   INIT_LIST_HEAD(&pg->rtpg_list);
+   INIT_LIST_HEAD(&pg->node);
+   spin_lock_init(&pg->lock);
 
/* Re-check list again to catch concurrent updates */
spin_lock(&port_group_lock);
tmp_pg = alua_lookup_pg(id_str, id

[PATCH 25/36] scsi_dh_alua: simplify alua_initialize()

2015-09-29 Thread Hannes Reinecke
Rework alua_check_vpd() to use scsi_vpd_get_tpg()
and move the port group selection into the function, too.
With that we can simplify alua_initialize() to just
call alua_check_tpgs() and alua_check_vpd();

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 99 ++
 1 file changed, 34 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index e2e6177..1755591 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -82,7 +82,6 @@ struct alua_port_group {
 
 struct alua_dh_data {
struct alua_port_group  *pg;
-   int group_id;
int rel_port;
struct scsi_device  *sdev;
activate_complete   callback_fn;
@@ -92,6 +91,7 @@ struct alua_dh_data {
 #define ALUA_POLICY_SWITCH_CURRENT 0
 #define ALUA_POLICY_SWITCH_ALL 1
 
+static int alua_rtpg(struct scsi_device *, struct alua_port_group *, int);
 static char print_alua_state(int);
 
 static void release_port_group(struct kref *kref)
@@ -292,35 +292,18 @@ static int alua_check_tpgs(struct scsi_device *sdev)
  *
  * Extract the relative target port and the target port group
  * descriptor from the list of identificators.
+ *
+ * Returns 0 or SCSI_DH_ error code on failure.
  */
-static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h,
+ int tpgs)
 {
-   unsigned char *d;
-
-   if (!sdev->vpd_pg83)
-   return SCSI_DH_DEV_UNSUPP;
-
-   /*
-* Look for the correct descriptor.
-*/
-   d = sdev->vpd_pg83 + 4;
-   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
-   switch (d[1] & 0xf) {
-   case 0x4:
-   /* Relative target port */
-   h->rel_port = get_unaligned_be16(&d[6]);
-   break;
-   case 0x5:
-   /* Target port group */
-   h->group_id = get_unaligned_be16(&d[6]);
-   break;
-   default:
-   break;
-   }
-   d += d[3] + 4;
-   }
+   int rel_port = -1, group_id;
+   char id_str[256];
+   int id_size;
 
-   if (h->group_id == -1) {
+   group_id = scsi_vpd_tpg_id(sdev, &rel_port);
+   if (group_id < 0) {
/*
 * Internal error; TPGS supported but required
 * VPD identification descriptors not present.
@@ -331,11 +314,29 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
ALUA_DH_NAME);
return SCSI_DH_DEV_UNSUPP;
}
+   h->rel_port = rel_port;
+
+   id_size = scsi_vpd_lun_id(sdev, id_str, 256);
+   if (id_size <= 0) {
+   /*
+* Internal error: TPGS supported but no device
+* identifcation found. Disable ALUA support.
+*/
+   sdev_printk(KERN_INFO, sdev,
+   "%s: No device descriptors found\n",
+   ALUA_DH_NAME);
+   return SCSI_DH_DEV_UNSUPP;
+   }
sdev_printk(KERN_INFO, sdev,
-   "%s: port group %02x rel port %02x\n",
-   ALUA_DH_NAME, h->group_id, h->rel_port);
+   "%s: device %s port group %02x "
+   "rel port %02x\n", ALUA_DH_NAME,
+   id_str, group_id, h->rel_port);
 
-   return 0;
+   h->pg = alua_get_pg(sdev, group_id, tpgs, id_str, id_size);
+   if (!h->pg)
+   return SCSI_DH_NOMEM;
+
+   return alua_rtpg(sdev, h->pg, 0);
 }
 
 static char print_alua_state(int state)
@@ -653,46 +654,14 @@ static unsigned alua_stpg(struct scsi_device *sdev, 
struct alua_port_group *pg)
 static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
 {
int err = SCSI_DH_DEV_UNSUPP, tpgs;
-   char device_id_str[256];
-   int device_id_len;
 
tpgs = alua_check_tpgs(sdev);
-   if (tpgs == TPGS_MODE_NONE)
-   goto out;
-
-   err = alua_check_vpd(sdev, h);
-   if (err != SCSI_DH_OK)
-   goto out;
+   if (tpgs != TPGS_MODE_NONE)
+   err = alua_check_vpd(sdev, h, tpgs);
 
-   device_id_len = scsi_vpd_lun_id(sdev, device_id_str,
-   sizeof(device_id_str));
-   if (device_id_len <= 0) {
-   /*
-* Internal error: TPGS supported but no device
-* identifcation found. Disable ALUA support.
-*/
-   sdev_printk(KERN_INFO, sdev,
-   "%s: No device descriptors found\n",
-   ALUA_DH_NAME);
-

[PATCH 16/36] scsi_dh_alua: call alua_rtpg() if stpg fails

2015-09-29 Thread Hannes Reinecke
If the call to SET TARGET PORT GROUPS fails we have no idea what
state the array is left in, so we need to issue a call to
REPORT TARGET PORT GROUPS in these cases.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7c3789b..b645593 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -717,6 +717,8 @@ static int alua_activate(struct scsi_device *sdev,
h->flags |= ALUA_OPTIMIZE_STPG;
 
err = alua_stpg(sdev, h);
+   if (err == SCSI_DH_RETRY)
+   err = alua_rtpg(sdev, h, 1);
 out:
if (fn)
fn(data, err);
-- 
1.8.5.6

--
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 07/36] scsi_dh_alua: use standard logging functions

2015-09-29 Thread Hannes Reinecke
Use standard logging functions instead of hand-crafted ones.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 27 +--
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 5334bba..018faf0 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -194,19 +195,14 @@ static void stpg_endio(struct request *req, int error)
 
if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
 &sense_hdr)) {
-   if (!err) {
-   err = SCSI_DH_IO;
-   goto done;
-   }
err = alua_check_sense(h->sdev, &sense_hdr);
if (err == ADD_TO_MLQUEUE) {
err = SCSI_DH_RETRY;
goto done;
}
-   sdev_printk(KERN_INFO, h->sdev,
-   "%s: stpg sense code: %02x/%02x/%02x\n",
-   ALUA_DH_NAME, sense_hdr.sense_key,
-   sense_hdr.asc, sense_hdr.ascq);
+   sdev_printk(KERN_INFO, h->sdev, "%s: stpg failed\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(h->sdev, ALUA_DH_NAME, &sense_hdr);
err = SCSI_DH_IO;
} else if (error)
err = SCSI_DH_IO;
@@ -526,13 +522,16 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
}
 
err = alua_check_sense(sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
+   if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry)) {
+   sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
goto retry;
-   sdev_printk(KERN_INFO, sdev,
-   "%s: rtpg sense code %02x/%02x/%02x\n",
-   ALUA_DH_NAME, sense_hdr.sense_key,
-   sense_hdr.asc, sense_hdr.ascq);
-   err = SCSI_DH_IO;
+   }
+   sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n",
+   ALUA_DH_NAME);
+   scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
+   return SCSI_DH_IO;
}
if (err != SCSI_DH_OK)
return err;
-- 
1.8.5.6

--
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 14/36] scsi_dh_alua: separate out alua_stpg()

2015-09-29 Thread Hannes Reinecke
Seperate out SET TARGET PORT GROUP functionality into a separate
function alua_stpg().

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 86 ++
 1 file changed, 52 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 63423b2..59fe3e9 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -614,6 +614,56 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 }
 
 /*
+ * alua_stpg - Issue a SET TARGET GROUP STATES command
+ *
+ * Issue a SET TARGET GROUP STATES command and evaluate the
+ * response. Returns SCSI_DH_RETRY per default to trigger
+ * a re-evaluation of the target group state.
+ */
+static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h,
+ activate_complete fn, void *data)
+{
+   int err = SCSI_DH_OK;
+   int stpg = 0;
+
+   if (!(h->tpgs & TPGS_MODE_EXPLICIT)) {
+   /* Only implicit ALUA supported */
+   return err;
+   }
+
+   switch (h->state) {
+   case TPGS_STATE_NONOPTIMIZED:
+   stpg = 1;
+   if ((h->flags & ALUA_OPTIMIZE_STPG) &&
+   !h->pref &&
+   (h->tpgs & TPGS_MODE_IMPLICIT))
+   stpg = 0;
+   break;
+   case TPGS_STATE_STANDBY:
+   case TPGS_STATE_UNAVAILABLE:
+   stpg = 1;
+   break;
+   case TPGS_STATE_OFFLINE:
+   err = SCSI_DH_IO;
+   break;
+   case TPGS_STATE_TRANSITIONING:
+   err = SCSI_DH_RETRY;
+   break;
+   default:
+   break;
+   }
+
+   if (stpg) {
+   h->callback_fn = fn;
+   h->callback_data = data;
+   err = submit_stpg(h);
+   if (err != SCSI_DH_OK)
+   h->callback_fn = h->callback_data = NULL;
+   }
+   return err;
+}
+
+/*
  * alua_initialize - Initialize ALUA state
  * @sdev: the device to be initialized
  *
@@ -690,7 +740,6 @@ static int alua_activate(struct scsi_device *sdev,
 {
struct alua_dh_data *h = sdev->handler_data;
int err = SCSI_DH_OK;
-   int stpg = 0;
 
err = alua_rtpg(sdev, h, 1);
if (err != SCSI_DH_OK)
@@ -699,41 +748,10 @@ static int alua_activate(struct scsi_device *sdev,
if (optimize_stpg)
h->flags |= ALUA_OPTIMIZE_STPG;
 
-   if (h->tpgs & TPGS_MODE_EXPLICIT) {
-   switch (h->state) {
-   case TPGS_STATE_NONOPTIMIZED:
-   stpg = 1;
-   if ((h->flags & ALUA_OPTIMIZE_STPG) &&
-   (!h->pref) &&
-   (h->tpgs & TPGS_MODE_IMPLICIT))
-   stpg = 0;
-   break;
-   case TPGS_STATE_STANDBY:
-   case TPGS_STATE_UNAVAILABLE:
-   stpg = 1;
-   break;
-   case TPGS_STATE_OFFLINE:
-   err = SCSI_DH_IO;
-   break;
-   case TPGS_STATE_TRANSITIONING:
-   err = SCSI_DH_RETRY;
-   break;
-   default:
-   break;
-   }
-   }
-
-   if (stpg) {
-   h->callback_fn = fn;
-   h->callback_data = data;
-   err = submit_stpg(h);
-   if (err == SCSI_DH_OK)
-   return 0;
-   h->callback_fn = h->callback_data = NULL;
-   }
+   err = alua_stpg(sdev, h, fn, data);
 
 out:
-   if (fn)
+   if (err != SCSI_DH_OK && fn)
fn(data, err);
return 0;
 }
-- 
1.8.5.6

--
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 19/36] scsi_dh_alua: Use separate alua_port_group structure

2015-09-29 Thread Hannes Reinecke
The port group needs to be a separate structure as several
LUNs might belong to the same group.

Reviewed-by: Ewan Milne 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 227 +++--
 include/scsi/scsi_dh.h |   1 +
 2 files changed, 155 insertions(+), 73 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index c6fcfa5..f3b455f 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -64,9 +64,13 @@
 #define ALUA_OPTIMIZE_STPG 1
 #define ALUA_RTPG_EXT_HDR_UNSUPP   2
 
-struct alua_dh_data {
+static LIST_HEAD(port_group_list);
+static DEFINE_SPINLOCK(port_group_lock);
+
+struct alua_port_group {
+   struct kref kref;
+   struct list_headnode;
int group_id;
-   int rel_port;
int tpgs;
int state;
int pref;
@@ -75,6 +79,12 @@ struct alua_dh_data {
unsigned char   *buff;
int bufflen;
unsigned char   transition_tmo;
+};
+
+struct alua_dh_data {
+   struct alua_port_group  *pg;
+   int group_id;
+   int rel_port;
struct scsi_device  *sdev;
activate_complete   callback_fn;
void*callback_data;
@@ -86,21 +96,35 @@ struct alua_dh_data {
 static char print_alua_state(int);
 static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
-static int realloc_buffer(struct alua_dh_data *h, unsigned len)
+static int realloc_buffer(struct alua_port_group *pg, unsigned len)
 {
-   if (h->buff && h->buff != h->inq)
-   kfree(h->buff);
+   if (pg->buff && pg->buff != pg->inq)
+   kfree(pg->buff);
 
-   h->buff = kmalloc(len, GFP_NOIO);
-   if (!h->buff) {
-   h->buff = h->inq;
-   h->bufflen = ALUA_INQUIRY_SIZE;
+   pg->buff = kmalloc(len, GFP_NOIO);
+   if (!pg->buff) {
+   pg->buff = pg->inq;
+   pg->bufflen = ALUA_INQUIRY_SIZE;
return 1;
}
-   h->bufflen = len;
+   pg->bufflen = len;
return 0;
 }
 
+static void release_port_group(struct kref *kref)
+{
+   struct alua_port_group *pg;
+
+   pg = container_of(kref, struct alua_port_group, kref);
+   printk(KERN_WARNING "alua: release port group %d\n", pg->group_id);
+   spin_lock(&port_group_lock);
+   list_del(&pg->node);
+   spin_unlock(&port_group_lock);
+   if (pg->buff && pg->inq != pg->buff)
+   kfree(pg->buff);
+   kfree(pg);
+}
+
 /*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
@@ -161,6 +185,40 @@ static int submit_stpg(struct scsi_device *sdev, int 
group_id,
 }
 
 /*
+ * alua_get_pg - Allocate a new port_group structure
+ * @sdev: scsi device
+ * @h: alua device_handler data
+ * @group_id: port group id
+ *
+ * Allocate a new port_group structure for a given
+ * device.
+ */
+struct alua_port_group *alua_get_pg(struct scsi_device *sdev,
+   int group_id, int tpgs)
+{
+   struct alua_port_group *pg = NULL;
+
+   pg = kzalloc(sizeof(struct alua_port_group), GFP_KERNEL);
+   if (!pg) {
+   sdev_printk(KERN_WARNING, sdev,
+   "%s: kzalloc port group failed\n",
+   ALUA_DH_NAME);
+   return NULL;
+   }
+   pg->group_id = group_id;
+   pg->buff = pg->inq;
+   pg->bufflen = ALUA_INQUIRY_SIZE;
+   pg->tpgs = tpgs;
+   pg->state = TPGS_STATE_OPTIMIZED;
+   kref_init(&pg->kref);
+   spin_lock(&port_group_lock);
+   list_add(&pg->node, &port_group_list);
+   spin_unlock(&port_group_lock);
+
+   return pg;
+}
+
+/*
  * alua_check_tpgs - Evaluate TPGS setting
  * @sdev: device to be checked
  *
@@ -255,8 +313,6 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h)
sdev_printk(KERN_INFO, sdev,
"%s: No target port descriptors found\n",
ALUA_DH_NAME);
-   h->state = TPGS_STATE_OPTIMIZED;
-   h->tpgs = TPGS_MODE_NONE;
return SCSI_DH_DEV_UNSUPP;
}
sdev_printk(KERN_INFO, sdev,
@@ -374,7 +430,7 @@ static int alua_check_sense(struct scsi_device *sdev,
  * Returns SCSI_DH_DEV_OFFLINED if the path is
  * found to be unusable.
  */
-static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h, int 
wait_for_transition)
+static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg, int 
wait_for_transition)
 {
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_stat

[PATCH 15/36] scsi_dh_alua: Make stpg synchronous

2015-09-29 Thread Hannes Reinecke
The 'activate_complete' function needs to be executed after
stpg has finished, so we can as well execute stpg synchronously
and call the function directly.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 133 +++--
 1 file changed, 50 insertions(+), 83 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 59fe3e9..7c3789b 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -170,76 +170,28 @@ done:
 }
 
 /*
- * stpg_endio - Evaluate SET TARGET GROUP STATES
- * @sdev: the device to be evaluated
- * @state: the new target group state
- *
- * Evaluate a SET TARGET GROUP STATES command response.
- */
-static void stpg_endio(struct request *req, int error)
-{
-   struct alua_dh_data *h = req->end_io_data;
-   struct scsi_sense_hdr sense_hdr;
-   unsigned err = SCSI_DH_OK;
-
-   if (host_byte(req->errors) != DID_OK ||
-   msg_byte(req->errors) != COMMAND_COMPLETE) {
-   err = SCSI_DH_IO;
-   goto done;
-   }
-
-   if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-&sense_hdr)) {
-   err = alua_check_sense(h->sdev, &sense_hdr);
-   if (err == ADD_TO_MLQUEUE) {
-   err = SCSI_DH_RETRY;
-   goto done;
-   }
-   sdev_printk(KERN_INFO, h->sdev, "%s: stpg failed\n",
-   ALUA_DH_NAME);
-   scsi_print_sense_hdr(h->sdev, ALUA_DH_NAME, &sense_hdr);
-   err = SCSI_DH_IO;
-   } else if (error)
-   err = SCSI_DH_IO;
-
-   if (err == SCSI_DH_OK) {
-   h->state = TPGS_STATE_OPTIMIZED;
-   sdev_printk(KERN_INFO, h->sdev,
-   "%s: port group %02x switched to state %c\n",
-   ALUA_DH_NAME, h->group_id,
-   print_alua_state(h->state));
-   }
-done:
-   req->end_io_data = NULL;
-   __blk_put_request(req->q, req);
-   if (h->callback_fn) {
-   h->callback_fn(h->callback_data, err);
-   h->callback_fn = h->callback_data = NULL;
-   }
-   return;
-}
-
-/*
  * submit_stpg - Issue a SET TARGET GROUP STATES command
  *
  * Currently we're only setting the current target port group state
  * to 'active/optimized' and let the array firmware figure out
  * the states of the remaining groups.
  */
-static unsigned submit_stpg(struct alua_dh_data *h)
+static unsigned submit_stpg(struct scsi_device *sdev, int group_id,
+   unsigned char *sense)
 {
struct request *rq;
+   unsigned char stpg_data[8];
int stpg_len = 8;
-   struct scsi_device *sdev = h->sdev;
+   int err = 0;
 
/* Prepare the data buffer */
-   memset(h->buff, 0, stpg_len);
-   h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
-   put_unaligned_be16(h->group_id, &h->buff[6]);
+   memset(stpg_data, 0, stpg_len);
+   stpg_data[4] = TPGS_STATE_OPTIMIZED & 0x0f;
+   put_unaligned_be16(group_id, &stpg_data[6]);
 
-   rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
+   rq = get_alua_req(sdev, stpg_data, stpg_len, WRITE);
if (!rq)
-   return SCSI_DH_RES_TEMP_UNAVAIL;
+   return DRIVER_BUSY << 24;
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_OUT;
@@ -247,13 +199,17 @@ static unsigned submit_stpg(struct alua_dh_data *h)
put_unaligned_be32(stpg_len, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
 
-   rq->sense = h->sense;
+   rq->sense = sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
-   rq->end_io_data = h;
 
-   blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
-   return SCSI_DH_OK;
+   blk_execute_rq(rq->q, NULL, rq, 1);
+   if (rq->errors)
+   err = rq->errors;
+
+   blk_put_request(rq);
+
+   return err;
 }
 
 /*
@@ -620,47 +576,59 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
  * response. Returns SCSI_DH_RETRY per default to trigger
  * a re-evaluation of the target group state.
  */
-static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h,
- activate_complete fn, void *data)
+static unsigned alua_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
 {
-   int err = SCSI_DH_OK;
-   int stpg = 0;
+   int retval;
+   struct scsi_sense_hdr sense_hdr;
 
if (!(h->tpgs & TPGS_MODE_EXPLICIT)) {
-   /* Only implicit ALUA supported */
-   return err;
+   /* Only implicit ALUA supported, retry */
+   return SCSI_DH_RETRY;
}
-
switch (h->state) {
+   case TPGS_STATE_OPTIMIZED:
+   r

[PATCH 17/36] scsi_dh_alua: switch to scsi_execute_req_flags()

2015-09-29 Thread Hannes Reinecke
All commands are issued synchronously, so no need to open-code
scsi_execute_req_flags() anymore. And we can get rid of the
static sense code structure element. scsi_execute_req_flags()
will be setting REQ_QUIET and REQ_PREEMPT, but that is
perfectly fine as we're evaluating and logging any errors
ourselves and we really need to send the command even if
the device is quiesced.

Reviewed-by: Christoph Hellwig 
Reviewed-by: Ewan Milne 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 125 +
 1 file changed, 36 insertions(+), 89 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index b645593..b72cea6 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -75,7 +75,6 @@ struct alua_dh_data {
unsigned char   *buff;
int bufflen;
unsigned char   transition_tmo;
-   unsigned char   sense[SCSI_SENSE_BUFFERSIZE];
struct scsi_device  *sdev;
activate_complete   callback_fn;
void*callback_data;
@@ -102,71 +101,30 @@ static int realloc_buffer(struct alua_dh_data *h, 
unsigned len)
return 0;
 }
 
-static struct request *get_alua_req(struct scsi_device *sdev,
-   void *buffer, unsigned buflen, int rw)
-{
-   struct request *rq;
-   struct request_queue *q = sdev->request_queue;
-
-   rq = blk_get_request(q, rw, GFP_NOIO);
-
-   if (IS_ERR(rq)) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: blk_get_request failed\n", __func__);
-   return NULL;
-   }
-   blk_rq_set_block_pc(rq);
-
-   if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
-   blk_put_request(rq);
-   sdev_printk(KERN_INFO, sdev,
-   "%s: blk_rq_map_kern failed\n", __func__);
-   return NULL;
-   }
-
-   rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
-REQ_FAILFAST_DRIVER;
-   rq->retries = ALUA_FAILOVER_RETRIES;
-   rq->timeout = ALUA_FAILOVER_TIMEOUT * HZ;
-
-   return rq;
-}
-
 /*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
-   int bufflen, unsigned char *sense, int flags)
+static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+  int bufflen, struct scsi_sense_hdr *sshdr, int flags)
 {
-   struct request *rq;
-   int err = 0;
-
-   rq = get_alua_req(sdev, buff, bufflen, READ);
-   if (!rq) {
-   err = DRIVER_BUSY << 24;
-   goto done;
-   }
+   u8 cdb[COMMAND_SIZE(MAINTENANCE_IN)];
+   int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+   REQ_FAILFAST_DRIVER;
 
/* Prepare the command. */
-   rq->cmd[0] = MAINTENANCE_IN;
+   memset(cdb, 0x0, COMMAND_SIZE(MAINTENANCE_IN));
+   cdb[0] = MAINTENANCE_IN;
if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP))
-   rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
+   cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
-   rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   put_unaligned_be32(bufflen, &rq->cmd[6]);
-   rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
-
-   rq->sense = sense;
-   memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = 0;
-
-   blk_execute_rq(rq->q, NULL, rq, 1);
-   if (rq->errors)
-   err = rq->errors;
-   blk_put_request(rq);
-done:
-   return err;
+   cdb[1] = MI_REPORT_TARGET_PGS;
+   put_unaligned_be32(bufflen, &cdb[6]);
+
+   return scsi_execute_req_flags(sdev, cdb, DMA_FROM_DEVICE,
+ buff, bufflen, sshdr,
+ ALUA_FAILOVER_TIMEOUT * HZ,
+ ALUA_FAILOVER_RETRIES, NULL, req_flags);
 }
 
 /*
@@ -176,40 +134,30 @@ done:
  * to 'active/optimized' and let the array firmware figure out
  * the states of the remaining groups.
  */
-static unsigned submit_stpg(struct scsi_device *sdev, int group_id,
-   unsigned char *sense)
+static int submit_stpg(struct scsi_device *sdev, int group_id,
+  struct scsi_sense_hdr *sshdr)
 {
-   struct request *rq;
+   u8 cdb[COMMAND_SIZE(MAINTENANCE_OUT)];
unsigned char stpg_data[8];
int stpg_len = 8;
-   int err = 0;
+   int req_flags = REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
+   REQ_FAILFAST_DRIVER;
 
/* Prepare the data buffer */
memset(stpg_data, 0, stpg_len);
stpg_data[4] = TPGS_STATE_OPTIMIZE

[PATCH 01/36] scsi_dh: move 'dh_state' sysfs attribute to generic code

2015-09-29 Thread Hannes Reinecke
As scsi_dh.c is now always compiled in we should be moving
the 'dh_state' attribute to the generic code.

Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_dh.c| 68 +--
 drivers/scsi/scsi_sysfs.c | 58 
 2 files changed, 59 insertions(+), 67 deletions(-)

diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index edb044a..1584080 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -153,76 +153,11 @@ static void scsi_dh_handler_detach(struct scsi_device 
*sdev)
module_put(sdev->handler->module);
 }
 
-/*
- * Functions for sysfs attribute 'dh_state'
- */
-static ssize_t
-store_dh_state(struct device *dev, struct device_attribute *attr,
-  const char *buf, size_t count)
-{
-   struct scsi_device *sdev = to_scsi_device(dev);
-   struct scsi_device_handler *scsi_dh;
-   int err = -EINVAL;
-
-   if (sdev->sdev_state == SDEV_CANCEL ||
-   sdev->sdev_state == SDEV_DEL)
-   return -ENODEV;
-
-   if (!sdev->handler) {
-   /*
-* Attach to a device handler
-*/
-   scsi_dh = scsi_dh_lookup(buf);
-   if (!scsi_dh)
-   return err;
-   err = scsi_dh_handler_attach(sdev, scsi_dh);
-   } else {
-   if (!strncmp(buf, "detach", 6)) {
-   /*
-* Detach from a device handler
-*/
-   sdev_printk(KERN_WARNING, sdev,
-   "can't detach handler %s.\n",
-   sdev->handler->name);
-   err = -EINVAL;
-   } else if (!strncmp(buf, "activate", 8)) {
-   /*
-* Activate a device handler
-*/
-   if (sdev->handler->activate)
-   err = sdev->handler->activate(sdev, NULL, NULL);
-   else
-   err = 0;
-   }
-   }
-
-   return err<0?err:count;
-}
-
-static ssize_t
-show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
-{
-   struct scsi_device *sdev = to_scsi_device(dev);
-
-   if (!sdev->handler)
-   return snprintf(buf, 20, "detached\n");
-
-   return snprintf(buf, 20, "%s\n", sdev->handler->name);
-}
-
-static struct device_attribute scsi_dh_state_attr =
-   __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
-  store_dh_state);
-
 int scsi_dh_add_device(struct scsi_device *sdev)
 {
struct scsi_device_handler *devinfo = NULL;
const char *drv;
-   int err;
-
-   err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
-   if (err)
-   return err;
+   int err = 0;
 
drv = scsi_dh_find_driver(sdev);
if (drv)
@@ -236,7 +171,6 @@ void scsi_dh_remove_device(struct scsi_device *sdev)
 {
if (sdev->handler)
scsi_dh_handler_detach(sdev);
-   device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
 }
 
 /*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index b89..5d64c3f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -875,6 +876,60 @@ sdev_show_function(queue_depth, "%d\n");
 static DEVICE_ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
   sdev_store_queue_depth);
 
+#ifdef CONFIG_SCSI_DH
+static ssize_t
+sdev_show_dh_state(struct device *dev, struct device_attribute *attr,
+  char *buf)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+
+   if (!sdev->handler)
+   return snprintf(buf, 20, "detached\n");
+
+   return snprintf(buf, 20, "%s\n", sdev->handler->name);
+}
+
+static ssize_t
+sdev_store_dh_state(struct device *dev, struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+   int err = -EINVAL;
+
+   if (sdev->sdev_state == SDEV_CANCEL ||
+   sdev->sdev_state == SDEV_DEL)
+   return -ENODEV;
+
+   if (!sdev->handler) {
+   /*
+* Attach to a device handler
+*/
+   err = scsi_dh_attach(sdev->request_queue, buf);
+   } else if (!strncmp(buf, "activate", 8)) {
+   /*
+* Activate a device handler
+*/
+   if (sdev->handler->activate)
+   err = sdev->handler->activate(sdev, NULL, NULL);
+   else
+   err = 0;
+   } else if (!strncmp(buf, "detach", 6)) {
+   /*
+* Detach from a device handler
+  

[PATCH 22/36] scsi: Add scsi_vpd_lun_id()

2015-09-29 Thread Hannes Reinecke
Add a function scsi_vpd_lun_id() to return a unique device
identifcation based on the designation descriptors of
VPD page 0x83.

As devices might implement several descriptors the order
of preference is:
- NAA IEE Registered Extended
- EUI-64 based 16-byte
- EUI-64 based 12-byte
- NAA IEEE Registered
- NAA IEEE Extended
A SCSI name string descriptor is preferred to all of them
if the identification is longer than 16 bytes.

The returned unique device identification will be formatted
as a SCSI Name string to avoid clashes between different
designator types.

Reviewed-by: Ewan Milne 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_lib.c| 132 +
 include/scsi/scsi_device.h |   1 +
 2 files changed, 133 insertions(+)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index cbfc599..de3dcef 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3154,3 +3154,135 @@ void sdev_enable_disk_events(struct scsi_device *sdev)
atomic_dec(&sdev->disk_events_disable_depth);
 }
 EXPORT_SYMBOL(sdev_enable_disk_events);
+
+/*
+ * scsi_vpd_lun_id - return a unique device identification
+ * @sdev: SCSI device
+ * @id:   buffer for the identification
+ * @id_len:  length of the buffer
+ *
+ * Copies a unique device identification into @id based
+ * on the information in the VPD page 0x83 of the device.
+ * The string will be formatted as a SCSI name string.
+ *
+ * Returns the length of the identification or error on failure.
+ * If the identifier is longer than the supplied buffer the actual
+ * identifier length is returned and the buffer is not zero-padded.
+ */
+int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
+{
+   u8 cur_id_type = 0xff;
+   u8 cur_id_size = 0;
+   unsigned char *d, *cur_id_str;
+   int id_size = -EAGAIN;
+
+   if (!sdev->vpd_pg83)
+   return -ENXIO;
+
+   /*
+* Look for the correct descriptor.
+* Order of preference for lun descriptor:
+* - SCSI name string
+* - NAA IEEE Registered Extended
+* - EUI-64 based 16-byte
+* - EUI-64 based 12-byte
+* - NAA IEEE Registered
+* - NAA IEEE Extended
+* as longer descriptors reduce the likelyhood
+* of identification clashes.
+*/
+
+   /* The id string must be at least 20 bytes + terminating NULL byte */
+   if (id_len < 21)
+   return -EINVAL;
+
+   memset(id, 0, id_len);
+   d = sdev->vpd_pg83 + 4;
+   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+   /* Skip designators not referring to the LUN */
+   if ((d[1] & 0x30) != 0x00)
+   goto next_desig;
+
+   switch (d[1] & 0xf) {
+   case 0x2:
+   /* EUI-64 */
+   if (cur_id_size > d[3])
+   break;
+   /* Prefer NAA IEEE Registered Extended */
+   if (cur_id_type == 0x3 &&
+   cur_id_size == d[3])
+   break;
+   cur_id_size = d[3];
+   cur_id_str = d + 4;
+   cur_id_type = d[1] & 0xf;
+   switch (cur_id_size) {
+   case 8:
+   id_size = snprintf(id, id_len,
+  "eui.%8phN",
+  cur_id_str);
+   break;
+   case 12:
+   id_size = snprintf(id, id_len,
+  "eui.%12phN",
+  cur_id_str);
+   break;
+   case 16:
+   id_size = snprintf(id, id_len,
+  "eui.%16phN",
+  cur_id_str);
+   break;
+   default:
+   cur_id_size = 0;
+   break;
+   }
+   break;
+   case 0x3:
+   /* NAA */
+   if (cur_id_size > d[3])
+   break;
+   cur_id_size = d[3];
+   cur_id_str = d + 4;
+   cur_id_type = d[1] & 0xf;
+   switch (cur_id_size) {
+   case 8:
+   id_size = snprintf(id, id_len,
+  "naa.%8phN",
+  cur_id_str);
+   break;
+   case 16:
+   id_size =

[PATCH 05/36] scsi_dh_alua: improved logging

2015-09-29 Thread Hannes Reinecke
Issue different logging messages if ALUA is not supported
or the TPGS setting is invalid.

Reviewed-by: Martin K. Petersen 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index f15b977..a20c8bf 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -310,12 +310,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
ALUA_DH_NAME);
break;
-   default:
-   h->tpgs = TPGS_MODE_NONE;
+   case TPGS_MODE_NONE:
sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
ALUA_DH_NAME);
err = SCSI_DH_DEV_UNSUPP;
break;
+   default:
+   sdev_printk(KERN_INFO, sdev,
+   "%s: unsupported TPGS setting %d\n",
+   ALUA_DH_NAME, h->tpgs);
+   h->tpgs = TPGS_MODE_NONE;
+   err = SCSI_DH_DEV_UNSUPP;
+   break;
}
 
return err;
-- 
1.8.5.6

--
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/36] scsi_dh_alua: sanitze sense code handling

2015-09-29 Thread Hannes Reinecke
The only check for a valid sense code is calling scsi_normalize_sense()
and check the return value. So drop the pointless checks and rely on
scsi_normalize_sense() to figure out if the sense code is valid.
With that we can also remove the 'senselen' field.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index a20c8bf..5334bba 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -73,7 +73,6 @@ struct alua_dh_data {
int bufflen;
unsigned char   transition_tmo;
unsigned char   sense[SCSI_SENSE_BUFFERSIZE];
-   int senselen;
struct scsi_device  *sdev;
activate_complete   callback_fn;
void*callback_data;
@@ -158,14 +157,13 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
 
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
+   rq->sense_len = 0;
 
err = blk_execute_rq(rq->q, NULL, rq, 1);
if (err == -EIO) {
sdev_printk(KERN_INFO, sdev,
"%s: rtpg failed with %x\n",
ALUA_DH_NAME, rq->errors);
-   h->senselen = rq->sense_len;
err = SCSI_DH_IO;
}
blk_put_request(rq);
@@ -194,9 +192,8 @@ static void stpg_endio(struct request *req, int error)
goto done;
}
 
-   if (req->sense_len > 0) {
-   err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-  &sense_hdr);
+   if (scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+&sense_hdr)) {
if (!err) {
err = SCSI_DH_IO;
goto done;
@@ -265,7 +262,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
 
rq->sense = h->sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
+   rq->sense_len = 0;
rq->end_io_data = h;
 
blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
@@ -508,10 +505,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
  retry:
err = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
 
-   if (err == SCSI_DH_IO && h->senselen > 0) {
-   err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
-  &sense_hdr);
-   if (!err)
+   if (err == SCSI_DH_IO) {
+   if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
+ &sense_hdr))
return SCSI_DH_IO;
 
/*
-- 
1.8.5.6

--
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 11/36] scsi_dh_alua: use flag for RTPG extended header

2015-09-29 Thread Hannes Reinecke
We should be using a flag when RTPG extended header is not
supported, that saves us sending RTPG twice for older arrays.

Reviewed-by: Bart Van Assche 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4ff9b90..a963f51 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -59,8 +59,9 @@
 #define ALUA_FAILOVER_TIMEOUT  60
 #define ALUA_FAILOVER_RETRIES  5
 
-/* flags passed from user level */
+/* device handler flags */
 #define ALUA_OPTIMIZE_STPG 1
+#define ALUA_RTPG_EXT_HDR_UNSUPP   2
 
 struct alua_dh_data {
int group_id;
@@ -134,8 +135,7 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h,
-   bool rtpg_ext_hdr_req)
+static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
 {
struct request *rq;
int err = 0;
@@ -148,7 +148,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
-   if (rtpg_ext_hdr_req)
+   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP))
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
@@ -484,7 +484,6 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
int len, k, off, valid_states = 0;
unsigned char *ucp;
unsigned err, retval;
-   bool rtpg_ext_hdr_req = 1;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
unsigned char orig_transition_tmo;
@@ -495,7 +494,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
+   retval = submit_rtpg(sdev, h);
if (retval) {
if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
  &sense_hdr)) {
@@ -515,10 +514,10 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 * The retry without rtpg_ext_hdr_req set
 * handles this.
 */
-   if (rtpg_ext_hdr_req == 1 &&
+   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP) &&
sense_hdr.sense_key == ILLEGAL_REQUEST &&
sense_hdr.asc == 0x24 && sense_hdr.ascq == 0) {
-   rtpg_ext_hdr_req = 0;
+   h->flags |= ALUA_RTPG_EXT_HDR_UNSUPP;
goto retry;
}
 
-- 
1.8.5.6

--
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 08/36] scsi_dh_alua: return standard SCSI return codes in submit_rtpg

2015-09-29 Thread Hannes Reinecke
Fixup submit_rtpg() to always return a standard SCSI return code.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 33 +++---
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 018faf0..d4e5691 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -138,11 +138,13 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
bool rtpg_ext_hdr_req)
 {
struct request *rq;
-   int err = SCSI_DH_RES_TEMP_UNAVAIL;
+   int err = 0;
 
rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
-   if (!rq)
+   if (!rq) {
+   err = DRIVER_BUSY << 24;
goto done;
+   }
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
@@ -160,13 +162,9 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h,
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
 
-   err = blk_execute_rq(rq->q, NULL, rq, 1);
-   if (err == -EIO) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: rtpg failed with %x\n",
-   ALUA_DH_NAME, rq->errors);
-   err = SCSI_DH_IO;
-   }
+   blk_execute_rq(rq->q, NULL, rq, 1);
+   if (rq->errors)
+   err = rq->errors;
blk_put_request(rq);
 done:
return err;
@@ -487,7 +485,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
struct scsi_sense_hdr sense_hdr;
int len, k, off, valid_states = 0;
unsigned char *ucp;
-   unsigned err;
+   unsigned err, retval;
bool rtpg_ext_hdr_req = 1;
unsigned long expiry, interval = 0;
unsigned int tpg_desc_tbl_off;
@@ -499,12 +497,17 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   err = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
-
-   if (err == SCSI_DH_IO) {
+   retval = submit_rtpg(sdev, h, rtpg_ext_hdr_req);
+   if (retval) {
if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
- &sense_hdr))
+ &sense_hdr)) {
+   sdev_printk(KERN_INFO, sdev,
+   "%s: rtpg failed, result %d\n",
+   ALUA_DH_NAME, retval);
+   if (driver_byte(retval) == DRIVER_BUSY)
+   return SCSI_DH_DEV_TEMP_BUSY;
return SCSI_DH_IO;
+   }
 
/*
 * submit_rtpg() has failed on existing arrays
@@ -533,8 +536,6 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr);
return SCSI_DH_IO;
}
-   if (err != SCSI_DH_OK)
-   return err;
 
len = (h->buff[0] << 24) + (h->buff[1] << 16) +
(h->buff[2] << 8) + h->buff[3] + 4;
-- 
1.8.5.6

--
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 10/36] scsi: remove scsi_show_sense_hdr()

2015-09-29 Thread Hannes Reinecke
Last caller is gone, so remove it.

Reviewed-by: Bart Van Assche 
Reviewed-by: Reviewed-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
Signed-off-by: Hannes Reinecke 
---
 include/scsi/scsi_dbg.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index f8170e9..56710e0 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -12,8 +12,6 @@ extern size_t __scsi_format_command(char *, size_t,
   const unsigned char *, size_t);
 extern void scsi_show_extd_sense(const struct scsi_device *, const char *,
 unsigned char, unsigned char);
-extern void scsi_show_sense_hdr(const struct scsi_device *, const char *,
-   const struct scsi_sense_hdr *);
 extern void scsi_print_sense_hdr(const struct scsi_device *, const char *,
 const struct scsi_sense_hdr *);
 extern void scsi_print_sense(const struct scsi_cmnd *);
-- 
1.8.5.6

--
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 13/36] scsi_dh_alua: Pass buffer as function argument

2015-09-29 Thread Hannes Reinecke
Pass in the buffer as a function argument for submit_rtpg().

Reviewed-by: Martin K. Petersen 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 8571e57..63423b2 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -136,12 +136,13 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
-static unsigned submit_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
+static unsigned submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+   int bufflen, unsigned char *sense, int flags)
 {
struct request *rq;
int err = 0;
 
-   rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
+   rq = get_alua_req(sdev, buff, bufflen, READ);
if (!rq) {
err = DRIVER_BUSY << 24;
goto done;
@@ -149,14 +150,14 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h)
 
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_IN;
-   if (!(h->flags & ALUA_RTPG_EXT_HDR_UNSUPP))
+   if (!(flags & ALUA_RTPG_EXT_HDR_UNSUPP))
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   put_unaligned_be32(h->bufflen, &rq->cmd[6]);
+   put_unaligned_be32(bufflen, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
 
-   rq->sense = h->sense;
+   rq->sense = sense;
memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
rq->sense_len = 0;
 
@@ -488,7 +489,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
expiry = round_jiffies_up(jiffies + h->transition_tmo * HZ);
 
  retry:
-   retval = submit_rtpg(sdev, h);
+   retval = submit_rtpg(sdev, h->buff, h->bufflen, h->sense, h->flags);
if (retval) {
if (!scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
  &sense_hdr)) {
-- 
1.8.5.6

--
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 12/36] scsi_dh_alua: use unaligned access macros

2015-09-29 Thread Hannes Reinecke
Use 'get_unaligned_XX' and 'put_unaligned_XX' instead of
open-coding it.

Reviewed-by: Martin K. Petersen 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 23 ---
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index a963f51..8571e57 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -152,10 +153,7 @@ static unsigned submit_rtpg(struct scsi_device *sdev, 
struct alua_dh_data *h)
rq->cmd[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
else
rq->cmd[1] = MI_REPORT_TARGET_PGS;
-   rq->cmd[6] = (h->bufflen >> 24) & 0xff;
-   rq->cmd[7] = (h->bufflen >> 16) & 0xff;
-   rq->cmd[8] = (h->bufflen >>  8) & 0xff;
-   rq->cmd[9] = h->bufflen & 0xff;
+   put_unaligned_be32(h->bufflen, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_IN);
 
rq->sense = h->sense;
@@ -236,8 +234,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
/* Prepare the data buffer */
memset(h->buff, 0, stpg_len);
h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
-   h->buff[6] = (h->group_id >> 8) & 0xff;
-   h->buff[7] = h->group_id & 0xff;
+   put_unaligned_be16(h->group_id, &h->buff[6]);
 
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
if (!rq)
@@ -246,10 +243,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
/* Prepare the command. */
rq->cmd[0] = MAINTENANCE_OUT;
rq->cmd[1] = MO_SET_TARGET_PGS;
-   rq->cmd[6] = (stpg_len >> 24) & 0xff;
-   rq->cmd[7] = (stpg_len >> 16) & 0xff;
-   rq->cmd[8] = (stpg_len >>  8) & 0xff;
-   rq->cmd[9] = stpg_len & 0xff;
+   put_unaligned_be32(stpg_len, &rq->cmd[6]);
rq->cmd_len = COMMAND_SIZE(MAINTENANCE_OUT);
 
rq->sense = h->sense;
@@ -338,11 +332,11 @@ static int alua_check_vpd(struct scsi_device *sdev, 
struct alua_dh_data *h)
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
-   h->rel_port = (d[6] << 8) + d[7];
+   h->rel_port = get_unaligned_be16(&d[6]);
break;
case 0x5:
/* Target port group */
-   h->group_id = (d[6] << 8) + d[7];
+   h->group_id = get_unaligned_be16(&d[6]);
break;
default:
break;
@@ -534,8 +528,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
return SCSI_DH_IO;
}
 
-   len = (h->buff[0] << 24) + (h->buff[1] << 16) +
-   (h->buff[2] << 8) + h->buff[3] + 4;
+   len = get_unaligned_be32(&h->buff[0]) + 4;
 
if (len > h->bufflen) {
/* Resubmit with the correct length */
@@ -570,7 +563,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_dh_data *h, int wait_
 k < len;
 k += off, ucp += off) {
 
-   if (h->group_id == (ucp[2] << 8) + ucp[3]) {
+   if (h->group_id == get_unaligned_be16(&ucp[2])) {
h->state = ucp[0] & 0x0f;
h->pref = ucp[0] >> 7;
valid_states = ucp[1];
-- 
1.8.5.6

--
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/36] scsi_dh_alua: fixup description of stpg_endio()

2015-09-29 Thread Hannes Reinecke
Fixup copy-and-paste error in the description of stpg_endio().

Signed-off-by: Hannes Reinecke 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index d4e5691..4ff9b90 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -171,13 +171,11 @@ done:
 }
 
 /*
- * alua_stpg - Evaluate SET TARGET GROUP STATES
+ * stpg_endio - Evaluate SET TARGET GROUP STATES
  * @sdev: the device to be evaluated
  * @state: the new target group state
  *
- * Send a SET TARGET GROUP STATES command to the device.
- * We only have to test here if we should resubmit the command;
- * any other error is assumed as a failure.
+ * Evaluate a SET TARGET GROUP STATES command response.
  */
 static void stpg_endio(struct request *req, int error)
 {
-- 
1.8.5.6

--
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


[PATCHv5 00/36] asynchronous ALUA device handler

2015-09-29 Thread Hannes Reinecke
Hi all,

here the next round of my update to the ALUA device handler. The main
features are:

- Topology discovery: the device handler creates a separate
  port_group structure, which is used to update all paths to
  the same port group. With that we achieve a significant
  reduction of the number of RTPGs.
- Asynchronous state update: The ALUA state is now updated
  from a workqueue item, so all concurrent RTPG calls are
  coaleasced. The ALUA state update is also triggered by
  sense codes indicating an ALUA state change.
- Use the existing vpd page 0x83 to detect device IDs
- Add generic 'access_state' attribute to discover the
  current ALUA state from userspace.

The entire tree can be found at

kernel/hare/scsi-devel branch alua.v5

on git.kernel.org

As usual, reviews and comments are welcome.

Changes to v1:
  - Split off rtpg workqueue into separate items
  - User per-port workqueues
  - Incorporate review from Bart
  - Incorporate review from hch
Changes to v2:
  - Fixup patch descriptions
  - Split off 'Improve error handling' patch
Changes to v3:
  - Implement generic 'scsi_vpd_lun_id()' function to parse vpd page 0x83
Changes to v4:
  - Revert back to a single workqueue item
  - Implement generic 'scsi_vpd_tpg_id()' function
  - Add 'access_state' attribute to struct scsi_device
  - Incorporate review from Ewan Milne
  - Incorporate further reviews from hch
  - Reshuffle patches

Hannes Reinecke (36):
  scsi_dh: move 'dh_state' sysfs attribute to generic code
  scsi: ignore errors from scsi_dh_add_device()
  scsi_dh_alua: Disable ALUA handling for non-disk devices
  scsi_dh_alua: Use vpd_pg83 information
  scsi_dh_alua: improved logging
  scsi_dh_alua: sanitze sense code handling
  scsi_dh_alua: use standard logging functions
  scsi_dh_alua: return standard SCSI return codes in submit_rtpg
  scsi_dh_alua: fixup description of stpg_endio()
  scsi: remove scsi_show_sense_hdr()
  scsi_dh_alua: use flag for RTPG extended header
  scsi_dh_alua: use unaligned access macros
  scsi_dh_alua: Pass buffer as function argument
  scsi_dh_alua: separate out alua_stpg()
  scsi_dh_alua: Make stpg synchronous
  scsi_dh_alua: call alua_rtpg() if stpg fails
  scsi_dh_alua: switch to scsi_execute_req_flags()
  scsi_dh_alua: rework alua_check_tpgs() to return the tpgs mode
  scsi_dh_alua: Use separate alua_port_group structure
  scsi_dh_alua: allocate RTPG buffer separately
  scsi_dh_alua: simplify sense code handling
  scsi: Add scsi_vpd_lun_id()
  scsi_dh_alua: use unique device id
  scsi: Add scsi_vpd_tpg_id()
  scsi_dh_alua: simplify alua_initialize()
  revert "scsi_dh_alua: ALUA hander attach should succeed while TPG is
transitioning"
  scsi_dh_alua: Use workqueue for RTPG
  scsi_dh_alua: Recheck state on unit attention
  scsi_dh_alua: update all port states
  scsi_dh_alua: Send TEST UNIT READY to poll for transitioning
  scsi: rescan VPD attributes
  scsi_dh: add 'rescan' callback
  scsi: Add 'access_state' attribute
  scsi_dh_alua: use common definitions for ALUA state
  scsi_dh_alua: update 'access_state' field
  scsi_dh_alua: Update version to 2.0

 drivers/scsi/device_handler/scsi_dh_alua.c | 1173 +---
 drivers/scsi/scsi.c|   20 +-
 drivers/scsi/scsi_dh.c |   68 +-
 drivers/scsi/scsi_lib.c|  184 +
 drivers/scsi/scsi_scan.c   |   11 +
 drivers/scsi/scsi_sysfs.c  |  122 ++-
 drivers/scsi/ses.c |   13 +-
 include/scsi/scsi_dbg.h|2 -
 include/scsi/scsi_device.h |4 +
 include/scsi/scsi_dh.h |2 +
 include/scsi/scsi_proto.h  |   13 +
 11 files changed, 1081 insertions(+), 531 deletions(-)

-- 
1.8.5.6

--
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/36] scsi_dh_alua: Use vpd_pg83 information

2015-09-29 Thread Hannes Reinecke
The SCSI device now has the VPD page 0x83 information attached,
so there is no need to query it again.

Reviewed-by: Martin K. Petersen 
Reviewed-by: Christoph Hellwig 
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 83 +-
 1 file changed, 13 insertions(+), 70 deletions(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index 7d01ef0..f15b977 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -131,43 +131,6 @@ static struct request *get_alua_req(struct scsi_device 
*sdev,
 }
 
 /*
- * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
- * @sdev: sdev the command should be sent to
- */
-static int submit_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
-{
-   struct request *rq;
-   int err = SCSI_DH_RES_TEMP_UNAVAIL;
-
-   rq = get_alua_req(sdev, h->buff, h->bufflen, READ);
-   if (!rq)
-   goto done;
-
-   /* Prepare the command. */
-   rq->cmd[0] = INQUIRY;
-   rq->cmd[1] = 1;
-   rq->cmd[2] = 0x83;
-   rq->cmd[4] = h->bufflen;
-   rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
-   rq->sense = h->sense;
-   memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-   rq->sense_len = h->senselen = 0;
-
-   err = blk_execute_rq(rq->q, NULL, rq, 1);
-   if (err == -EIO) {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: evpd inquiry failed with %x\n",
-   ALUA_DH_NAME, rq->errors);
-   h->senselen = rq->sense_len;
-   err = SCSI_DH_IO;
-   }
-   blk_put_request(rq);
-done:
-   return err;
-}
-
-/*
  * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
  * @sdev: sdev the command should be sent to
  */
@@ -359,43 +322,24 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
 }
 
 /*
- * alua_vpd_inquiry - Evaluate INQUIRY vpd page 0x83
+ * alua_check_vpd - Evaluate INQUIRY vpd page 0x83
  * @sdev: device to be checked
  *
  * Extract the relative target port and the target port group
  * descriptor from the list of identificators.
  */
-static int alua_vpd_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h)
 {
-   int len;
-   unsigned err;
unsigned char *d;
 
- retry:
-   err = submit_vpd_inquiry(sdev, h);
-
-   if (err != SCSI_DH_OK)
-   return err;
-
-   /* Check if vpd page exceeds initial buffer */
-   len = (h->buff[2] << 8) + h->buff[3] + 4;
-   if (len > h->bufflen) {
-   /* Resubmit with the correct length */
-   if (realloc_buffer(h, len)) {
-   sdev_printk(KERN_WARNING, sdev,
-   "%s: kmalloc buffer failed\n",
-   ALUA_DH_NAME);
-   /* Temporary failure, bypass */
-   return SCSI_DH_DEV_TEMP_BUSY;
-   }
-   goto retry;
-   }
+   if (!sdev->vpd_pg83)
+   return SCSI_DH_DEV_UNSUPP;
 
/*
-* Now look for the correct descriptor.
+* Look for the correct descriptor.
 */
-   d = h->buff + 4;
-   while (d < h->buff + len) {
+   d = sdev->vpd_pg83 + 4;
+   while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */
@@ -422,14 +366,13 @@ static int alua_vpd_inquiry(struct scsi_device *sdev, 
struct alua_dh_data *h)
ALUA_DH_NAME);
h->state = TPGS_STATE_OPTIMIZED;
h->tpgs = TPGS_MODE_NONE;
-   err = SCSI_DH_DEV_UNSUPP;
-   } else {
-   sdev_printk(KERN_INFO, sdev,
-   "%s: port group %02x rel port %02x\n",
-   ALUA_DH_NAME, h->group_id, h->rel_port);
+   return SCSI_DH_DEV_UNSUPP;
}
+   sdev_printk(KERN_INFO, sdev,
+   "%s: port group %02x rel port %02x\n",
+   ALUA_DH_NAME, h->group_id, h->rel_port);
 
-   return err;
+   return 0;
 }
 
 static char print_alua_state(int state)
@@ -692,7 +635,7 @@ static int alua_initialize(struct scsi_device *sdev, struct 
alua_dh_data *h)
if (err != SCSI_DH_OK)
goto out;
 
-   err = alua_vpd_inquiry(sdev, h);
+   err = alua_check_vpd(sdev, h);
if (err != SCSI_DH_OK)
goto out;
 
-- 
1.8.5.6

--
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 02/36] scsi: ignore errors from scsi_dh_add_device()

2015-09-29 Thread Hannes Reinecke
device handler initialisation might fail due to a number of
reasons. But as device_handlers are optional this shouldn't
cause us to disable the device entirely.
So just ignore errors from scsi_dh_add_device().

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/scsi_sysfs.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 5d64c3f..81d05ec 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1090,11 +1090,12 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
}
 
error = scsi_dh_add_device(sdev);
-   if (error) {
+   if (error)
+   /*
+* device_handler is optional, so any error can be ignored
+*/
sdev_printk(KERN_INFO, sdev,
"failed to add device handler: %d\n", error);
-   return error;
-   }
 
device_enable_async_suspend(&sdev->sdev_dev);
error = device_add(&sdev->sdev_dev);
-- 
1.8.5.6

--
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/36] scsi_dh_alua: Disable ALUA handling for non-disk devices

2015-09-29 Thread Hannes Reinecke
Non-disk devices might support ALUA, but the firmware
implementation is untested and frequently broken.
As we're don't actually need it disable ALUA support
for non-disk device for now.

Signed-off-by: Hannes Reinecke 
Reviewed-by: Bart Van Assche 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Martin K. Petersen 
---
 drivers/scsi/device_handler/scsi_dh_alua.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index cc2773b..7d01ef0 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -320,6 +320,18 @@ static int alua_check_tpgs(struct scsi_device *sdev, 
struct alua_dh_data *h)
 {
int err = SCSI_DH_OK;
 
+   /*
+* ALUA support for non-disk devices is fraught with
+* difficulties, so disable it for now.
+*/
+   if (sdev->type != TYPE_DISK) {
+   h->tpgs = TPGS_MODE_NONE;
+   sdev_printk(KERN_INFO, sdev,
+   "%s: disable for non-disk devices\n",
+   ALUA_DH_NAME);
+   return SCSI_DH_DEV_UNSUPP;
+   }
+
h->tpgs = scsi_device_tpgs(sdev);
switch (h->tpgs) {
case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
-- 
1.8.5.6

--
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 V8 9/9] aacraid: Update driver version

2015-09-29 Thread Mahesh Rajashekhara
Hi James,

Can you please let me know the status of V8 patch set.

Thanks,
Mahesh


-Original Message-
From: Mahesh Rajashekhara 
Sent: Wednesday, September 09, 2015 6:51 PM
To: Mahesh Rajashekhara; jbottom...@parallels.com; linux-scsi@vger.kernel.org
Cc: the...@redhat.com; Murthy Bhat; Karthikeya Sunkesula; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: RE: [PATCH V8 9/9] aacraid: Update driver version

Hi James,

Please let me know the status of V8 patchset.

Thanks,
Mahesh

-Original Message-
From: Mahesh Rajashekhara [mailto:mahesh.rajashekh...@pmcs.com] 
Sent: Friday, August 28, 2015 4:09 PM
To: jbottom...@parallels.com; linux-scsi@vger.kernel.org
Cc: the...@redhat.com; Murthy Bhat; Karthikeya Sunkesula; 
aacr...@pmc-sierra.com; Harry Yang; Rich Bono
Subject: [PATCH V8 9/9] aacraid: Update driver version

Reviewed-by: Tomas Henzl 
Reviewed-by: Murthy Bhat 
Reviewed-by: Karthikeya Sunkesula 
Signed-off-by: Mahesh Rajashekhara 
---
 drivers/scsi/aacraid/aacraid.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h 
index 2de5ebc..074878b 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -62,7 +62,7 @@ enum {
 #definePMC_GLOBAL_INT_BIT0 0x0001
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 40709
+# define AAC_DRIVER_BUILD 41010
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
--
1.9.3

--
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