@@ -871,6 +871,10 @@ get_serial (char * str, int maxlen, int fd)
return 1;
}
+/*
+ * Side effect: sets pp->tpgs if it could be determined.
+ * If ALUA calls fail because paths are unreachable, pp->tpgs remains unchanged.
+ */
static void
detect_alua(struct path * pp)
{
@@ -881,12 +885,28 @@ detect_alua(struct path * pp)
if (sysfs_get_timeout(pp, &timeout) <= 0)
timeout = DEF_TIMEOUT;
- if ((tpgs = get_target_port_group_support(pp, timeout)) <= 0) {
+ tpgs = get_target_port_group_support(pp, timeout);
+ if (tpgs == -RTPG_INQUIRY_FAILED)
+ return;
+ else if (tpgs <= 0) {
pp->tpgs = TPGS_NONE;
return;
}
+
+ if (pp->fd == -1 || pp->offline)
+ return;
+
ret = get_target_port_group(pp, timeout);
if (ret < 0 || get_asymmetric_access_state(pp, ret, timeout) < 0) {
+ int state;
+
+ if (ret == -RTPG_INQUIRY_FAILED)
+ return;
+
+ state = path_offline(pp);
+ if (state == PATH_DOWN || state == PATH_PENDING)
+ return;
+
pp->tpgs = TPGS_NONE;
return;
}
@@ -432,12 +432,26 @@ int select_hwhandler(struct config *conf, struct multipath *mp)
static const char tpgs_origin[]= "(setting: autodetected from TPGS)";
char *dh_state;
int i;
- bool all_tpgs = true;
+ bool all_tpgs = true, one_tpgs = false;
dh_state = &handler[2];
- vector_foreach_slot(mp->paths, pp, i)
- all_tpgs = all_tpgs && (path_get_tpgs(pp) > 0);
+ /*
+ * TPGS_UNDEF means that ALUA support couldn't determined either way
+ * yet, probably because the path was always down.
+ * If at least one path does have TPGS support, and no path has
+ * TPGS_NONE, assume that TPGS would be supported by all paths if
+ * all were up.
+ */
+ vector_foreach_slot(mp->paths, pp, i) {
+ int tpgs = path_get_tpgs(pp);
+
+ all_tpgs = all_tpgs && tpgs != TPGS_NONE;
+ one_tpgs = one_tpgs ||
+ (tpgs != TPGS_NONE && tpgs != TPGS_UNDEF);
+ }
+ all_tpgs = all_tpgs && one_tpgs;
+
if (mp->retain_hwhandler != RETAIN_HWHANDLER_OFF) {
vector_foreach_slot(mp->paths, pp, i) {
if (get_dh_state(pp, dh_state, sizeof(handler) - 2) > 0