summaryrefslogtreecommitdiffstats
path: root/0096-RHBZ-683616-ioship-support.patch
blob: 42383b51d07b0d7a89f356df3e58eec5d5c66a7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
---
 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(&current, 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 = &current;
+	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 = &current;
+
+	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);
 }