Add HP hardware handler support to dm-multipath
Subsystems (2)
cover Add HP hardware handler support to dm-multipath
The following 3 patches add HP hardware handler support to dm-multipath. The first patch is very basic and provides a baseline of support but it is not complete (has no retries, error code handling, etc). Second and third patches add retries and some error code handling.
I believe all comments to date have been addressed, including whitespace issues, and passing of scripts/checkpatch.pl.
PATCH 1/3 Extremely basic hp hardware handler (no retries, no error handling, etc).
This patch adds the most basic dm-multipath hardware support for the HP active/passive arrays.
---
drivers/md/Makefile +2 -0
@@ -8,6 +8,7 @@ dm-multipath-objs := dm-hw-handler.o dm- 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 +dm-hp-sw-objs := dm-mpath-hp-sw.o md-mod-objs := md.o bitmap.o raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \
@@ -35,6 +36,7 @@ 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
drivers/md/Kconfig +6 -0
@@ -267,6 +267,12 @@ config DM_MULTIPATH_RDAC ---help--- Multipath support for LSI/Engenio RDAC. +config DM_MULTIPATH_HP + tristate "HP MSA multipath support (EXPERIMENTAL)" + depends on DM_MULTIPATH && BLK_DEV_DM && 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/dm-mpath-hp-sw.c new file +205 -0
205 lines not on this page · raw message
PATCH 2/3 Add MP_RETRY flag for hw handlers to tell dm-mpath to retry pg_init.
In reply to [email protected]This patch adds a MP_RETRY flag and "pg_init_retries" feature to dm-multipath core. The flag is a generic one, but in this instance we use it to flag cases where we must retry a pg_init command. The patch is useful for cases where a hw handler sends a path initialization command to the storage and it sees the command complete with an error code indicating the command should be retried. In this case, the hardware handler should call dm_pg_init_complete() with MP_RETRY set in the err_flags, and this suggests to the dm-mpath core to retry the pg_init. However, it is not a guarantee that the dm-mpath core will actually retry the pg_init. The number of actual retries is governed by the multipath feature argument "pg_init_retries". Once the dm-mpath core has retried the command "pg_init_retries" times without success, a subsequent dm_pg_init_complete() with MP_RETRY will cause the path to be failed via fail_path(). To specify a value of pg_init_retries, add a line similar to the following in the 'device' section of your /etc/multipath.conf file:
features "2 pg_init_retries 7"
---
drivers/md/dm-hw-handler.h +1 -0
@@ -58,5 +58,6 @@ unsigned dm_scsi_err_handler(struct hw_h#define MP_FAIL_PATH 1#define MP_BYPASS_PG 2#define MP_ERROR_IO 4/* Don't retry this I/O */ +#define MP_RETRY 8#endif
drivers/md/dm-mpath.c +50 -8
111 lines not on this page · raw message
PATCH 3/3 Add retries to hp hardware handler if path initialization command completes with a check condition.
In reply to [email protected]This patch adds retries to the hp hardware handler, and utilizes the MP_RETRY flag of dm-multipath. For now in the hp handler, if we get a pg_init completed with a check condition we just assume we can retry the pg_init command. We make this assumption because of incomplete data on specific check condition code of the HP hardware, and because testing has shown the HP path initialization command to be idempotent. The number of times we retry is settable via the "pg_init_retries" multipath map feature.
---
drivers/md/dm-mpath-hp-sw.c +46 -8
@@ -18,18 +18,52 @@#include <linux/types.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_dbg.h> #include "dm.h" #include "dm-hw-handler.h" #define DM_MSG_PREFIX "multipath hp_sw"#define HP_DM_HWH_NAME "hp_sw" -#define HP_DM_HWH_VER "0.0.3" +#define HP_DM_HWH_VER "1.0.0"struct hp_sw_context {unsigned char sense[SCSI_SENSE_BUFFERSIZE ]; }; +/** +* hp_sw_error_is_retryable - Is an HP-specific check condition retryable? +* @req: path activation request +* +* Examine error codes of request and determine whether the error is retryable. +* Some error codes are already retried by scsi-ml (see +* scsi_decide_disposition), but some HP specific codes are not. +* The intent of this routine is to supply the logic for the HP specific +* check conditions. +* +* Returns: +* 1 - command completed with retryable error +* 0 - command completed with non-retryable error +* +* Possible optimizations +* 1. More hardware-specific error codes +*/ +static int hp_sw_error_is_retryable (struct request *req) +{ +/* +* NOT_READY is known to be retryable +* For now we just dump out the sense data and call it retryable +*/ +if (status_byte (req->errors) ==CHECK_CONDITION ) +__scsi_print_sense ("hp_sw" , req->sense, req->sense_len); + +/* +* At this point we don't have complete information about all the error +* codes from this hardware, so we are just conservative and retry +* when in doubt. +*/ +return 1 ; +}/** * hp_sw_end_io - Completion handler for HP path activation.
@@ -41,8 +75,6 @@ struct hp_sw_context {* * Context: scsi-ml softirq * -* Possible optimizations -* 1. Actually check sense data for retryable error (e.g. NOT_READY) */ static void hp_sw_end_io (struct request *req,int error) {
@@ -54,11 +86,17 @@ static void hp_sw_end_io(struct requestDMDEBUG ("%s path activation command - success" , path->dev->name); }else { -DMWARN ("%s path activation command - error=0x%x" , +if (hp_sw_error_is_retryable (req)) { +DMDEBUG ("%s path activation command - retry" , + path->dev->name); + err_flags =MP_RETRY ; + goto out; + } +DMWARN ("%s path activation fail - error=0x%x" , path->dev->name, error); err_flags =MP_FAIL_PATH ; } - +out: req->end_io_data =NULL ;__blk_put_request (req->q, req);dm_pg_init_complete (path, err_flags);
@@ -136,7 +174,7 @@ static void hp_sw_pg_init(struct hw_handif (!req) {DMERR ("%s path activation command - allocation fail" , path->dev->name); - goto fail; + goto retry; }DMDEBUG ("%s path activation command - sent" , path->dev->name);
@@ -144,8 +182,8 @@ static void hp_sw_pg_init(struct hw_handblk_execute_rq_nowait (req->q,NULL , req,1 , hp_sw_end_io);return ; -fail: -dm_pg_init_complete (path,MP_FAIL_PATH ); +retry: +dm_pg_init_complete (path,MP_RETRY ); }static int hp_sw_create (struct hw_handler *hwh,unsigned argc,char **argv)