10 #include "structs_vec.h"
12 #include "devmapper.h"
17 #include "discovery.h"
21 * creates or updates mpp->paths reading mpp->pg
24 update_mpp_paths(struct multipath * mpp, vector pathvec)
26 struct pathgroup * pgp;
34 !(mpp->paths = vector_alloc()))
37 vector_foreach_slot (mpp->pg, pgp, i) {
38 vector_foreach_slot (pgp->paths, pp, j) {
39 if (!find_path_by_devt(mpp->paths, pp->dev_t) &&
40 (find_path_by_devt(pathvec, pp->dev_t)) &&
41 store_path(mpp->paths, pp))
49 adopt_paths (vector pathvec, struct multipath * mpp, int get_info)
57 if (update_mpp_paths(mpp, pathvec))
60 vector_foreach_slot (pathvec, pp, i) {
61 if (!strncmp(mpp->wwid, pp->wwid, WWID_SIZE)) {
62 condlog(3, "%s: ownership set to %s",
66 if (!mpp->paths && !(mpp->paths = vector_alloc()))
69 if (!find_path_by_dev(mpp->paths, pp->dev) &&
70 store_path(mpp->paths, pp))
73 pathinfo(pp, conf->hwtable,
74 DI_PRIO | DI_CHECKER);
81 orphan_path (struct path * pp)
84 pp->dmstate = PSTATE_UNDEF;
85 pp->uid_attribute = NULL;
87 checker_put(&pp->checker);
94 orphan_paths (vector pathvec, struct multipath * mpp)
99 vector_foreach_slot (pathvec, pp, i) {
100 if (pp->mpp == mpp) {
101 condlog(4, "%s: orphaned", pp->dev);
108 set_multipath_wwid (struct multipath * mpp)
113 dm_get_uuid(mpp->alias, mpp->wwid);
116 #define KEEP_WAITER 0
117 #define STOP_WAITER 1
121 _remove_map (struct multipath * mpp, struct vectors * vecs,
122 int stop_waiter, int purge_vec)
126 condlog(4, "%s: remove multipath map", mpp->alias);
129 * stop the DM event waiter thread
132 stop_waiter_thread(mpp, vecs);
135 * clear references to this map
137 orphan_paths(vecs->pathvec, mpp);
140 (i = find_slot(vecs->mpvec, (void *)mpp)) != -1)
141 vector_del_slot(vecs->mpvec, i);
146 free_multipath(mpp, KEEP_PATHS);
150 remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec)
152 _remove_map(mpp, vecs, KEEP_WAITER, purge_vec);
156 remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs,
159 _remove_map(mpp, vecs, STOP_WAITER, purge_vec);
163 _remove_maps (struct vectors * vecs, int stop_waiter)
166 struct multipath * mpp;
171 vector_foreach_slot (vecs->mpvec, mpp, i) {
172 _remove_map(mpp, vecs, stop_waiter, 1);
176 vector_free(vecs->mpvec);
181 remove_maps (struct vectors * vecs)
183 _remove_maps(vecs, KEEP_WAITER);
187 remove_maps_and_stop_waiters (struct vectors * vecs)
189 _remove_maps(vecs, STOP_WAITER);
192 static struct hwentry *
193 extract_hwe_from_path(struct multipath * mpp)
195 struct path * pp = NULL;
196 int pg_num = -1, p_num = -1, i;
197 struct pathgroup * pgp = NULL;
199 condlog(3, "%s: searching paths for valid hwe", mpp->alias);
201 if (mpp && mpp->pg) {
202 vector_foreach_slot(mpp->pg, pgp, i) {
203 if (pgp->status == PGSTATE_ACTIVE ||
204 pgp->status == PGSTATE_ENABLED) {
210 pgp = VECTOR_SLOT(mpp->pg, pg_num);
213 if (pgp && pgp->paths) {
214 vector_foreach_slot(pgp->paths, pp, i) {
215 if (pp->dmstate == PSTATE_FAILED)
217 if (strlen(pp->vendor_id) > 0 &&
218 strlen(pp->product_id) > 0 &&
219 strlen(pp->rev) > 0) {
225 pp = VECTOR_SLOT(pgp->paths, i);
229 condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
230 condlog(3, "%s: product = %s", pp->dev, pp->product_id);
231 condlog(3, "%s: rev = %s", pp->dev, pp->rev);
233 condlog(3, "searching hwtable");
234 pp->hwe = find_hwe(conf->hwtable, pp->vendor_id,
235 pp->product_id, pp->rev);
239 return pp?pp->hwe:NULL;
243 update_multipath_table (struct multipath *mpp, vector pathvec)
245 char params[PARAMS_SIZE] = {0};
250 if (dm_get_map(mpp->alias, &mpp->size, params))
253 if (disassemble_map(pathvec, params, mpp))
260 update_multipath_status (struct multipath *mpp)
262 char status[PARAMS_SIZE] = {0};
267 if(dm_get_status(mpp->alias, status))
270 if (disassemble_status(status, mpp))
277 update_multipath_strings (struct multipath *mpp, vector pathvec)
282 condlog(4, "%s: %s", mpp->alias, __FUNCTION__);
284 free_multipath_attributes(mpp);
285 free_pgvec(mpp->pg, KEEP_PATHS);
288 if (update_multipath_table(mpp, pathvec))
291 if (update_multipath_status(mpp))
298 set_no_path_retry(struct multipath *mpp)
301 mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
302 if (mpp->nr_active > 0)
303 select_no_path_retry(mpp);
305 switch (mpp->no_path_retry) {
306 case NO_PATH_RETRY_UNDEF:
308 case NO_PATH_RETRY_FAIL:
309 dm_queue_if_no_path(mpp->alias, 0);
311 case NO_PATH_RETRY_QUEUE:
312 dm_queue_if_no_path(mpp->alias, 1);
315 dm_queue_if_no_path(mpp->alias, 1);
316 if (mpp->nr_active == 0) {
317 /* Enter retry mode */
318 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
319 condlog(1, "%s: Entering recovery mode: max_retries=%d",
320 mpp->alias, mpp->no_path_retry);
327 __setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
329 if (dm_get_info(mpp->alias, &mpp->dmi)) {
330 /* Error accessing table */
331 condlog(3, "%s: cannot access table", mpp->alias);
335 if (!dm_map_present(mpp->alias)) {
336 /* Table has been removed */
337 condlog(3, "%s: table does not exist", mpp->alias);
341 set_multipath_wwid(mpp);
342 mpp->mpe = find_mpe(mpp->wwid);
343 condlog(3, "%s: discover", mpp->alias);
345 if (update_multipath_strings(mpp, vecs->pathvec)) {
346 condlog(0, "%s: failed to setup multipath", mpp->alias);
351 mpp->hwe = extract_hwe_from_path(mpp);
353 condlog(3, "%s: no hardware entry found, using defaults",
357 select_rr_weight(mpp);
358 select_pgfailback(mpp);
359 set_no_path_retry(mpp);
360 select_pg_timeout(mpp);
361 select_flush_on_last_del(mpp);
366 remove_map(mpp, vecs, PURGE_VEC);
370 extern struct multipath *
371 add_map_without_path (struct vectors * vecs, char * alias)
373 struct multipath * mpp = alloc_multipath();
378 mpp->alias = STRDUP(alias);
380 if (setup_multipath(vecs, mpp))
381 return NULL; /* mpp freed in setup_multipath */
383 if (adopt_paths(vecs->pathvec, mpp, 1))
386 if (!vector_alloc_slot(vecs->mpvec))
389 vector_set_slot(vecs->mpvec, mpp);
391 if (start_waiter_thread(mpp, vecs))
396 remove_map(mpp, vecs, PURGE_VEC);
400 extern struct multipath *
401 add_map_with_path (struct vectors * vecs,
402 struct path * pp, int add_vec)
404 struct multipath * mpp;
406 if (!(mpp = alloc_multipath()))
409 mpp->mpe = find_mpe(pp->wwid);
412 strcpy(mpp->wwid, pp->wwid);
413 if (select_alias(mpp))
415 mpp->size = pp->size;
417 if (adopt_paths(vecs->pathvec, mpp, 1))
421 if (!vector_alloc_slot(vecs->mpvec))
424 vector_set_slot(vecs->mpvec, mpp);
430 remove_map(mpp, vecs, PURGE_VEC);
435 verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec)
444 vector_foreach_slot (mpp->paths, pp, i) {
446 * see if path is in sysfs
448 if (!pp->udev || sysfs_get_dev(pp->udev, pp->dev_t,
450 if (pp->state != PATH_DOWN) {
451 condlog(1, "%s: removing valid path %s in state %d",
452 mpp->alias, pp->dev, pp->state);
454 condlog(3, "%s: failed to access path %s",
455 mpp->alias, pp->dev);
458 vector_del_slot(mpp->paths, i);
462 store_path(rpvec, pp);
464 if ((j = find_slot(vecs->pathvec,
466 vector_del_slot(vecs->pathvec, j);
470 condlog(4, "%s: verified path %s dev_t %s",
471 mpp->alias, pp->dev, pp->dev_t);
477 int update_multipath (struct vectors *vecs, char *mapname, int reset)
479 struct multipath *mpp;
480 struct pathgroup *pgp;
484 mpp = find_mp_by_alias(vecs->mpvec, mapname);
487 condlog(3, "%s: multipath map not found\n", mapname);
491 free_pgvec(mpp->pg, KEEP_PATHS);
494 if (__setup_multipath(vecs, mpp, reset))
495 return 1; /* mpp freed in setup_multipath */
497 adopt_paths(vecs->pathvec, mpp, 0);
499 * compare checkers states with DM states
501 vector_foreach_slot (mpp->pg, pgp, i) {
502 vector_foreach_slot (pgp->paths, pp, j) {
503 if (pp->dmstate != PSTATE_FAILED)
506 if (pp->state != PATH_DOWN) {
507 int oldstate = pp->state;
508 condlog(2, "%s: mark as failed", pp->dev_t);
509 mpp->stat_path_failures++;
510 pp->state = PATH_DOWN;
511 if (oldstate == PATH_UP ||
512 oldstate == PATH_GHOST)
513 update_queue_mode_del_path(mpp);
517 * schedule the next check earlier
519 if (pp->tick > conf->checkint)
520 pp->tick = conf->checkint;
529 * mpp->no_path_retry:
530 * -2 (QUEUE) : queue_if_no_path enabled, never turned off
531 * -1 (FAIL) : fail_if_no_path
532 * 0 (UNDEF) : nothing
533 * >0 : queue_if_no_path enabled, turned off after polling n times
535 void update_queue_mode_del_path(struct multipath *mpp)
537 if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
540 * meaning of +1: retry_tick may be decremented in
541 * checkerloop before starting retry.
543 mpp->stat_queueing_timeouts++;
544 mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
545 condlog(1, "%s: Entering recovery mode: max_retries=%d",
546 mpp->alias, mpp->no_path_retry);
548 condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
551 void update_queue_mode_add_path(struct multipath *mpp)
553 if (mpp->nr_active++ == 0 && mpp->no_path_retry > 0) {
554 /* come back to normal mode from retry mode */
556 dm_queue_if_no_path(mpp->alias, 1);
557 condlog(2, "%s: queue_if_no_path enabled", mpp->alias);
558 condlog(1, "%s: Recovered to normal mode", mpp->alias);
560 condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);