@@ -23,6 +23,11 @@
#define MSG_TUR_UP "tur checker reports path is up"
#define MSG_TUR_DOWN "tur checker reports path is down"
+/* from linux/include/scsi/scsi.h */
+#define DID_BUS_BUSY 0x02
+#define DID_ERROR 0x07
+#define DID_TRANSPORT_DISRUPTED 0x0e
+
struct tur_checker_context {
void * dummy;
};
@@ -62,6 +67,12 @@
if (io_hdr.info & SG_INFO_OK_MASK) {
int key = 0, asc, ascq;
+ if (io_hdr.host_status == DID_BUS_BUSY ||
+ io_hdr.host_status == DID_ERROR ||
+ io_hdr.host_status == DID_TRANSPORT_DISRUPTED) {
+ if (--retry_tur)
+ goto retry;
+ }
if (io_hdr.sb_len_wr > 3) {
if (io_hdr.sbp[0] == 0x72 || io_hdr.sbp[0] == 0x73) {
key = io_hdr.sbp[1] & 0x0f;
@@ -235,6 +235,7 @@
declare_sysfs_get_str(rev, "%s/block/%s/device/rev");
declare_sysfs_get_str(dev, "%s/block/%s/dev");
declare_sysfs_get_str(bustype, "%s/block/%s/device/bus");
+declare_sysfs_get_str(state, "%s/block/%s/device/state");
int
sysfs_get_size (char * sysfs_path, char * dev, unsigned long long * size)
@@ -30,7 +30,7 @@
int sysfs_get_rev (char * sysfs_path, char * dev, char * buff, int len);
int sysfs_get_dev (char * sysfs_path, char * dev, char * buff, int len);
int sysfs_get_bustype (char * sysfs_path, char * dev, char * buff, int len);
-
+int sysfs_get_state (char * sysfs_path, char * dev, char * buff, int len);
int sysfs_get_size (char * sysfs_path, char * dev, unsigned long long *);
int path_discovery (vector pathvec, struct config * conf, int flag);
@@ -907,6 +907,22 @@
}
}
+int
+check_sysfs_state (struct path *pp, int *newstate)
+{
+ char state[32];
+ if (pp->bus != SYSFS_BUS_SCSI)
+ return 0;
+ if (sysfs_get_state(sysfs_path, pp->dev, state, 32) != 0)
+ return 0;
+ condlog(3, "%s: state = %s", pp->dev, state);
+ if (strncmp(state, "blocked", 7) == 0){
+ *newstate = PATH_PENDING;
+ return 1;
+ }
+ return 0;
+}
+
static void *
checkerloop (void *ap)
{
@@ -963,7 +979,8 @@
*/
checker_set_async(&pp->checker);
- newstate = checker_check(&pp->checker);
+ if (check_sysfs_state(pp, &newstate) == 0)
+ newstate = checker_check(&pp->checker);
if (newstate < 0) {
condlog(2, "%s: unusable path", pp->dev);
@@ -268,7 +268,7 @@
}
rc = do_rtpg(fd, buf, buflen);
if (rc < 0)
- return rc;
+ goto out;
scsi_buflen = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
if (buflen < (scsi_buflen + 4)) {
free(buf);