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
|
/*
* 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 <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sg_include.h>
#include <debug.h>
#include "libprio.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
#define pp_hp_sw_log(prio, fmt, args...) \
condlog(prio, "%s: hp_sw prio: " fmt, dev, ##args)
int hp_sw_prio(const char *dev, int fd)
{
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;
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) {
pp_hp_sw_log(0, "sending tur command failed");
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;
}
}
}
}
out:
return(ret);
}
int getprio (struct path * pp)
{
return hp_sw_prio(pp->dev, pp->fd);
}
|