Search
j0ke.net Open Build Service
>
Projects
>
GFS
>
multipath-tools
> multipath-tools-add-hp-sw-prio
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File multipath-tools-add-hp-sw-prio of Package multipath-tools
tree d7d968b8eef01639d41cf493a3624c361724d869 parent 96872c26aa434b4611dbc46b14fbb79eeda2b81c author Hannes Reinecke <hare@suse.de> 1174050152 +0100 committer Hannes Reinecke <hare@suse.de> 1174050152 +0100 [hwtable] Add new priority checker mpath_hp_sw All paths on HP Active/Standby firmware should really be grouped according to the path state as we want to send the failover command correctly. And access it via more that one path. Signed-off-by: Hannes Reinecke <hare@suse.de> 9ac652e1aed2fdcaf4408a5b817ba69829b141ae libmultipath/hwtable.c | 8 +- path_priority/pp_hp_sw/Makefile | 25 ++++++++ path_priority/pp_hp_sw/pp_hp_sw.c | 119 +++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 4 deletions(-) diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c index a708051..92304d7 100644 --- a/libmultipath/hwtable.c +++ b/libmultipath/hwtable.c @@ -63,11 +63,11 @@ static struct hwentry default_hw[] = { .vendor = "DEC", .product = "HSG80", .getuid = DEFAULT_GETUID, - .getprio = NULL, + .getprio = "mpath_prio_hp_sw /dev/%n", .features = DEFAULT_FEATURES, .hwhandler = "1 hp_sw", .selector = DEFAULT_SELECTOR, - .pgpolicy = GROUP_BY_SERIAL, + .pgpolicy = GROUP_BY_PRIO, .pgfailback = FAILBACK_UNDEF, .rr_weight = RR_WEIGHT_NONE, .no_path_retry = NO_PATH_RETRY_UNDEF, @@ -94,11 +94,11 @@ static struct hwentry default_hw[] = { .vendor = "(COMPAQ|HP)", .product = "(MSA|HSV)1.0.*", .getuid = DEFAULT_GETUID, - .getprio = NULL, + .getprio = "mpath_prio_hp_sw /dev/%n", .features = DEFAULT_FEATURES, .hwhandler = "1 hp_sw", .selector = DEFAULT_SELECTOR, - .pgpolicy = MULTIBUS, + .pgpolicy = GROUP_BY_PRIO, .pgfailback = FAILBACK_UNDEF, .rr_weight = RR_WEIGHT_NONE, .no_path_retry = NO_PATH_RETRY_UNDEF, diff --git a/path_priority/pp_hp_sw/Makefile b/path_priority/pp_hp_sw/Makefile new file mode 100644 index 0000000..e7debf5 --- /dev/null +++ b/path_priority/pp_hp_sw/Makefile @@ -0,0 +1,25 @@ +EXEC = mpath_prio_hp_sw +BUILD = glibc +OBJS = pp_hp_sw.o + +TOPDIR = ../.. +include $(TOPDIR)/Makefile.inc + +all: $(BUILD) + +glibc: $(OBJS) + $(CC) -o $(EXEC) $(OBJS) $(LDFLAGS) + +klibc: $(OBJS) + $(CC) -static -o $(EXEC) $(OBJS) + +install: $(EXEC) + install -m 755 $(EXEC) $(DESTDIR)$(bindir)/$(EXEC) + +uninstall: + rm $(DESTDIR)$(bindir)/$(EXEC) +clean: + rm -f *.o $(EXEC) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/path_priority/pp_hp_sw/pp_hp_sw.c b/path_priority/pp_hp_sw/pp_hp_sw.c new file mode 100644 index 0000000..e4a18b1 --- /dev/null +++ b/path_priority/pp_hp_sw/pp_hp_sw.c @@ -0,0 +1,119 @@ +/* + * Path priority checker for HP active/standby controller + * + * Check the path state and sort them into groups. + * There is actually a preferred path in the controller; + * we should ask HP on how to retrieve that information. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <errno.h> + +#define TUR_CMD_LEN 6 +#define SCSI_CHECK_CONDITION 0x2 +#define SCSI_COMMAND_TERMINATED 0x22 +#define SG_ERR_DRIVER_SENSE 0x08 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define UNIT_ATTENTION 0x06 + +#define HP_PATH_ACTIVE 0x04 +#define HP_PATH_STANDBY 0x02 +#define HP_PATH_FAILED 0x00 + +#include "../../libmultipath/sg_include.h" + +int hp_sw_prio(const char *dev) +{ + unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; + unsigned char sb[128]; + struct sg_io_hdr io_hdr; + int ret = HP_PATH_FAILED; + int fd; + + fd = open(dev, O_RDWR|O_NONBLOCK); + + if (fd <= 0) { + fprintf(stderr, "Opening the device failed.\n"); + goto out; + } + + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof (turCmdBlk); + io_hdr.mx_sb_len = sizeof (sb); + io_hdr.dxfer_direction = SG_DXFER_NONE; + io_hdr.cmdp = turCmdBlk; + io_hdr.sbp = sb; + io_hdr.timeout = 60000; + io_hdr.pack_id = 0; + retry: + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + fprintf(stderr, "sending tur command failed\n"); + goto out; + } + io_hdr.status &= 0x7e; + if ((0 == io_hdr.status) && (0 == io_hdr.host_status) && + (0 == io_hdr.driver_status)) { + /* Command completed normally, path is active */ + ret = HP_PATH_ACTIVE; + } + + if ((SCSI_CHECK_CONDITION == io_hdr.status) || + (SCSI_COMMAND_TERMINATED == io_hdr.status) || + (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) { + if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) { + int sense_key, asc, asq; + unsigned char * sense_buffer = io_hdr.sbp; + if (sense_buffer[0] & 0x2) { + sense_key = sense_buffer[1] & 0xf; + asc = sense_buffer[2]; + asq = sense_buffer[3]; + } else { + sense_key = sense_buffer[2] & 0xf; + asc = sense_buffer[12]; + asq = sense_buffer[13]; + } + if(RECOVERED_ERROR == sense_key) + ret = HP_PATH_ACTIVE; + if(NOT_READY == sense_key) { + if (asc == 0x04 && asq == 0x02) { + /* This is a standby path */ + ret = HP_PATH_STANDBY; + } + } + if(UNIT_ATTENTION == sense_key) { + if (asc == 0x29) { + /* Retry for device reset */ + goto retry; + } + } + } + } + + close(fd); + +out: + return(ret); +} + +int +main (int argc, char **argv) +{ + int prio; + if (argc != 2) { + fprintf(stderr, "Arguments wrong!\n"); + prio = 0; + } else + prio = hp_sw_prio(argv[1]); + + printf("%d\n", prio); + exit(0); +} +