@@ -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;
}
@@ -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) {
@@ -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);
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@redhat.com> --- libmultipath/devmapper.c | 22 ++++++++++++++-------- libmultipath/discovery.c | 24 ++++++++++++------------ libmultipath/structs.h | 7 +++++++ 3 files changed, 33 insertions(+), 20 deletions(-)