Skip to content

Commit 70addc2

Browse files
bmarzinsmwilck
authored andcommitted
multipathd: finish initalization of paths added while offline
If a path in a mulitpath device is offline while multipathd is reconfigured, it will get added to the updated multipath device, just like it was in the old multipath device. However the device will still be in the INIT_NEW state because it can't get initilized while offline. This is different than the INIT_PARTIAL state because the path was discovered in path_discovery(). INIT_PARTIAL is for paths that multipathd did not discover in path_discovery() or receive a uevent for, but are part of a multipath device that was added, and which should receive a uevent shortly. There is no reason to expect a uevent for these offline paths. When the path comes back online, multipathd will run the checker and prioritizer on it. The only two pathinfo checks that won't happen are the DI_WWID and DI_IOCTL ones. Modify pathinfo() to make sure that if DI_IOCTL was skipped for offline paths, it gets called the next time pathinfo() is called after the fd can be opened. Also, make sure that when one of these offline paths becomes usable, its WWID is rechecked. With those changes, all the DI_ALL checks will be accounted for, and the path can be marked INIT_OK. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Reviewed-by: Martin Wilck <mwilck@suse.com> (cherry picked from commit 1942fb1)
1 parent b19582e commit 70addc2

2 files changed

Lines changed: 49 additions & 7 deletions

File tree

libmultipath/discovery.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
25592559
* Recoverable error, for example faulty or offline path
25602560
*/
25612561
pp->chkrstate = pp->state = PATH_DOWN;
2562+
if (mask & DI_IOCTL && pp->ioctl_info == IOCTL_INFO_NOT_REQUESTED)
2563+
pp->ioctl_info = IOCTL_INFO_SKIPPED;
25622564
if (pp->initialized == INIT_NEW || pp->initialized == INIT_FAILED)
25632565
memset(pp->wwid, 0, WWID_SIZE);
25642566

multipathd/main.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,6 +2545,26 @@ sync_mpp(struct vectors * vecs, struct multipath *mpp, unsigned int ticks)
25452545
return do_sync_mpp(vecs, mpp);
25462546
}
25472547

2548+
/*
2549+
* pp->wwid should never be empty when this function is called, but if it
2550+
* is, this function can set it.
2551+
*/
2552+
static bool new_path_wwid_changed(struct path *pp, int state)
2553+
{
2554+
char wwid[WWID_SIZE];
2555+
2556+
strlcpy(wwid, pp->wwid, WWID_SIZE);
2557+
if (get_uid(pp, state, pp->udev, 1) != 0) {
2558+
strlcpy(pp->wwid, wwid, WWID_SIZE);
2559+
return false;
2560+
}
2561+
if (strlen(wwid) && strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
2562+
strlcpy(pp->wwid, wwid, WWID_SIZE);
2563+
return true;
2564+
}
2565+
return false;
2566+
}
2567+
25482568
static int
25492569
update_path_state (struct vectors * vecs, struct path * pp)
25502570
{
@@ -2573,14 +2593,34 @@ update_path_state (struct vectors * vecs, struct path * pp)
25732593
pp->tick = 1;
25742594
return CHECK_PATH_SKIPPED;
25752595
}
2576-
if (pp->recheck_wwid == RECHECK_WWID_ON &&
2577-
(newstate == PATH_UP || newstate == PATH_GHOST) &&
2596+
2597+
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
25782598
((pp->state != PATH_UP && pp->state != PATH_GHOST) ||
2579-
pp->dmstate == PSTATE_FAILED) &&
2580-
check_path_wwid_change(pp)) {
2581-
condlog(0, "%s: path wwid change detected. Removing", pp->dev);
2582-
return handle_path_wwid_change(pp, vecs)? CHECK_PATH_REMOVED :
2583-
CHECK_PATH_SKIPPED;
2599+
pp->dmstate == PSTATE_FAILED)) {
2600+
bool wwid_changed = false;
2601+
2602+
if (pp->initialized == INIT_NEW) {
2603+
/*
2604+
* Path was added to map while offline, mark it as
2605+
* initialized.
2606+
* DI_SYSFS was checked when the path was added
2607+
* DI_IOCTL was checked when the checker was selected
2608+
* DI_CHECKER just got checked
2609+
* DI_WWID is about to be checked
2610+
* DI_PRIO will get checked at the end of this checker
2611+
* loop
2612+
*/
2613+
pp->initialized = INIT_OK;
2614+
wwid_changed = new_path_wwid_changed(pp, newstate);
2615+
} else if (pp->recheck_wwid == RECHECK_WWID_ON)
2616+
wwid_changed = check_path_wwid_change(pp);
2617+
if (wwid_changed) {
2618+
condlog(0, "%s: path wwid change detected. Removing",
2619+
pp->dev);
2620+
return handle_path_wwid_change(pp, vecs)
2621+
? CHECK_PATH_REMOVED
2622+
: CHECK_PATH_SKIPPED;
2623+
}
25842624
}
25852625
if ((newstate != PATH_UP && newstate != PATH_GHOST &&
25862626
newstate != PATH_PENDING) && (pp->state == PATH_DELAYED)) {

0 commit comments

Comments
 (0)