diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index eb1e735..01aadba 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1266,6 +1266,31 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff) return buff_len; } +/* heavily based on sg_inq.c from sg3_utils */ +bool +is_vpd_page_supported(int fd, int pg) +{ + int i, len, buff_len; + unsigned char buff[4096]; + + buff_len = fetch_vpd_page(fd, 0x00, buff); + if (buff_len < 0) + return false; + if (buff_len < 4) { + condlog(3, "VPD page 00h too short"); + return false; + } + + len = buff[3] + 4; + if (len > buff_len) + condlog(3, "vpd page 00h trucated, expected %d, have %d", + len, buff_len); + for (i = 4; i < len; ++i) + if (buff[i] == pg) + return true; + return false; +} + int get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen) { diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h index 6444887..d3193da 100644 --- a/libmultipath/discovery.h +++ b/libmultipath/discovery.h @@ -56,6 +56,7 @@ int sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen); int get_uid(struct path * pp, int path_state, struct udev_device *udev, int allow_fallback); +bool is_vpd_page_supported(int fd, int pg); /* * discovery bitmask diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index d362beb..d7febec 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -496,13 +496,15 @@ check_rdac(struct path * pp) { int len; char buff[44]; - const char *checker_name; + const char *checker_name = NULL; if (pp->bus != SYSFS_BUS_SCSI) return 0; - /* Avoid ioctl if this is likely not an RDAC array */ - if (__do_set_from_hwe(checker_name, pp, checker_name) && - strcmp(checker_name, RDAC)) + /* Avoid checking 0xc9 if this is likely not an RDAC array */ + if (!__do_set_from_hwe(checker_name, pp, checker_name) && + !is_vpd_page_supported(pp->fd, 0xC9)) + return 0; + if (checker_name && strcmp(checker_name, RDAC)) return 0; len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44); if (len <= 0)