Move hardware handlers from dm layer to SCSI layer
Subsystems (3)
cover Move hardware handlers from dm layer to SCSI layer
Hello,
Set of patches that follow this email facilitate movement of hardware handlers from dm layer to SCSI layer.
Previous set of patches that implemented this was posted on Jan 24:
http://marc.info/?l=linux-scsi&m=120113462706925&w=2
Changes have been made based on feedback received from James, Alasdair, Mike Christie and Mike Anderson.
Following are the changes:
- Removed scsi_dh hardware handler in the dm layer. This means no change (not even a change in the multipath.conf file) is required in user space.
- Replaced REQ_OP_LB_TRANSITION with an activate() function.
- Removed the SDEV_PASSIVE and added a prep_fn to the device handler, hence giving it the veto power.
- Replaced blk_execute_rq_nowait() with blk_execute_rq() in device handlers to make them synchronous. Added a thread(work queue) to dm-multipath to handle requests asynchronously.
- Added Ed's changes to the EMC hardware handler.
Patches are created on top of 2.6.25-rc2-mm1.
Testing has been done with a IBM DS4800 storage device, which means the infrastructure and the lsi_rdac hardware handler has been tested. Testing by someone with the EMC hardware and/or HP hardware would be appreciated.
Comments, suggestions solicited.
Thanks,
chandra
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 1/7 scsi_dh: add skeleton for SCSI Device Handlers
Subject: scsi_dh: add skeleton for SCSI Device Handlers
From: Chandra Seetharaman <[email protected]>
Add base support to the SCSI subsystem for SCSI device handlers.
---
drivers/scsi/Kconfig | 2 2 + 0 - 0 ! drivers/scsi/Makefile | 1 1 + 0 - 0 ! drivers/scsi/device_handler/Kconfig | 12 12 + 0 - 0 ! drivers/scsi/device_handler/Makefile | 4 4 + 0 - 0 ! drivers/scsi/device_handler/scsi_dh.c | 146 146 + 0 - 0 ! drivers/scsi/scsi_error.c | 10 10 + 0 - 0 ! drivers/scsi/scsi_lib.c | 5 5 + 0 - 0 ! include/scsi/scsi_device.h | 18 18 + 0 - 0 ! include/scsi/scsi_dh.h | 58 58 + 0 - 0 ! 9 files changed, 256 insertions(+)
drivers/scsi/Kconfig +2 -0
@@ -1749,4 +1749,6 @@ endif # SCSI_LOWLEVEL source "drivers/scsi/pcmcia/Kconfig" +source "drivers/scsi/device_handler/Kconfig" + endmenu
drivers/scsi/Makefile +1 -0
@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_t obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o +obj-$(CONFIG_SCSI_DH) += device_handler/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o
drivers/scsi/device_handler/Kconfig new file +12 -0
@@ -0,0 +1,12 @@ +# +# SCSI Device Handler configuration +# + +menuconfig SCSI_DH + bool "SCSI Device Handlers" + depends on SCSI!=n + default n + help + SCSI Device Handlers provide device specific support for + devices utilized in multipath configurations. Say Y here to + select support for specific hardware.
drivers/scsi/device_handler/Makefile new file +4 -0
@@ -0,0 +1,4 @@ +# +# SCSI Device Handler +# +obj-$(CONFIG_SCSI_DH) += scsi_dh.o
drivers/scsi/scsi_error.c +10 -0
@@ -298,6 +298,7 @@ static inline void scsi_eh_prt_fail_stat*/ static int scsi_check_sense (struct scsi_cmnd *scmd) { +struct scsi_device *sdev = scmd->device;struct scsi_sense_hdr sshdr;if (!scsi_command_normalize_sense (scmd, &sshdr))
@@ -306,6 +307,15 @@ static int scsi_check_sense(struct scsi_if (scsi_sense_is_deferred (&sshdr))return NEEDS_RETRY ; +if (sdev->sdev_dh && sdev->sdev_dh->check_sense) { +int rc; + + rc = sdev->sdev_dh->check_sense (sdev, &sshdr); +if (rc !=SUCCESS ) +return rc; +/* handler does not care. Drop down to default handling */ + } +/* * Previous logic looked for FILEMARK, EOM or ILI which are * mainly associated with tapes and returned SUCCESS.
include/scsi/scsi_device.h +18 -0
@@ -161,9 +161,25 @@ struct scsi_device {struct execute_work ew;/* used to get process context on put */ +struct scsi_device_handler *sdev_dh; +void *sdev_dh_data;enum scsi_device_state sdev_state;unsigned long sdev_data[0 ]; } __attribute__((aligned(sizeof(unsigned long)))); + +struct scsi_device_handler { +/* Used by the infrastructure */ +struct list_head list;/* list of scsi_device_handlers */ +struct notifier_block nb; + +/* Filled by the hardware handler */ +struct module *module; +const char *name; +int (*check_sense)(struct scsi_device *,struct scsi_sense_hdr *); +int (*activate)(struct scsi_device *); +int (*prep_fn)(struct scsi_device *); +}; +#define to_scsi_device (d) \ container_of(d, struct scsi_device, sdev_gendev)#define class_to_sdev (d) \
@@ -229,7 +245,9 @@ extern struct scsi_device *__scsi_add_de uint, uint, uint, void *hostdata);extern int scsi_add_device (struct Scsi_Host *host,uint channel,uint target,uint lun); +extern int scsi_register_device_handler (struct scsi_device_handler *sdev_dh);extern void scsi_remove_device (struct scsi_device *); +extern int scsi_unregister_device_handler (struct scsi_device_handler *sdev_dh);extern int scsi_device_get (struct scsi_device *);extern void scsi_device_put (struct scsi_device *);
drivers/scsi/device_handler/scsi_dh.c new file +146 -0
146 lines not on this page · raw message
include/scsi/scsi_dh.h new file +58 -0
58 lines not on this page · raw message
drivers/scsi/scsi_lib.c +5 -0
@@ -1156,6 +1156,11 @@ int scsi_setup_fs_cmnd(struct scsi_devicstruct scsi_cmnd *cmd;int ret =scsi_prep_state_check (sdev, req); +if ((ret ==BLKPREP_OK ) && (req->cmd_type ==REQ_TYPE_FS )) { +if (sdev->sdev_dh && sdev->sdev_dh->prep_fn) + ret = sdev->sdev_dh->prep_fn (sdev); + } +if (ret !=BLKPREP_OK )return ret;/*
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------James Bottomley
maintainerRe: [PATCH 1/7] scsi_dh: add skeleton for SCSI Device Handlers
Quoted 5 lines · Chandra Seetharaman
Subject:
scsi_dh: add skeleton for SCSI Device HandlersFrom: Chandra Seetharaman <[email protected]>
Add base support to the SCSI subsystem for SCSI device handlers.
Generally, this is much cleaner and an easier implementation to follow, thanks.
Quoted 78 lines
Signed-off-by Chandra Seetharaman <[email protected]>Signed-off-by Mike Anderson <[email protected]>Signed-off-by Mike Christie <[email protected]>---
drivers/scsi/Kconfig | 2 2 + 0 - 0 ! drivers/scsi/Makefile | 1 1 + 0 - 0 ! drivers/scsi/device_handler/Kconfig | 12 12 + 0 - 0 ! drivers/scsi/device_handler/Makefile | 4 4 + 0 - 0 ! drivers/scsi/device_handler/scsi_dh.c | 146 146 + 0 - 0 ! drivers/scsi/scsi_error.c | 10 10 + 0 - 0 ! drivers/scsi/scsi_lib.c | 5 5 + 0 - 0 ! include/scsi/scsi_device.h | 18 18 + 0 - 0 ! include/scsi/scsi_dh.h | 58 58 + 0 - 0 ! 9 files changed, 256 insertions(+)Index: linux-2.6.25-rc2-mm1/drivers/scsi/Kconfig
===================================================================drivers/scsi/Kconfig +2
-0@@ -1749,4 +1749,6 @@ endif # SCSI_LOWLEVEL source "drivers/scsi/pcmcia/Kconfig" +source "drivers/scsi/device_handler/Kconfig" + endmenuIndex: linux-2.6.25-rc2-mm1/drivers/scsi/Makefile
===================================================================drivers/scsi/Makefile +1
-0@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_t obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o +obj-$(CONFIG_SCSI_DH) += device_handler/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.oIndex: linux-2.6.25-rc2-mm1/drivers/scsi/device_handler/Kconfig
===================================================================drivers/scsi/device_handler/Kconfig new file +12
-0@@ -0,0 +1,12 @@ +# +# SCSI Device Handler configuration +# + +menuconfig SCSI_DH + bool "SCSI Device Handlers" + depends on SCSI!=n + default n + help + SCSI Device Handlers provide device specific support for + devices utilized in multipath configurations. Say Y here to + select support for specific hardware.Index: linux-2.6.25-rc2-mm1/drivers/scsi/device_handler/Makefile
===================================================================drivers/scsi/device_handler/Makefile new file +4
-0@@ -0,0 +1,4 @@ +# +# SCSI Device Handler +# +obj-$(CONFIG_SCSI_DH) += scsi_dh.oIndex:
linux-2.6.25-rc2-mm1/drivers/scsi/scsi_error.c
===================================================================drivers/scsi/scsi_error.c +1
-0@@ -298,6 +298,7 @@ static inline void scsi_eh_prt_fail_stat*/ static int scsi_check_sense (struct scsi_cmnd *scmd) { +struct scsi_device *sdev = scmd->device;struct scsi_sense_hdr sshdr;if (!scsi_command_normalize_sense (scmd, &sshdr))
drivers/scsi/scsi_error.c static int scsi_check_sense(struct scsi_ · line 314
Quoted 8 lines
drivers/scsi/scsi_error.c +5
-0@@ -306,6 +307,15 @@ static int scsi_check_sense(struct scsi_if (scsi_sense_is_deferred (&sshdr))return NEEDS_RETRY ; +if (sdev->sdev_dh && sdev->sdev_dh->check_sense) { +int rc; + + rc = sdev->sdev_dh->check_sense (sdev, &sshdr); +if (rc !=SUCCESS )
I can see reasons for a sense handler to return SUCCESS to trigger a fast failure (say not ready needs initialising command or something, so this should be a specific sense handler doesn't care return code.
Quoted 12 lines
drivers/scsi/scsi_error.c +4
-0+return rc; +/* handler does not care. Drop down to default handling */ + } +/* * Previous logic looked for FILEMARK, EOM or ILI which are * mainly associated with tapes and returned SUCCESS. Index:
linux-2.6.25-rc2-mm1/include/scsi/scsi_device.h
===================================================================
include/scsi/scsi_device.h struct scsi_device { · line 165
Quoted 5 lines
include/scsi/scsi_device.h +2
-0@@ -161,9 +161,25 @@ struct scsi_device {struct execute_work ew;/* used to get process context on put */ +struct scsi_device_handler *sdev_dh; +void *sdev_dh_data;
This is a bit wasteful of 8 bytes ... why not simply move the sdev_dh_data inside the sdev_dh structure, then if there's no handler it's not occupying space?
Quoted 163 lines
include/scsi/scsi_device.h +16
-0enum scsi_device_state sdev_state;unsigned long sdev_data[0 ]; } __attribute__((aligned(sizeof(unsigned long)))); + +struct scsi_device_handler { +/* Used by the infrastructure */ +struct list_head list;/* list of scsi_device_handlers */ +struct notifier_block nb; + +/* Filled by the hardware handler */ +struct module *module; +const char *name; +int (*check_sense)(struct scsi_device *,struct scsi_sense_hdr *); +int (*activate)(struct scsi_device *); +int (*prep_fn)(struct scsi_device *); +}; +#define to_scsi_device (d) \ container_of(d, struct scsi_device, sdev_gendev)#define class_to_sdev (d) \@@ -229,7 +245,9 @@ extern struct scsi_device *__scsi_add_de uint, uint, uint, void *hostdata);extern int scsi_add_device (struct Scsi_Host *host,uint channel,uint target,uint lun); +extern int scsi_register_device_handler (struct scsi_device_handler *sdev_dh);extern void scsi_remove_device (struct scsi_device *); +extern int scsi_unregister_device_handler (struct scsi_device_handler *sdev_dh);extern int scsi_device_get (struct scsi_device *);extern void scsi_device_put (struct scsi_device *);Index:
linux-2.6.25-rc2-mm1/drivers/scsi/device_handler/scsi_dh.c
===================================================================drivers/scsi/device_handler/scsi_dh.c new file +128
-0@@ -0,0 +1,146 @@ +/* +* SCSI device handler infrastruture. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Copyright IBM Corporation, 2007 +* Authors: +* Chandra Seetharaman <[email protected]> +* Mike Anderson <[email protected]> +*/ + +#include <scsi/scsi_dh.h> +#include "../scsi_priv.h" + +static DEFINE_SPINLOCK (list_lock); +static LIST_HEAD (scsi_dh_list); + +static struct scsi_device_handler *get_device_handler (const char *name) +{ +struct scsi_device_handler *tmp, *found =NULL ; + +spin_lock (&list_lock); +list_for_each_entry (tmp, &scsi_dh_list, list) { +if (!strcmp (tmp->name, name)) { + found = tmp; +break ; + } + } +spin_unlock (&list_lock); +return found; +} + +static int scsi_dh_notifier_add (struct device *dev,void *data) +{ +struct scsi_device_handler *sdev_dh = data; + + sdev_dh->nb.notifier_call (&sdev_dh->nb,BUS_NOTIFY_ADD_DEVICE , dev); +return 0 ; +} + +/* +* scsi_register_device_handler - register a device handler personality +* module. +* @sdev_dh - device handler to be registered. +* +* Returns 0 on success, -EBUSY if handler already registered. +*/ +int scsi_register_device_handler (struct scsi_device_handler *sdev_dh) +{ +int ret = -EBUSY ; +struct scsi_device_handler *tmp; + + tmp =get_device_handler (sdev_dh->name); +if (tmp) + goto done; + + ret =bus_register_notifier (&scsi_bus_type, &sdev_dh->nb); + +bus_for_each_dev (&scsi_bus_type,NULL , sdev_dh, scsi_dh_notifier_add); +spin_lock (&list_lock); +list_add (&sdev_dh->list, &scsi_dh_list); +spin_unlock (&list_lock); + +done: +return ret; +} +EXPORT_SYMBOL_GPL (scsi_register_device_handler); + +static int scsi_dh_notifier_remove (struct device *dev,void *data) +{ +struct scsi_device_handler *sdev_dh = data; + + sdev_dh->nb.notifier_call (&sdev_dh->nb,BUS_NOTIFY_DEL_DEVICE , dev); +return 0 ; +} + +/* +* scsi_unregister_device_handler - register a device handler personality +* module. +* @sdev_dh - device handler to be unregistered. +* +* Returns 0 on success, -ENODEV if handler not registered. +*/ +int scsi_unregister_device_handler (struct scsi_device_handler *sdev_dh) +{ +int ret = -ENODEV ; +struct scsi_device_handler *tmp; + + tmp =get_device_handler (sdev_dh->name); +if (!tmp) + goto done; + + ret =bus_unregister_notifier (&scsi_bus_type, &sdev_dh->nb); + +bus_for_each_dev (&scsi_bus_type,NULL , sdev_dh, + scsi_dh_notifier_remove); +spin_lock (&list_lock); +list_del (&sdev_dh->list); +spin_unlock (&list_lock); + +done: +return ret; +} +EXPORT_SYMBOL_GPL (scsi_unregister_device_handler); + +/* +* scsi_dh_activate - activate the path associated with the scsi_device +* corresponding to the given request queue. +* @q - Request queue that is associated with the scsi_device to be +* activated. +*/ +int scsi_dh_activate (struct request_queue *q) +{ +int err =SCSI_DH_NOSYS ; +struct scsi_device *sdev; +struct scsi_device_handler *sdev_dh;
drivers/scsi/device_handler/scsi_dh.c line 138
Quoted 10 lines
drivers/scsi/device_handler/scsi_dh.c new file +10
-0+unsigned long flags; + +spin_lock_irqsave (q->queue_lock, flags); + sdev = q->queuedata; + sdev_dh = sdev->sdev_dh; +if (!sdev || !sdev_dh || !get_device (&sdev->sdev_gendev)) { +spin_unlock_irqrestore (q->queue_lock, flags); + goto done; + } +spin_unlock_irqrestore (q->queue_lock, flags);
just on programming style, this is marginally better expressed as
err = (!sdev || !sdev_dh || !get_device(&sdev->sdev_gendev)) ? SCSI_DH_NOSYS : 0; spin_unlock_irqrestore(q->queue_lock, flags);
if (err)
goto done; (or even return err)
Just to eliminate the duplicate unlocks.
Quoted 76 lines
drivers/scsi/device_handler/scsi_dh.c new file +8
-0+ +if (sdev_dh->activate) + err = sdev_dh->activate (sdev); +put_device (&sdev->sdev_gendev); +done: +return err; +} +EXPORT_SYMBOL_GPL (scsi_dh_activate);Index:
linux-2.6.25-rc2-mm1/include/scsi/scsi_dh.h
===================================================================include/scsi/scsi_dh.h new file +58
-0@@ -0,0 +1,58 @@ +/* +* Header file for SCSI device handler infrastruture. +* +* Modified version of patches posted by Mike Christie <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Copyright IBM Corporation, 2007 +* Authors: +* Chandra Seetharaman <[email protected]> +* Mike Anderson <[email protected]> +*/ + +#include <scsi/scsi_device.h> + +enum { +SCSI_DH_OK =0 , +/* +* device errors +*/ +SCSI_DH_DEV_FAILED ,/* generic device error */ +SCSI_DH_DEV_TEMP_BUSY , +SCSI_DH_DEVICE_MAX ,/* max device blkerr definition */ + +/* +* transport errors +*/ +SCSI_DH_NOTCONN =SCSI_DH_DEVICE_MAX +1 , +SCSI_DH_CONN_FAILURE , +SCSI_DH_TRANSPORT_MAX ,/* max transport blkerr definition */ + +/* +* driver and generic errors +*/ +SCSI_DH_IO =SCSI_DH_TRANSPORT_MAX +1 ,/* generic error */ +SCSI_DH_INVALID_IO , +SCSI_DH_RETRY ,/* retry the req, but not immediately */ +SCSI_DH_IMM_RETRY ,/* immediately retry the req */ +SCSI_DH_TIMED_OUT , +SCSI_DH_RES_TEMP_UNAVAIL , +SCSI_DH_DEV_OFFLINED , +SCSI_DH_NOSYS , +SCSI_DH_DRIVER_MAX , +}; + +extern int scsi_dh_activate (struct request_queue *);Index:
linux-2.6.25-rc2-mm1/drivers/scsi/scsi_lib.c
===================================================================
drivers/scsi/scsi_lib.c int scsi_setup_fs_cmnd(struct scsi_devic · line 1165
Quoted 10 lines
drivers/scsi/scsi_lib.c +5
-0@@ -1156,6 +1156,11 @@ int scsi_setup_fs_cmnd(struct scsi_devicstruct scsi_cmnd *cmd;int ret =scsi_prep_state_check (sdev, req); +if ((ret ==BLKPREP_OK ) && (req->cmd_type ==REQ_TYPE_FS )) { +if (sdev->sdev_dh && sdev->sdev_dh->prep_fn) + ret = sdev->sdev_dh->prep_fn (sdev); + } +if (ret !=BLKPREP_OK )return ret;
This is the fastpath and we need to be careful. We already checked cmd_type == REQ_TYPE before calling scsi_setup_fs_cmnd(), so there's no need to check it again, surely.
Plus, since we're doing if (ret != BLKPREP_OK) just below this, if you move the if down below that, it can simply become
if (unlikely(sdev->sdev_dh && sdev->sdev_dh->prep_fn)) {
ret = sdev->sdev_dh->prep_fn(sdev);
if (ret != BLKPREP_OK)
return ret;
}Because the two outer gates have already been checked. The unlikely expresses the fact that having device handlers isn't currently the very common case.
Presumably the gcc optimiser would see all of this, but it never hurts to make sure.
James
Re: [PATCH 1/7] scsi_dh: add skeleton for SCSI Device Handlers
Thanks for your comments, James.
Quoted 9 lines · James Bottomley
Quoted 5 lines · Chandra Seetharaman
Subject:
scsi_dh: add skeleton for SCSI Device HandlersFrom: Chandra Seetharaman <[email protected]>
Add base support to the SCSI subsystem for SCSI device handlers.
Generally, this is much cleaner and an easier implementation to follow, thanks.
Cool, thanks.
Quoted 4 lines
Quoted 4 lines
Signed-off-by Chandra Seetharaman <[email protected]>Signed-off-by Mike Anderson <[email protected]>Signed-off-by Mike Christie <[email protected]>
<snip>
Quoted 5 lines
if (!
scsi_command_normalize_sense(scmd, &sshdr))Quoted 4 lines
drivers/scsi/scsi_error.c +0
-0@@ -306,6 +307,15 @@ static int scsi_check_sense(struct scsi_if (scsi_sense_is_deferred (&sshdr))return NEEDS_RETRY ;
Quoted 9 lines
drivers/scsi/scsi_error.c static int scsi_check_sense(struct scsi_ · line 314
Quoted 5 lines
drivers/scsi/scsi_error.c +5
-0+if (sdev->sdev_dh && sdev->sdev_dh->check_sense) { +int rc; + + rc = sdev->sdev_dh->check_sense (sdev, &sshdr); +if (rc !=SUCCESS )I can see reasons for a sense handler to return SUCCESS to trigger a fast failure (say not ready needs initialising command or something, so this should be a specific sense handler doesn't care return code.
understand. I can return a NOT_HANDLED. Is it ok to add it as 0x2008 to scsi.h ? or any suggestions.
Quoted 14 lines
Quoted 14 lines
drivers/scsi/scsi_error.c +4
-0+return rc; +/* handler does not care. Drop down to default handling */ + } +/* * Previous logic looked for FILEMARK, EOM or ILI which are * mainly associated with tapes and returned SUCCESS. Index:
linux-2.6.25-rc2-mm1/include/scsi/scsi_device.h
===================================================================include/scsi/scsi_device.h +0
-0@@ -161,9 +161,25 @@ struct scsi_device {
Quoted 8 lines
include/scsi/scsi_device.h struct scsi_device { · line 165
Quoted 4 lines
include/scsi/scsi_device.h +2
-0struct execute_work ew;/* used to get process context on put */ +struct scsi_device_handler *sdev_dh; +void *sdev_dh_data;This is a bit wasteful of 8 bytes ... why not simply move the
sdev_dh_datainside thesdev_dhstructure, then if there's no handler it's not occupying space?
There is one sdev_dh per handler, and one sdev_dh_data per device.
But, structures can be redefined to save space when there is no hardware handler present. But, there will be a additional pointer dereference while invoking the functions, is it ok ?
Here is what I am thinking:
--------
struct scsi_device_handler { }; /* same as now */
struct scsi_dh_data {
struct scsi_device_handler *sdev_dh;
char buf[0];
};and the handlers will allocate appropriate size for this data structure.
struct scsi_device {
:
:
struct scsi_dh_data *scsi_dh_data;
};all the function invocations will be like
sdev->scsi_dh_data->sdev_dh->activate,prep_fn,check_sense
------------
Quoted 5 lines
Quoted 5 lines
include/scsi/scsi_device.h +0
-0enum scsi_device_state sdev_state;unsigned long sdev_data[0 ]; } __attribute__((aligned(sizeof(unsigned long))));
<snip>
Quoted 18 lines
+int
scsi_dh_activate(struct request_queue *q)Quoted 4 lines
include/scsi/scsi_device.h +4
-0+{ +int err =SCSI_DH_NOSYS ; +struct scsi_device *sdev; +struct scsi_device_handler *sdev_dh;include/scsi/scsi_device.h
Quoted 10 lines
include/scsi/scsi_device.h +10
-0+unsigned long flags; + +spin_lock_irqsave (q->queue_lock, flags); + sdev = q->queuedata; + sdev_dh = sdev->sdev_dh; +if (!sdev || !sdev_dh || !get_device (&sdev->sdev_gendev)) { +spin_unlock_irqrestore (q->queue_lock, flags); + goto done; + } +spin_unlock_irqrestore (q->queue_lock, flags);just on programming style, this is marginally better expressed as
Quoted 7 lines
err = (!sdev || !sdev_dh || !get_device(&sdev->sdev_gendev)) ?
SCSI_DH_NOSYS: 0;spin_unlock_irqrestore(q->queue_lock, flags);if (err)
goto done; (or even return err)Just to eliminate the duplicate unlocks.
will do.
Quoted 10 lines
Quoted 10 lines
include/scsi/scsi_device.h +8
-0+ +if (sdev_dh->activate) + err = sdev_dh->activate (sdev); +put_device (&sdev->sdev_gendev); +done: +return err; +} +EXPORT_SYMBOL_GPL (scsi_dh_activate);
<snip>
Quoted 10 lines
+
Quoted 9 lines
+extern int
scsi_dh_activate(struct request_queue *);
Index:linux-2.6.25-rc2-mm1/drivers/scsi/scsi_lib.c
===================================================================drivers/scsi/scsi_lib.c +0
-0@@ -1156,6 +1156,11 @@ int scsi_setup_fs_cmnd(struct scsi_devicstruct scsi_cmnd *cmd;int ret =scsi_prep_state_check (sdev, req);
Quoted 11 lines
drivers/scsi/scsi_lib.c int scsi_setup_fs_cmnd(struct scsi_devic · line 1165
Quoted 7 lines
drivers/scsi/scsi_lib.c +5
-0+if ((ret ==BLKPREP_OK ) && (req->cmd_type ==REQ_TYPE_FS )) { +if (sdev->sdev_dh && sdev->sdev_dh->prep_fn) + ret = sdev->sdev_dh->prep_fn (sdev); + } +if (ret !=BLKPREP_OK )return ret;This is the fastpath and we need to be careful. We already checked
cmd_type==REQ_TYPEbefore callingscsi_setup_fs_cmnd(), so there's no need to check it again, surely.
Yeah, this was a cut-n-paste problem. I had this block at the higher level, moved it here to get rid of that check, but forgot to remove that :)
Quoted 10 lines
Plus, since we're doing if (ret !=
BLKPREP_OK) just below this, if you move the if down below that, it can simply becomeif (unlikely(sdev->sdev_dh && sdev->sdev_dh->prep_fn)) { ret = sdev->sdev_dh->prep_fn(sdev); if (ret != BLKPREP_OK) return ret; }
Quoted 3 lines
Because the two outer gates have already been checked. The unlikely expresses the fact that having device handlers isn't currently the very common case.
will do.
Quoted 7 lines
Presumably the gcc optimiser would see all of this, but it never hurts to make sure.
James
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 2/7 scsi_dh: add lsi rdac device handler
In reply to Chandra SeetharamanSubject: scsi_dh: add lsi rdac device handler
From: Chandra Seetharaman <[email protected]>
add LSI RDAC SCSI device handler
---
drivers/scsi/device_handler/Kconfig | 6 6 + 0 - 0 ! drivers/scsi/device_handler/Makefile | 1 1 + 0 - 0 ! drivers/scsi/device_handler/scsi_dh_rdac.c | 660 660 + 0 - 0 ! 3 files changed, 667 insertions(+)
drivers/scsi/device_handler/Kconfig +6 -0
@@ -10,3 +10,9 @@ menuconfig SCSI_DH SCSI Device Handlers provide device specific support for devices utilized in multipath configurations. Say Y here to select support for specific hardware. + +config SCSI_DH_RDAC + tristate "LSI RDAC Device Handler" + depends on SCSI_DH + help + If you have a LSI RDAC select y. Otherwise, say N.
drivers/scsi/device_handler/scsi_dh_rdac.c new file +660 -0
660 lines not on this page · raw message
drivers/scsi/device_handler/Makefile +1 -0
@@ -2,3 +2,4 @@ # SCSI Device Handler # obj-$(CONFIG_SCSI_DH) += scsi_dh.o +obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 3/7 scsi_dh: add hp sw device handler
In reply to Chandra SeetharamanSubject: scsi_dh: add hp sw device handler
From: Mike Christie <[email protected]>
This patch adds a very basic scsi device handler for older hp boxes which cannot be upgraded.
---
drivers/scsi/device_handler/Kconfig | 8 8 + 0 - 0 ! drivers/scsi/device_handler/Makefile | 1 1 + 0 - 0 ! drivers/scsi/device_handler/scsi_dh_hp_sw.c | 193 193 + 0 - 0 ! 3 files changed, 202 insertions(+)
drivers/scsi/device_handler/Kconfig +8 -0
@@ -16,3 +16,11 @@ config SCSI_DH_RDAC depends on SCSI_DH help If you have a LSI RDAC select y. Otherwise, say N. + +config SCSI_DH_HP_SW + tristate "HP/COMPAQ MSA Device Handler" + depends on SCSI_DH + help + If you have a HP/COMPAQ MSA device that requires START_STOP to + be sent to start it and cannot upgrade the firmware then select y. + Otherwise, say N.
drivers/scsi/device_handler/Makefile +1 -0
@@ -3,3 +3,4 @@ # obj-$(CONFIG_SCSI_DH) += scsi_dh.o obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o +obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o
drivers/scsi/device_handler/scsi_dh_hp_sw.c new file +193 -0
193 lines not on this page · raw message
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 4/7 scsi_dh: add EMC Clariion device handler
In reply to Chandra SeetharamanSubject: scsi_dh: add EMC Clariion device handler
From: Chandra Seetharaman <[email protected]>
This adds support for EMC Clariions. This patch has the features that currently exists in mainline and advanced features from Ed's patches.
---
drivers/scsi/device_handler/Kconfig | 6 6 + 0 - 0 ! drivers/scsi/device_handler/Makefile | 1 1 + 0 - 0 ! drivers/scsi/device_handler/scsi_dh_emc.c | 488 488 + 0 - 0 ! 3 files changed, 495 insertions(+)
drivers/scsi/device_handler/Kconfig +6 -0
@@ -24,3 +24,9 @@ config SCSI_DH_HP_SW If you have a HP/COMPAQ MSA device that requires START_STOP to be sent to start it and cannot upgrade the firmware then select y. Otherwise, say N. + +config SCSI_DH_EMC + tristate "EMC CLARiiON Device Handler" + depends on SCSI_DH + help + If you have a EMC CLARiiON select y. Otherwise, say N.
drivers/scsi/device_handler/scsi_dh_emc.c new file +488 -0
488 lines not on this page · raw message
drivers/scsi/device_handler/Makefile +1 -0
@@ -4,3 +4,4 @@ obj-$(CONFIG_SCSI_DH) += scsi_dh.o obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o +obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 5/7 scsi_dh: Use SCSI device handler in dm-multipath
In reply to Chandra SeetharamanSubject: scsi_dh: Use SCSI device handler in dm-multipath
From: Chandra Seetharaman <[email protected]>
This patch converts dm-mpath to scsi hw handlers. It does not add any new functionality and old behaviors and userspace tools work as is except we use the safe clariion default instead of using the userspace setting.
---
drivers/md/Kconfig | 1 1 + 0 - 0 !
drivers/md/dm-mpath.c | 226 114 + 112 - 0 !
2 files changed, 115 insertions(+), 112 deletions(-)
drivers/md/dm-mpath.c +114 -112
@@ -7,7 +7,6 @@#include "dm.h" #include "dm-path-selector.h" -#include "dm-hw-handler.h" #include "dm-bio-list.h" #include "dm-bio-record.h" #include "dm-uevent.h"
@@ -20,6 +19,7 @@#include <linux/slab.h> #include <linux/time.h> #include <linux/workqueue.h> +#include <scsi/scsi_dh.h> #include <asm/atomic.h> #define DM_MSG_PREFIX "multipath"
@@ -61,9 +61,14 @@ struct multipath {spinlock_t lock; -struct hw_handler hw_handler;unsigned nr_priority_groups;struct list_head priority_groups; + +/* Fields used by hardware handler usage */ +char *hw_handler_name; +struct work_struct activate_passive_path; +struct dm_path *path_to_activate; +unsigned pg_init_required;/* pg_init needs calling? */ unsigned pg_init_in_progress;/* Only one pg_init allowed at once */
@@ -106,9 +111,13 @@ typedef int (*action_fn) (struct pgpathstatic struct kmem_cache *_mpio_cache; -static struct workqueue_struct *kmultipathd; +static struct workqueue_struct *kmultipathd, *hw_handlerd;static void process_queued_ios (struct work_struct *work);static void trigger_event (struct work_struct *work); +static void activate_passive_path (struct work_struct *work); +static void bypass_pg (struct multipath *m,struct priority_group *pg, +int bypassed); +static int fail_path (struct pgpath *pgpath);/*-----------------------------------------------
@@ -178,6 +187,7 @@ static struct multipath *alloc_multipath m->queue_io =1 ;INIT_WORK (&m->process_queued_ios, process_queued_ios);INIT_WORK (&m->trigger_event, trigger_event); +INIT_WORK (&m->activate_passive_path, activate_passive_path); m->mpio_pool =mempool_create_slab_pool (MIN_IOS , _mpio_cache);if (!m->mpio_pool) {kfree (m);
@@ -193,18 +203,13 @@ static struct multipath *alloc_multipathstatic void free_multipath (struct multipath *m) {struct priority_group *pg, *tmp; -struct hw_handler *hwh = &m->hw_handler;list_for_each_entry_safe (pg, tmp, &m->priority_groups, list) {list_del (&pg->list);free_priority_group (pg, m->ti); } -if (hwh->type) { - hwh->type->destroy (hwh); -dm_put_hw_handler (hwh->type); - } - +kfree (m->hw_handler_name);mempool_destroy (m->mpio_pool);kfree (m); }
@@ -216,12 +221,10 @@ static void free_multipath(struct multipstatic void __switch_pg (struct multipath *m,struct pgpath *pgpath) { -struct hw_handler *hwh = &m->hw_handler; - m->current_pg = pgpath->pg;/* Must we initialise the PG first, and queue I/O till it's ready? */ -if (hwh->type && hwh->type->pg_init) { +if (m->hw_handler_name) { m->pg_init_required =1 ; m->queue_io =1 ; }else {
@@ -405,11 +408,86 @@ static void dispatch_queued_ios(struct m } } +static void pg_init_done (struct dm_path *path,int errors) +{ +struct pgpath *pgpath =path_to_pgpath (path); +struct priority_group *pg = pgpath->pg; +struct multipath *m = pg->m; +unsigned long flags; + +/* device or driver problems */ +switch (errors) { +case SCSI_DH_OK : +break ; +case SCSI_DH_NOSYS : +if (!m->hw_handler_name) { + errors =0 ; +break ; + } +DMERR ("Cannot failover device because hw-%s may not be " +"loaded." , m->hw_handler_name); +/* +* Fail path for now, so we do not ping poing +*/ +fail_path (pgpath); +break ; +case SCSI_DH_DEV_TEMP_BUSY : +/* +* Probably doing something like FW upgrade on the +* controller so try the other pg. +*/ +bypass_pg (m, pg,1 ); +break ; +/* TODO: For SCSI_DH_RETRY we should wait a couple seconds */ +case SCSI_DH_RETRY : +case SCSI_DH_IMM_RETRY : +case SCSI_DH_RES_TEMP_UNAVAIL : +break ; +default : +/* +* We probably do not want to fail the path for a device +* error, but this is what the old dm did. In future +* patches we can do more advanced handling. +*/ +fail_path (pgpath); + } + +spin_lock_irqsave (&m->lock, flags); +if (errors) { +DMERR ("Could not failover device. Error %d." , errors); + m->current_pgpath =NULL ; + m->current_pg =NULL ; + }else if (!m->pg_init_required) { + m->queue_io =0 ; + pg->bypassed =0 ; + } + + m->pg_init_in_progress =0 ; +queue_work (kmultipathd, &m->process_queued_ios); +spin_unlock_irqrestore (&m->lock, flags); +} + +static void activate_passive_path (struct work_struct *work) +{ +int ret; +struct multipath *m = + container_of(work, struct multipath, activate_passive_path); +struct dm_path *path = m->path_to_activate; + + ret =scsi_dh_activate (bdev_get_queue (path->dev->bdev)); +pg_init_done (path, ret); +} + +static void pg_init (struct multipath *m,struct dm_path *path) +{ + m->path_to_activate = path; +queue_work (hw_handlerd, &m->activate_passive_path); +} +static void process_queued_ios (struct work_struct *work) {struct multipath *m = container_of(work, struct multipath, process_queued_ios); -struct hw_handler *hwh = &m->hw_handler;struct pgpath *pgpath =NULL ;unsigned init_required =0 , must_queue =1 ;unsigned long flags;
@@ -439,7 +517,7 @@ out:spin_unlock_irqrestore (&m->lock, flags);if (init_required) - hwh->type->pg_init (hwh, pgpath->pg->bypassed, &pgpath->path); +pg_init (m, &pgpath->path);if (!must_queue)dispatch_queued_ios (m);
@@ -652,10 +730,9 @@ static struct priority_group *parse_priostatic int parse_hw_handler (struct arg_set *as,struct multipath *m) { +struct dm_target *ti = m->ti;int r; -struct hw_handler_type *hwht;unsigned hw_argc; -struct dm_target *ti = m->ti;static struct param _params[] = { {0 ,1024 ,"invalid number of hardware handler args" },
@@ -668,25 +745,15 @@ static int parse_hw_handler(struct arg_sif (!hw_argc)return 0 ; - hwht =dm_get_hw_handler (shift (as)); -if (!hwht) { + m->hw_handler_name =kstrdup (shift (as),GFP_KERNEL ); + r =request_module ("scsi_dh_%s" , m->hw_handler_name); +if (r) { +kfree (m->hw_handler_name); + m->hw_handler_name =NULL ; ti->error ="unknown hardware handler type" ;return -EINVAL ; } - - m->hw_handler.md =dm_table_get_md (ti->table); -dm_put (m->hw_handler.md); - - r = hwht->create (&m->hw_handler, hw_argc -1 , as->argv); -if (r) { -dm_put_hw_handler (hwht); - ti->error ="hardware handler constructor failed" ; -return r; - } - - m->hw_handler.type = hwht;consume (as, hw_argc -1 ); -return 0 ; }
@@ -808,6 +875,7 @@ static void multipath_dtr(struct dm_targ {struct multipath *m = (struct multipath *) ti->private; +flush_workqueue (hw_handlerd);flush_workqueue (kmultipathd);free_multipath (m); }
@@ -1006,71 +1074,11 @@ static int bypass_pg_num(struct multipat }/* -* Should we retry pg_init immediately? -*/ -static int pg_init_limit_reached (struct multipath *m,struct pgpath *pgpath) -{ -unsigned long flags; -int limit_reached =0 ; - -spin_lock_irqsave (&m->lock, flags); - -if (m->pg_init_count <= m->pg_init_retries) - m->pg_init_required =1 ; -else - limit_reached =1 ; - -spin_unlock_irqrestore (&m->lock, flags); - -return limit_reached; -} - -/* -* pg_init must call this when it has completed its initialisation -*/ -void dm_pg_init_complete (struct dm_path *path,unsigned err_flags) -{ -struct pgpath *pgpath =path_to_pgpath (path); -struct priority_group *pg = pgpath->pg; -struct multipath *m = pg->m; -unsigned long flags; - -/* -* If requested, retry pg_init until maximum number of retries exceeded. -* If retry not requested and PG already bypassed, always fail the path. -*/ -if (err_flags &MP_RETRY ) { -if (pg_init_limit_reached (m, pgpath)) - err_flags |=MP_FAIL_PATH ; - }else if (err_flags && pg->bypassed) - err_flags |=MP_FAIL_PATH ; - -if (err_flags &MP_FAIL_PATH ) -fail_path (pgpath); - -if (err_flags &MP_BYPASS_PG ) -bypass_pg (m, pg,1 ); - -spin_lock_irqsave (&m->lock, flags); -if (err_flags & ~MP_RETRY ) { - m->current_pgpath =NULL ; - m->current_pg =NULL ; - }else if (!m->pg_init_required) - m->queue_io =0 ; - - m->pg_init_in_progress =0 ; -queue_work (kmultipathd, &m->process_queued_ios); -spin_unlock_irqrestore (&m->lock, flags); -} - -/* * end_io handling */ static int do_end_io (struct multipath *m,struct bio *bio,int error,struct dm_mpath_io *mpio) { -struct hw_handler *hwh = &m->hw_handler; -unsigned err_flags =MP_FAIL_PATH ;/* Default behavior */ unsigned long flags;if (!error)
@@ -1097,19 +1105,8 @@ static int do_end_io(struct multipath *m }spin_unlock_irqrestore (&m->lock, flags); -if (hwh->type && hwh->type->error) - err_flags = hwh->type->error (hwh, bio); - -if (mpio->pgpath) { -if (err_flags &MP_FAIL_PATH ) -fail_path (mpio->pgpath); - -if (err_flags &MP_BYPASS_PG ) -bypass_pg (m, mpio->pgpath->pg,1 ); - } - -if (err_flags &MP_ERROR_IO ) -return -EIO ; +if (mpio->pgpath) +fail_path (mpio->pgpath); requeue:dm_bio_restore (&mpio->details, bio);
@@ -1194,7 +1191,6 @@ static int multipath_status(struct dm_taint sz =0 ;unsigned long flags;struct multipath *m = (struct multipath *) ti->private; -struct hw_handler *hwh = &m->hw_handler;struct priority_group *pg;struct pgpath *p;unsigned pg_num;
@@ -1214,12 +1210,10 @@ static int multipath_status(struct dm_taDMEMIT ("pg_init_retries %u " , m->pg_init_retries); } -if (hwh->type && hwh->type->status) - sz += hwh->type->status (hwh, type, result + sz, maxlen - sz); -else if (!hwh->type || type ==STATUSTYPE_INFO ) -DMEMIT ("0 " ); +if (m->hw_handler_name) +DMEMIT ("1 %s " , m->hw_handler_name);else -DMEMIT ("1 %s " , hwh->type->name); +DMEMIT ("0 " );DMEMIT ("%u " , m->nr_priority_groups);
@@ -1422,6 +1416,15 @@ static int __init dm_multipath_init(voidreturn -ENOMEM ; } + hw_handlerd =create_workqueue ("khwhandlerd" ); +if (!hw_handlerd) { +DMERR ("failed to create workqueue khwhandlerd" ); +destroy_workqueue (kmultipathd); +dm_unregister_target (&multipath_target); +kmem_cache_destroy (_mpio_cache); +return -ENOMEM ; + } +DMINFO ("version %u.%u.%u loaded" , multipath_target.version[0 ], multipath_target.version[1 ], multipath_target.version[2 ]);
@@ -1433,6 +1436,7 @@ static void __exit dm_multipath_exit(voi {int r; +destroy_workqueue (hw_handlerd);destroy_workqueue (kmultipathd); r =dm_unregister_target (&multipath_target);
@@ -1441,8 +1445,6 @@ static void __exit dm_multipath_exit(voikmem_cache_destroy (_mpio_cache); } -EXPORT_SYMBOL_GPL (dm_pg_init_complete); -module_init (dm_multipath_init);module_exit (dm_multipath_exit);
drivers/md/Kconfig +1 -0
@@ -252,6 +252,7 @@ config DM_ZERO config DM_MULTIPATH tristate "Multipath target" depends on BLK_DEV_DM + select SCSI_DH ---help--- Allow volume managers to support multipath hardware.
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 6/7 scsi_dh: Remove hardware handlers from dm
In reply to Chandra SeetharamanSubject: scsi_dh: Remove hardware handlers from dm
From: Chandra Seetharaman <[email protected]>
This patch removes the 3 hardware handlers that currently exist under dm as they are moved to SCSI layer in the previous patches.
---
drivers/md/Kconfig | 18 0 + 18 - 0 ! drivers/md/Makefile | 3 0 + 3 - 0 ! drivers/md/dm-emc.c | 347 0 + 347 - 0 ! drivers/md/dm-mpath-hp-sw.c | 248 0 + 248 - 0 ! drivers/md/dm-mpath-rdac.c | 701 0 + 701 - 0 ! 5 files changed, 1317 deletions(-)
drivers/md/Kconfig +0 -18
@@ -256,24 +256,6 @@ config DM_MULTIPATH ---help--- Allow volume managers to support multipath hardware. -config DM_MULTIPATH_EMC - tristate "EMC CX/AX multipath support" - depends on DM_MULTIPATH && BLK_DEV_DM - ---help--- - Multipath support for EMC CX/AX series hardware. - -config DM_MULTIPATH_RDAC - tristate "LSI/Engenio RDAC multipath support (EXPERIMENTAL)" - depends on DM_MULTIPATH && BLK_DEV_DM && SCSI && EXPERIMENTAL - ---help--- - Multipath support for LSI/Engenio RDAC. - -config DM_MULTIPATH_HP - tristate "HP MSA multipath support (EXPERIMENTAL)" - depends on DM_MULTIPATH && BLK_DEV_DM && SCSI && EXPERIMENTAL - ---help--- - Multipath support for HP MSA (Active/Passive) series hardware. - config DM_DELAY tristate "I/O delaying target (EXPERIMENTAL)" depends on BLK_DEV_DM && EXPERIMENTAL
drivers/md/Makefile +0 -3
@@ -35,9 +35,6 @@ obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o obj-$(CONFIG_DM_DELAY) += dm-delay.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o -obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o -obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o -obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o obj-$(CONFIG_DM_ZERO) += dm-zero.o
drivers/md/dm-emc.c deleted +0 -347
347 lines not on this page · raw message
drivers/md/dm-mpath-hp-sw.c deleted +0 -248
248 lines not on this page · raw message
drivers/md/dm-mpath-rdac.c deleted +0 -701
701 lines not on this page · raw message
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------PATCH 7/7 scsi_dh: Remove hardware handler infrastructure from dm
In reply to Chandra SeetharamanSubject: scsi_dh: Remove hardware handler infrastructure from dm
From: Chandra Seetharaman <[email protected]>
This patch just removes infrastructure that provide support to add a hardware handler to dm.
---
drivers/md/Makefile | 2 1 + 1 - 0 ! drivers/md/dm-hw-handler.c | 213 0 + 213 - 0 ! drivers/md/dm-hw-handler.h | 63 0 + 63 - 0 ! drivers/md/dm-mpath.h | 1 0 + 1 - 0 ! 4 files changed, 1 insertion(+), 278 deletions(-)
drivers/md/dm-hw-handler.c deleted +0 -213
@@ -1,213 +0,0 @@ -/* -* Copyright (C) 2004 Red Hat, Inc. All rights reserved. -* -* This file is released under the GPL. -* -* Multipath hardware handler registration. -*/ - -#include "dm.h" -#include "dm-hw-handler.h" - -#include <linux/slab.h> - -struct hwh_internal { -struct hw_handler_type hwht; - -struct list_head list; -long use; -}; - -#define hwht_to_hwhi (__hwht) container_of((__hwht), struct hwh_internal, hwht) - -static LIST_HEAD (_hw_handlers); -static DECLARE_RWSEM (_hwh_lock); - -static struct hwh_internal *__find_hw_handler_type (const char *name) -{ -struct hwh_internal *hwhi; - -list_for_each_entry (hwhi, &_hw_handlers, list) { -if (!strcmp (name, hwhi->hwht.name)) -return hwhi; - } - -return NULL ; -} - -static struct hwh_internal *get_hw_handler (const char *name) -{ -struct hwh_internal *hwhi; - -down_read (&_hwh_lock); - hwhi =__find_hw_handler_type (name); -if (hwhi) { -if ((hwhi->use ==0 ) && !try_module_get (hwhi->hwht.module)) - hwhi =NULL ; -else - hwhi->use++; - } -up_read (&_hwh_lock); - -return hwhi; -} - -struct hw_handler_type *dm_get_hw_handler (const char *name) -{ -struct hwh_internal *hwhi; - -if (!name) -return NULL ; - - hwhi =get_hw_handler (name); -if (!hwhi) { -request_module ("dm-%s" , name); - hwhi =get_hw_handler (name); - } - -return hwhi ? &hwhi->hwht :NULL ; -} - -void dm_put_hw_handler (struct hw_handler_type *hwht) -{ -struct hwh_internal *hwhi; - -if (!hwht) -return ; - -down_read (&_hwh_lock); - hwhi =__find_hw_handler_type (hwht->name); -if (!hwhi) - goto out; - -if (--hwhi->use ==0 ) -module_put (hwhi->hwht.module); - -BUG_ON (hwhi->use <0 ); - - out: -up_read (&_hwh_lock); -} - -static struct hwh_internal *_alloc_hw_handler (struct hw_handler_type *hwht) -{ -struct hwh_internal *hwhi =kzalloc (sizeof (*hwhi),GFP_KERNEL ); - -if (hwhi) - hwhi->hwht = *hwht; - -return hwhi; -} - -int dm_register_hw_handler (struct hw_handler_type *hwht) -{ -int r =0 ; -struct hwh_internal *hwhi =_alloc_hw_handler (hwht); - -if (!hwhi) -return -ENOMEM ; - -down_write (&_hwh_lock); - -if (__find_hw_handler_type (hwht->name)) { -kfree (hwhi); - r = -EEXIST ; - }else -list_add (&hwhi->list, &_hw_handlers); - -up_write (&_hwh_lock); - -return r; -} - -int dm_unregister_hw_handler (struct hw_handler_type *hwht) -{ -struct hwh_internal *hwhi; - -down_write (&_hwh_lock); - - hwhi =__find_hw_handler_type (hwht->name); -if (!hwhi) { -up_write (&_hwh_lock); -return -EINVAL ; - } - -if (hwhi->use) { -up_write (&_hwh_lock); -return -ETXTBSY ; - } - -list_del (&hwhi->list); - -up_write (&_hwh_lock); - -kfree (hwhi); - -return 0 ; -} - -unsigned dm_scsi_err_handler (struct hw_handler *hwh,struct bio *bio) -{ -#if 0 -int sense_key, asc, ascq; - -if (bio->bi_error &BIO_SENSE ) { -/* FIXME: This is just an initial guess. */ -/* key / asc / ascq */ - sense_key = (bio->bi_error >>16 ) &0xff ; - asc = (bio->bi_error >>8 ) &0xff ; - ascq = bio->bi_error &0xff ; - -switch (sense_key) { -/* This block as a whole comes from the device. -* So no point retrying on another path. */ -case 0x03 :/* Medium error */ -case 0x05 :/* Illegal request */ -case 0x07 :/* Data protect */ -case 0x08 :/* Blank check */ -case 0x0a :/* copy aborted */ -case 0x0c :/* obsolete - no clue ;-) */ -case 0x0d :/* volume overflow */ -case 0x0e :/* data miscompare */ -case 0x0f :/* reserved - no idea either. */ -return MP_ERROR_IO ; - -/* For these errors it's unclear whether they -* come from the device or the controller. -* So just lets try a different path, and if -* it eventually succeeds, user-space will clear -* the paths again... */ -case 0x02 :/* Not ready */ -case 0x04 :/* Hardware error */ -case 0x09 :/* vendor specific */ -case 0x0b :/* Aborted command */ -return MP_FAIL_PATH ; - -case 0x06 :/* Unit attention - might want to decode */ -if (asc ==0x04 && ascq ==0x01 ) -/* "Unit in the process of -* becoming ready" */ -return 0 ; -return MP_FAIL_PATH ; - -/* FIXME: For Unit Not Ready we may want -* to have a generic pg activation -* feature (START_UNIT). */ - -/* Should these two ever end up in the -* error path? I don't think so. */ -case 0x00 :/* No sense */ -case 0x01 :/* Recovered error */ -return 0 ; - } - } -#endif - -/* We got no idea how to decode the other kinds of errors -> -* assume generic error condition. */ -return MP_FAIL_PATH ; -} - -EXPORT_SYMBOL_GPL (dm_register_hw_handler); -EXPORT_SYMBOL_GPL (dm_unregister_hw_handler); -EXPORT_SYMBOL_GPL (dm_scsi_err_handler);
drivers/md/dm-hw-handler.h deleted +0 -63
63 lines not on this page · raw message
drivers/md/Makefile +1 -1
@@ -4,7 +4,7 @@ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ dm-ioctl.o dm-io.o kcopyd.o -dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o +dm-multipath-objs := dm-path-selector.o dm-mpath.o dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-mirror-objs := dm-log.o dm-raid1.o dm-rdac-objs := dm-mpath-rdac.o
drivers/md/dm-mpath.h +0 -1
@@ -16,7 +16,6 @@ struct dm_path {unsigned is_active;/* Read-only */ void *pscontext;/* For path-selector use */ -void *hwhcontext;/* For hw-handler use */ };/* Callback for hwh_pg_init_fn to use when complete */
Signature · 4 lines
----------------------------------------------------------------------
Chandra Seetharaman | Be careful what you choose....
- [email protected] | .......you may get it.
----------------------------------------------------------------------