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 <bmarz...@redhat.com>
---
 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


Reply via email to