152 lines
4.0 KiB
Diff
152 lines
4.0 KiB
Diff
|
---
|
||
|
libmultipath/checkers/rdac.c | 92 ++++++++++++++++++++++++++++++++++++++-
|
||
|
libmultipath/prioritizers/rdac.c | 4 +
|
||
|
2 files changed, 95 insertions(+), 1 deletion(-)
|
||
|
|
||
|
Index: multipath-tools/libmultipath/checkers/rdac.c
|
||
|
===================================================================
|
||
|
--- multipath-tools.orig/libmultipath/checkers/rdac.c
|
||
|
+++ multipath-tools/libmultipath/checkers/rdac.c
|
||
|
@@ -12,27 +12,113 @@
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include "checkers.h"
|
||
|
+#include "debug.h"
|
||
|
|
||
|
#include "../libmultipath/sg_include.h"
|
||
|
|
||
|
#define INQUIRY_CMDLEN 6
|
||
|
#define INQUIRY_CMD 0x12
|
||
|
+#define MODE_SENSE_CMD 0x5a
|
||
|
+#define MODE_SELECT_CMD 0x55
|
||
|
+#define MODE_SEN_SEL_CMDLEN 10
|
||
|
#define SENSE_BUFF_LEN 32
|
||
|
#define SCSI_CHECK_CONDITION 0x2
|
||
|
#define SCSI_COMMAND_TERMINATED 0x22
|
||
|
#define SG_ERR_DRIVER_SENSE 0x08
|
||
|
#define RECOVERED_ERROR 0x01
|
||
|
|
||
|
+
|
||
|
+#define CURRENT_PAGE_CODE_VALUES 0
|
||
|
+#define CHANGEABLE_PAGE_CODE_VALUES 1
|
||
|
+
|
||
|
#define MSG_RDAC_UP "rdac checker reports path is up"
|
||
|
#define MSG_RDAC_DOWN "rdac checker reports path is down"
|
||
|
#define MSG_RDAC_GHOST "rdac checker reports path is ghost"
|
||
|
|
||
|
+struct control_mode_page {
|
||
|
+ unsigned char header[8];
|
||
|
+ unsigned char page_code;
|
||
|
+ unsigned char page_len;
|
||
|
+ unsigned char dontcare0[3];
|
||
|
+ unsigned char tas_bit;
|
||
|
+ unsigned char dontcare1[6];
|
||
|
+};
|
||
|
+
|
||
|
struct rdac_checker_context {
|
||
|
void * dummy;
|
||
|
};
|
||
|
|
||
|
int libcheck_init (struct checker * c)
|
||
|
{
|
||
|
+ unsigned char cmd[MODE_SEN_SEL_CMDLEN];
|
||
|
+ unsigned char sense_b[SENSE_BUFF_LEN];
|
||
|
+ struct sg_io_hdr io_hdr;
|
||
|
+ struct control_mode_page current, changeable;
|
||
|
+ int set = 0;
|
||
|
+
|
||
|
+ memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
|
||
|
+ cmd[0] = MODE_SENSE_CMD;
|
||
|
+ cmd[1] = 0x08; /* DBD bit on */
|
||
|
+ cmd[2] = 0xA + (CURRENT_PAGE_CODE_VALUES << 6);
|
||
|
+ cmd[8] = (sizeof(struct control_mode_page) & 0xff);
|
||
|
+
|
||
|
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
|
||
|
+ memset(sense_b, 0, SENSE_BUFF_LEN);
|
||
|
+ memset(¤t, 0, sizeof(struct control_mode_page));
|
||
|
+
|
||
|
+ io_hdr.interface_id = 'S';
|
||
|
+ io_hdr.cmd_len = MODE_SEN_SEL_CMDLEN;
|
||
|
+ io_hdr.mx_sb_len = sizeof(sense_b);
|
||
|
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||
|
+ io_hdr.dxfer_len = (sizeof(struct control_mode_page) & 0xff);
|
||
|
+ io_hdr.dxferp = ¤t;
|
||
|
+ io_hdr.cmdp = cmd;
|
||
|
+ io_hdr.sbp = sense_b;
|
||
|
+ io_hdr.timeout = c->timeout;
|
||
|
+
|
||
|
+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ /* check the TAS bit to see if it is already set */
|
||
|
+ if ((current.tas_bit >> 6) & 0x1) {
|
||
|
+ set = 1;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* get the changeble values */
|
||
|
+ cmd[2] = 0xA + (CHANGEABLE_PAGE_CODE_VALUES << 6);
|
||
|
+ io_hdr.dxferp = &changeable;
|
||
|
+ memset(&changeable, 0, sizeof(struct control_mode_page));
|
||
|
+
|
||
|
+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ /* if TAS bit is not settable exit */
|
||
|
+ if (((changeable.tas_bit >> 6) & 0x1) == 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ /* Now go ahead and set it */
|
||
|
+ memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
|
||
|
+ cmd[0] = MODE_SELECT_CMD;
|
||
|
+ cmd[1] = 0x1; /* set SP bit on */
|
||
|
+ cmd[8] = (sizeof(struct control_mode_page) & 0xff);
|
||
|
+
|
||
|
+ /* use the same buffer as current, only set the tas bit */
|
||
|
+ current.page_code = 0xA;
|
||
|
+ current.page_len = 0xA;
|
||
|
+ current.tas_bit |= (1 << 6);
|
||
|
+
|
||
|
+ io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
|
||
|
+ io_hdr.dxferp = ¤t;
|
||
|
+
|
||
|
+ if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ /* Success */
|
||
|
+ set = 1;
|
||
|
+out:
|
||
|
+ if (set == 0)
|
||
|
+ condlog(0, "rdac checker failed to set TAS bit");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -132,7 +218,11 @@ libcheck_check (struct checker * c)
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
- ret = ((inq.avtcvp & 0x1) ? PATH_UP : PATH_GHOST);
|
||
|
+ /* If owner set or ioship mode is enabled return PATH_UP always */
|
||
|
+ if ((inq.avtcvp & 0x1) || ((inq.avtcvp >> 5) & 0x1))
|
||
|
+ ret = PATH_UP;
|
||
|
+ else
|
||
|
+ ret = PATH_GHOST;
|
||
|
|
||
|
done:
|
||
|
switch (ret) {
|
||
|
Index: multipath-tools/libmultipath/prioritizers/rdac.c
|
||
|
===================================================================
|
||
|
--- multipath-tools.orig/libmultipath/prioritizers/rdac.c
|
||
|
+++ multipath-tools/libmultipath/prioritizers/rdac.c
|
||
|
@@ -81,6 +81,10 @@ int rdac_prio(const char *dev, int fd)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
+ /* For ioship mode set the bit 3 (00001000) */
|
||
|
+ if ((sense_buffer[8] >> 5) & 0x01)
|
||
|
+ ret |= 0x08;
|
||
|
+
|
||
|
out:
|
||
|
return(ret);
|
||
|
}
|