The 'normal' SG_IO tur checker has some issues with cciss, so we'd better use a dedicated path checker here. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- libmultipath/checkers.h | 1 + libmultipath/checkers/Makefile | 1 + libmultipath/checkers/cciss.h | 142 +++++++++++++++++++++++++++++++++++++ libmultipath/checkers/cciss_tur.c | 137 +++++++++++++++++++++++++++++++++++ 4 files changed, 281 insertions(+), 0 deletions(-) create mode 100644 libmultipath/checkers/cciss.h create mode 100644 libmultipath/checkers/cciss_tur.c diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h index 93337f1..4ff475d 100644 --- a/libmultipath/checkers.h +++ b/libmultipath/checkers.h @@ -61,6 +61,7 @@ #define RDAC "rdac" #define EMC_CLARIION "emc_clariion" #define READSECTOR0 "readsector0" +#define CCISS_TUR "cciss_tur" #define DEFAULT_CHECKER DIRECTIO diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile index f37a0f9..9b517f2 100644 --- a/libmultipath/checkers/Makefile +++ b/libmultipath/checkers/Makefile @@ -5,6 +5,7 @@ include ../../Makefile.inc LIBS= \ + libcheckcciss_tur.so \ libcheckreadsector0.so \ libchecktur.so \ libcheckdirectio.so \ diff --git a/libmultipath/checkers/cciss.h b/libmultipath/checkers/cciss.h new file mode 100644 index 0000000..f6a37d8 --- /dev/null +++ b/libmultipath/checkers/cciss.h @@ -0,0 +1,142 @@ +#ifndef CCISS_H +#define CCISS_H + +#include <linux/types.h> +#include <linux/ioctl.h> + +#define CCISS_IOC_MAGIC 'B' + +/* + * transfer direction + */ +#define XFER_NONE 0x00 +#define XFER_WRITE 0x01 +#define XFER_READ 0x02 +#define XFER_RSVD 0x03 + +/* + * task attribute + */ +#define ATTR_UNTAGGED 0x00 +#define ATTR_SIMPLE 0x04 +#define ATTR_HEADOFQUEUE 0x05 +#define ATTR_ORDERED 0x06 +#define ATTR_ACA 0x07 + +/* + * cdb type + */ +#define TYPE_CMD 0x00 +#define TYPE_MSG 0x01 + +#define SENSEINFOBYTES 32 + +/* + * Type defs used in the following structs + */ +#define BYTE __u8 +#define WORD __u16 +#define HWORD __u16 +#define DWORD __u32 + +#pragma pack(1) + +//Command List Structure +typedef union _SCSI3Addr_struct { + struct { + BYTE Dev; + BYTE Bus:6; + BYTE Mode:2; // b00 + } PeripDev; + struct { + BYTE DevLSB; + BYTE DevMSB:6; + BYTE Mode:2; // b01 + } LogDev; + struct { + BYTE Dev:5; + BYTE Bus:3; + BYTE Targ:6; + BYTE Mode:2; // b10 + } LogUnit; +} SCSI3Addr_struct; + +typedef struct _PhysDevAddr_struct { + DWORD TargetId:24; + DWORD Bus:6; + DWORD Mode:2; + SCSI3Addr_struct Target[2]; //2 level target device addr +} PhysDevAddr_struct; + +typedef struct _LogDevAddr_struct { + DWORD VolId:30; + DWORD Mode:2; + BYTE reserved[4]; +} LogDevAddr_struct; + +typedef union _LUNAddr_struct { + BYTE LunAddrBytes[8]; + SCSI3Addr_struct SCSI3Lun[4]; + PhysDevAddr_struct PhysDev; + LogDevAddr_struct LogDev; +} LUNAddr_struct; + +typedef struct _RequestBlock_struct { + BYTE CDBLen; + struct { + BYTE Type:3; + BYTE Attribute:3; + BYTE Direction:2; + } Type; + HWORD Timeout; + BYTE CDB[16]; +} RequestBlock_struct; + +typedef union _MoreErrInfo_struct{ + struct { + BYTE Reserved[3]; + BYTE Type; + DWORD ErrorInfo; + }Common_Info; + struct{ + BYTE Reserved[2]; + BYTE offense_size;//size of offending entry + BYTE offense_num; //byte # of offense 0-base + DWORD offense_value; + }Invalid_Cmd; +}MoreErrInfo_struct; + +typedef struct _ErrorInfo_struct { + BYTE ScsiStatus; + BYTE SenseLen; + HWORD CommandStatus; + DWORD ResidualCnt; + MoreErrInfo_struct MoreErrInfo; + BYTE SenseInfo[SENSEINFOBYTES]; +} ErrorInfo_struct; + +#pragma pack() + +typedef struct _IOCTL_Command_struct { + LUNAddr_struct LUN_info; + RequestBlock_struct Request; + ErrorInfo_struct error_info; + WORD buf_size; /* size in bytes of the buf */ + BYTE *buf; +} IOCTL_Command_struct; + +typedef struct _LogvolInfo_struct{ + __u32 LunID; + int num_opens; /* number of opens on the logical volume */ + int num_parts; /* number of partitions configured on logvol */ +} LogvolInfo_struct; + +#define CCISS_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 11, IOCTL_Command_struct) +#define CCISS_GETLUNINFO _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct) + +int cciss_init( struct checker *); +void cciss_free (struct checker * c); +int cciss_tur( struct checker *); + +#endif + diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c new file mode 100644 index 0000000..4c26901 --- /dev/null +++ b/libmultipath/checkers/cciss_tur.c @@ -0,0 +1,137 @@ +/* + ***************************************************************************** + * * + * (C) Copyright 2007 Hewlett-Packard Development Company, L.P * + * * + * 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., * + * 675 Mass Ave, Cambridge, MA 02139, USA. * + * * + * The copy of the GNU General Public License is available at * + * /opt/hp/HPDMmultipath-tool directoy * + * * + ***************************************************************************** +*/ + +/* + * This program originally derived from and inspired by + * Christophe Varoqui's tur.c, part of libchecker. + */ + + +#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> + +#include "checkers.h" + +#include "cciss.h" + +#define TUR_CMD_LEN 6 +#define HEAVY_CHECK_COUNT 10 + +#define MSG_CCISS_TUR_UP "cciss_tur checker reports path is up" +#define MSG_CCISS_TUR_DOWN "cciss_tur checker reports path is down" + +struct cciss_tur_checker_context { + void * dummy; +}; + +int libcheck_init (struct checker * c) +{ + return 0; +} + +void libcheck_free (struct checker * c) +{ + return; +} + +extern int +libcheck_check (struct checker * c) +{ + int rc; + int ret; + unsigned int lun = 0; + struct cciss_tur_checker_context * ctxt = NULL; + LogvolInfo_struct lvi; // logical "volume" info + IOCTL_Command_struct cic; // cciss ioctl command + + if ((c->fd) <= 0) { + MSG(c,"no usable fd"); + ret = -1; + goto out; + } + + rc = ioctl(c->fd, CCISS_GETLUNINFO, &lvi); + if ( rc != 0) { + perror("Error: "); + fprintf(stderr, "cciss TUR failed in CCISS_GETLUNINFO: %s\n", + strerror(errno)); + MSG(c,MSG_CCISS_TUR_DOWN); + ret = PATH_DOWN; + goto out; + } else { + lun = lvi.LunID; + } + + memset(&cic, 0, sizeof(cic)); + cic.LUN_info.LogDev.VolId = lun & 0x3FFFFFFF; + cic.LUN_info.LogDev.Mode = 0x01; /* logical volume addressing */ + cic.Request.CDBLen = 6; /* need to try just 2 bytes here */ + cic.Request.Type.Type = TYPE_CMD; // It is a command. + cic.Request.Type.Attribute = ATTR_SIMPLE; + cic.Request.Type.Direction = XFER_NONE; + cic.Request.Timeout = 0; + + cic.Request.CDB[0] = 0; + cic.Request.CDB[1] = 0; + cic.Request.CDB[2] = 0; + cic.Request.CDB[3] = 0; + cic.Request.CDB[4] = 0; + cic.Request.CDB[5] = 0; + + rc = ioctl(c->fd, CCISS_PASSTHRU, &cic); + if (rc < 0) { + fprintf(stderr, "cciss TUR failed: %s\n", + strerror(errno)); + MSG(c,MSG_CCISS_TUR_DOWN); + ret = PATH_DOWN; + goto out; + } + + if ((cic.error_info.CommandStatus | cic.error_info.ScsiStatus )) { + MSG(c,MSG_CCISS_TUR_DOWN); + ret = PATH_DOWN; + goto out; + } + + MSG(c,MSG_CCISS_TUR_UP); + + ret = PATH_UP; +out: + /* + * caller told us he doesn't want to keep the context : + * free it + */ + if (!c->context) + free(ctxt); + + return(ret); +} -- 1.5.2.4 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel