pathinfo() shouldn't call any of the DI_IOCTL functions if path_state is not PATH_UP (It only actually checked this for scsi_ioctl_pathinfo). But since pathinfo() is rarely called with the DI_IOCTL flag, this information might never be gathered if a path is added, and pathinfo is first called, while it's offline. Make paths remember if they skipped the DI_IOCTL calls because the path was offline, and try again on future pathinfo() calls that don't set DI_NOIO. Also make dm_setgeometry check all paths, since it's possible that set_geometry() was skipped (in the past, the ioctls would just fail for the offline device, with the same result). Signed-off-by: Benjamin Marzinski <bmarzins@xxxxxxxxxx> --- libmultipath/devmapper.c | 22 ++++++++++++++-------- libmultipath/discovery.c | 24 ++++++++++++------------ libmultipath/structs.h | 7 +++++++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c index 55052cf5..8e632ba8 100644 --- a/libmultipath/devmapper.c +++ b/libmultipath/devmapper.c @@ -1704,7 +1704,10 @@ int dm_reassign(const char *mapname) int dm_setgeometry(struct multipath *mpp) { struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL; + struct pathgroup *pgp; struct path *pp; + int i, j; + bool found = false; char heads[4], sectors[4]; char cylinders[10], start[32]; int r = 0; @@ -1712,15 +1715,18 @@ int dm_setgeometry(struct multipath *mpp) if (!mpp) return 1; - pp = first_path(mpp); - if (!pp) { - condlog(3, "%s: no path for geometry", mpp->alias); - return 1; + vector_foreach_slot (mpp->pg, pgp, i) { + vector_foreach_slot (pgp->paths, pp, j) { + if (pp->geom.cylinders != 0 && + pp->geom.heads != 0 && + pp->geom.sectors != 0) { + found = true; + break; + } + } } - if (pp->geom.cylinders == 0 || - pp->geom.heads == 0 || - pp->geom.sectors == 0) { - condlog(3, "%s: invalid geometry on %s", mpp->alias, pp->dev); + if (!found) { + condlog(3, "%s: no path with valid geometry", mpp->alias); return 1; } diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 8a780d69..2015a32f 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1908,13 +1908,10 @@ sysfs_pathinfo(struct path *pp, const struct vector_s *hwtable) } static void -scsi_ioctl_pathinfo (struct path * pp, int mask) +scsi_ioctl_pathinfo (struct path * pp) { int vpd_id; - if (!(mask & DI_IOCTL)) - return; - select_vpd_vendor_id(pp); vpd_id = pp->vpd_vendor_id; @@ -2433,14 +2430,17 @@ int pathinfo(struct path *pp, struct config *conf, int mask) goto blank; } - if (mask & DI_IOCTL) - get_geometry(pp); - - if (path_state == PATH_UP && pp->bus == SYSFS_BUS_SCSI) - scsi_ioctl_pathinfo(pp, mask); - - if (pp->bus == SYSFS_BUS_CCISS && mask & DI_IOCTL) - cciss_ioctl_pathinfo(pp); + if (mask & DI_IOCTL || pp->ioctl_info == IOCTL_INFO_SKIPPED) { + if (path_state == PATH_UP) { + get_geometry(pp); + if (pp->bus == SYSFS_BUS_SCSI) + scsi_ioctl_pathinfo(pp); + else if (pp->bus == SYSFS_BUS_CCISS) + cciss_ioctl_pathinfo(pp); + pp->ioctl_info = IOCTL_INFO_COMPLETED; + } else if (pp->ioctl_info == IOCTL_INFO_NOT_REQUESTED) + pp->ioctl_info = IOCTL_INFO_SKIPPED; + } if (mask & DI_CHECKER) { if (path_state == PATH_UP) { diff --git a/libmultipath/structs.h b/libmultipath/structs.h index 1b5a878b..28de9a7f 100644 --- a/libmultipath/structs.h +++ b/libmultipath/structs.h @@ -353,6 +353,12 @@ struct hd_geometry { #define GROUP_ID_UNDEF -1 +enum ioctl_info_states { + IOCTL_INFO_NOT_REQUESTED = 0, + IOCTL_INFO_SKIPPED, + IOCTL_INFO_COMPLETED, +}; + struct path { char dev[FILE_NAME_SIZE]; char dev_t[BLK_DEV_SIZE]; @@ -412,6 +418,7 @@ struct path { vector hwe; struct gen_path generic_path; int tpg_id; + enum ioctl_info_states ioctl_info; }; typedef int (pgpolicyfn) (struct multipath *, vector); -- 2.46.2