2 * Copyright (c) 2005 Christophe Varoqui
10 #include "structs_vec.h"
11 #include <libdevmapper.h>
12 #include "devmapper.h"
13 #include "discovery.h"
15 #include "configure.h"
16 #include "blacklist.h"
18 #include "dm-generic.h"
23 #include <mpath_persist.h>
28 #include "mpath_cmd.h"
33 #include "cli_handlers.h"
36 show_paths (struct strbuf *reply, struct vectors *vecs, char *style, int pretty)
41 fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
44 if ((width = alloc_path_layout()) == NULL)
46 get_path_layout(vecs->pathvec, 1, width);
47 foreign_path_layout(width);
49 if (pretty && (hdr_len = snprint_path_header(reply, style, width)) < 0)
52 vector_foreach_slot(vecs->pathvec, pp, i) {
53 if (snprint_path(reply, style, pp, width) < 0)
56 if (snprint_foreign_paths(reply, style, width) < 0)
59 if (pretty && get_strbuf_len(reply) == (size_t)hdr_len)
60 /* No output - clear header */
61 truncate_strbuf(reply, 0);
67 show_path (struct strbuf *reply, struct vectors *vecs, struct path *pp,
70 if (snprint_path(reply, style, pp, NULL) < 0)
76 show_map_topology (struct strbuf *reply, struct multipath *mpp,
77 struct vectors *vecs, const fieldwidth_t *width)
79 if (update_multipath(vecs, mpp->alias, 0))
82 if (snprint_multipath_topology(reply, mpp, 2, width) < 0)
89 show_maps_topology (struct strbuf *reply, struct vectors * vecs)
92 struct multipath * mpp;
93 fieldwidth_t *p_width __attribute__((cleanup(cleanup_ucharp))) = NULL;
95 if ((p_width = alloc_path_layout()) == NULL)
97 get_path_layout(vecs->pathvec, 0, p_width);
98 foreign_path_layout(p_width);
100 vector_foreach_slot(vecs->mpvec, mpp, i) {
101 if (update_multipath(vecs, mpp->alias, 0)) {
105 if (snprint_multipath_topology(reply, mpp, 2, p_width) < 0)
108 if (snprint_foreign_topology(reply, 2, p_width) < 0)
115 show_maps_json (struct strbuf *reply, struct vectors * vecs)
118 struct multipath * mpp;
120 vector_foreach_slot(vecs->mpvec, mpp, i) {
121 if (update_multipath(vecs, mpp->alias, 0)) {
126 if (snprint_multipath_topology_json(reply, vecs) < 0)
133 show_map_json (struct strbuf *reply, struct multipath * mpp,
134 struct vectors * vecs)
136 if (update_multipath(vecs, mpp->alias, 0))
139 if (snprint_multipath_map_json(reply, mpp) < 0)
146 show_config (struct strbuf *reply, const struct _vector *hwtable,
147 const struct _vector *mpvec)
152 conf = get_multipath_config();
153 pthread_cleanup_push(put_multipath_config, conf);
154 rc = __snprint_config(conf, reply, hwtable, mpvec);
155 pthread_cleanup_pop(1);
162 reset_stats(struct multipath * mpp)
164 mpp->stat_switchgroup = 0;
165 mpp->stat_path_failures = 0;
166 mpp->stat_map_loads = 0;
167 mpp->stat_total_queueing_time = 0;
168 mpp->stat_queueing_timeouts = 0;
169 mpp->stat_map_failures = 0;
173 cli_list_config (void *v, struct strbuf *reply, void *data)
175 condlog(3, "list config (operator)");
177 return show_config(reply, NULL, NULL);
180 static void v_free(void *x)
186 cli_list_config_local (void *v, struct strbuf *reply, void *data)
188 struct vectors *vecs = (struct vectors *)data;
192 condlog(3, "list config local (operator)");
194 hwes = get_used_hwes(vecs->pathvec);
195 pthread_cleanup_push(v_free, hwes);
196 ret = show_config(reply, hwes, vecs->mpvec);
197 pthread_cleanup_pop(1);
202 cli_list_paths (void *v, struct strbuf *reply, void *data)
204 struct vectors * vecs = (struct vectors *)data;
206 condlog(3, "list paths (operator)");
208 return show_paths(reply, vecs, PRINT_PATH_CHECKER, 1);
212 cli_list_paths_fmt (void *v, struct strbuf *reply, void *data)
214 struct vectors * vecs = (struct vectors *)data;
215 char * fmt = get_keyparam(v, KEY_FMT);
217 condlog(3, "list paths (operator)");
219 return show_paths(reply, vecs, fmt, 1);
223 cli_list_paths_raw (void *v, struct strbuf *reply, void * data)
225 struct vectors * vecs = (struct vectors *)data;
226 char * fmt = get_keyparam(v, KEY_FMT);
228 condlog(3, "list paths (operator)");
230 return show_paths(reply, vecs, fmt, 0);
234 cli_list_path (void *v, struct strbuf *reply, void *data)
236 struct vectors * vecs = (struct vectors *)data;
237 char * param = get_keyparam(v, KEY_PATH);
240 param = convert_dev(param, 1);
241 condlog(3, "%s: list path (operator)", param);
243 pp = find_path_by_dev(vecs->pathvec, param);
247 return show_path(reply, vecs, pp, "%o");
251 cli_list_map_topology (void *v, struct strbuf *reply, void *data)
253 struct multipath * mpp;
254 struct vectors * vecs = (struct vectors *)data;
255 char * param = get_keyparam(v, KEY_MAP);
256 fieldwidth_t *p_width __attribute__((cleanup(cleanup_ucharp))) = NULL;
258 if ((p_width = alloc_path_layout()) == NULL)
260 get_path_layout(vecs->pathvec, 0, p_width);
261 param = convert_dev(param, 0);
262 mpp = find_mp_by_str(vecs->mpvec, param);
267 condlog(3, "list multipath %s (operator)", param);
269 return show_map_topology(reply, mpp, vecs, p_width);
273 cli_list_maps_topology (void *v, struct strbuf *reply, void *data)
275 struct vectors * vecs = (struct vectors *)data;
277 condlog(3, "list multipaths (operator)");
279 return show_maps_topology(reply, vecs);
283 cli_list_map_json (void *v, struct strbuf *reply, void *data)
285 struct multipath * mpp;
286 struct vectors * vecs = (struct vectors *)data;
287 char * param = get_keyparam(v, KEY_MAP);
289 param = convert_dev(param, 0);
290 mpp = find_mp_by_str(vecs->mpvec, param);
295 condlog(3, "list multipath json %s (operator)", param);
297 return show_map_json(reply, mpp, vecs);
301 cli_list_maps_json (void *v, struct strbuf *reply, void *data)
303 struct vectors * vecs = (struct vectors *)data;
305 condlog(3, "list multipaths json (operator)");
307 return show_maps_json(reply, vecs);
311 cli_list_wildcards (void *v, struct strbuf *reply, void *data)
313 if (snprint_wildcards(reply) < 0)
320 show_status (struct strbuf *reply, struct vectors *vecs)
322 if (snprint_status(reply, vecs) < 0)
329 show_daemon (struct strbuf *reply)
331 if (print_strbuf(reply, "pid %d %s\n",
332 daemon_pid, daemon_status()) < 0)
339 show_map (struct strbuf *reply, struct multipath *mpp, char *style,
340 const fieldwidth_t *width)
342 if (snprint_multipath(reply, style, mpp, width) < 0)
349 show_maps (struct strbuf *reply, struct vectors *vecs, char *style,
353 struct multipath * mpp;
355 fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
358 if ((width = alloc_multipath_layout()) == NULL)
360 get_multipath_layout(vecs->mpvec, 1, width);
361 foreign_multipath_layout(width);
364 if (pretty && (hdr_len = snprint_multipath_header(reply, style, width)) < 0)
367 vector_foreach_slot(vecs->mpvec, mpp, i) {
368 if (update_multipath(vecs, mpp->alias, 0)) {
372 if (snprint_multipath(reply, style, mpp, width) < 0)
375 if (snprint_foreign_multipaths(reply, style, width) < 0)
378 if (pretty && get_strbuf_len(reply) == (size_t)hdr_len)
379 /* No output - clear header */
380 truncate_strbuf(reply, 0);
386 cli_list_maps_fmt (void *v, struct strbuf *reply, void *data)
388 struct vectors * vecs = (struct vectors *)data;
389 char * fmt = get_keyparam(v, KEY_FMT);
391 condlog(3, "list maps (operator)");
393 return show_maps(reply, vecs, fmt, 1);
397 cli_list_maps_raw (void *v, struct strbuf *reply, void *data)
399 struct vectors * vecs = (struct vectors *)data;
400 char * fmt = get_keyparam(v, KEY_FMT);
402 condlog(3, "list maps (operator)");
404 return show_maps(reply, vecs, fmt, 0);
408 cli_list_map_fmt (void *v, struct strbuf *reply, void *data)
410 struct multipath * mpp;
411 struct vectors * vecs = (struct vectors *)data;
412 char * param = get_keyparam(v, KEY_MAP);
413 char * fmt = get_keyparam(v, KEY_FMT);
414 fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
416 if ((width = alloc_multipath_layout()) == NULL)
418 get_multipath_layout(vecs->mpvec, 1, width);
419 param = convert_dev(param, 0);
420 mpp = find_mp_by_str(vecs->mpvec, param);
424 condlog(3, "list map %s fmt %s (operator)", param, fmt);
426 return show_map(reply, mpp, fmt, width);
430 cli_list_maps (void *v, struct strbuf *reply, void *data)
432 struct vectors * vecs = (struct vectors *)data;
434 condlog(3, "list maps (operator)");
436 return show_maps(reply, vecs, PRINT_MAP_NAMES, 1);
440 cli_list_status (void *v, struct strbuf *reply, void *data)
442 struct vectors * vecs = (struct vectors *)data;
444 condlog(3, "list status (operator)");
446 return show_status(reply, vecs);
450 cli_list_maps_status (void *v, struct strbuf *reply, void *data)
452 struct vectors * vecs = (struct vectors *)data;
454 condlog(3, "list maps status (operator)");
456 return show_maps(reply, vecs, PRINT_MAP_STATUS, 1);
460 cli_list_maps_stats (void *v, struct strbuf *reply, void *data)
462 struct vectors * vecs = (struct vectors *)data;
464 condlog(3, "list maps stats (operator)");
466 return show_maps(reply, vecs, PRINT_MAP_STATS, 1);
470 cli_list_daemon (void *v, struct strbuf *reply, void *data)
472 condlog(3, "list daemon (operator)");
474 return show_daemon(reply);
478 cli_reset_maps_stats (void *v, struct strbuf *reply, void *data)
480 struct vectors * vecs = (struct vectors *)data;
482 struct multipath * mpp;
484 condlog(3, "reset multipaths stats (operator)");
486 vector_foreach_slot(vecs->mpvec, mpp, i) {
493 cli_reset_map_stats (void *v, struct strbuf *reply, void *data)
495 struct vectors * vecs = (struct vectors *)data;
496 struct multipath * mpp;
497 char * param = get_keyparam(v, KEY_MAP);
499 param = convert_dev(param, 0);
500 mpp = find_mp_by_str(vecs->mpvec, param);
505 condlog(3, "reset multipath %s stats (operator)", param);
511 add_partial_path(struct path *pp, struct vectors *vecs)
513 char wwid[WWID_SIZE];
514 struct udev_device *udd;
516 udd = get_udev_device(pp->dev_t, DEV_DEVT);
519 strcpy(wwid, pp->wwid);
520 if (get_uid(pp, pp->state, udd, 0) != 0) {
521 strcpy(pp->wwid, wwid);
522 udev_device_unref(udd);
525 if (strlen(wwid) && strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
526 condlog(0, "%s: path wwid changed from '%s' to '%s'. removing",
527 pp->dev, wwid, pp->wwid);
528 ev_remove_path(pp, vecs, 1);
529 udev_device_unref(udd);
532 udev_device_unref(pp->udev);
534 return finish_path_init(pp, vecs);
538 cli_add_path (void *v, struct strbuf *reply, void *data)
540 struct vectors * vecs = (struct vectors *)data;
541 char * param = get_keyparam(v, KEY_PATH);
547 param = convert_dev(param, 1);
548 condlog(2, "%s: add path (operator)", param);
549 conf = get_multipath_config();
550 pthread_cleanup_push(put_multipath_config, conf);
551 if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
554 pthread_cleanup_pop(1);
558 pp = find_path_by_dev(vecs->pathvec, param);
559 if (pp && pp->initialized != INIT_REMOVED) {
560 condlog(2, "%s: path already in pathvec", param);
562 if (pp->initialized == INIT_PARTIAL) {
563 if (add_partial_path(pp, vecs) < 0)
566 else if (pp->recheck_wwid == RECHECK_WWID_ON &&
567 check_path_wwid_change(pp)) {
568 condlog(0, "%s: wwid changed. Removing device",
570 handle_path_wwid_change(pp, vecs);
577 /* Trying to add a path in INIT_REMOVED state */
578 struct multipath *prev_mpp;
581 if (prev_mpp == NULL)
582 condlog(0, "Bug: %s was in INIT_REMOVED state without being a multipath member",
585 pp->initialized = INIT_NEW;
587 conf = get_multipath_config();
588 pthread_cleanup_push(put_multipath_config, conf);
589 r = pathinfo(pp, conf, DI_ALL | DI_BLACKLIST);
590 pthread_cleanup_pop(1);
593 /* Similar logic as in uev_add_path() */
595 if (r == PATHINFO_OK &&
596 !strncmp(prev_mpp->wwid, pp->wwid, WWID_SIZE)) {
597 condlog(2, "%s: path re-added to %s", pp->dev,
599 /* Have the checker reinstate this path asap */
602 } else if (ev_remove_path(pp, vecs, true) &
604 /* Path removed in ev_remove_path() */
607 /* Init state is now INIT_REMOVED again */
608 pp->dmstate = PSTATE_FAILED;
609 dm_fail_path(pp->mpp->alias, pp->dev_t);
610 condlog(1, "%s: failed to re-add path still mapped in %s",
611 pp->dev, pp->mpp->alias);
616 case PATHINFO_SKIPPED:
621 condlog(0, "%s: failed to get pathinfo", param);
628 struct udev_device *udevice;
630 udevice = udev_device_new_from_subsystem_sysname(udev,
634 condlog(0, "%s: can't find path", param);
637 conf = get_multipath_config();
638 pthread_cleanup_push(put_multipath_config, conf);
639 r = store_pathinfo(vecs->pathvec, conf,
640 udevice, DI_ALL | DI_BLACKLIST, &pp);
641 pthread_cleanup_pop(1);
642 udev_device_unref(udevice);
646 condlog(0, "%s: failed to store path info", param);
650 return ev_add_path(pp, vecs, 1);
652 append_strbuf_str(reply, "blacklisted\n");
653 condlog(2, "%s: path blacklisted", param);
658 cli_del_path (void * v, struct strbuf *reply, void * data)
660 struct vectors * vecs = (struct vectors *)data;
661 char * param = get_keyparam(v, KEY_PATH);
665 param = convert_dev(param, 1);
666 condlog(2, "%s: remove path (operator)", param);
667 pp = find_path_by_dev(vecs->pathvec, param);
669 condlog(0, "%s: path already removed", param);
672 ret = ev_remove_path(pp, vecs, 1);
673 if (ret == REMOVE_PATH_DELAY)
674 append_strbuf_str(reply, "delayed\n");
675 else if (ret == REMOVE_PATH_MAP_ERROR)
676 append_strbuf_str(reply, "map reload error. removed\n");
677 return (ret == REMOVE_PATH_FAILURE);
681 cli_add_map (void * v, struct strbuf *reply, void * data)
683 struct vectors * vecs = (struct vectors *)data;
684 char * param = get_keyparam(v, KEY_MAP);
685 int major = -1, minor = -1;
686 char dev_path[FILE_NAME_SIZE];
687 char *refwwid, *alias = NULL;
692 param = convert_dev(param, 0);
693 condlog(2, "%s: add map (operator)", param);
695 conf = get_multipath_config();
696 pthread_cleanup_push(put_multipath_config, conf);
697 if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0)
699 pthread_cleanup_pop(1);
701 append_strbuf_str(reply, "blacklisted\n");
702 condlog(2, "%s: map blacklisted", param);
706 if (dm_get_major_minor(param, &major, &minor) < 0)
707 condlog(count ? 2 : 3,
708 "%s: not a device mapper table", param);
710 sprintf(dev_path, "dm-%d", minor);
711 alias = dm_mapname(major, minor);
713 /*if there is no mapname found, we first create the device*/
714 if (!alias && !count) {
715 condlog(3, "%s: mapname not found for %d:%d",
716 param, major, minor);
717 get_refwwid(CMD_NONE, param, DEV_DEVMAP,
718 vecs->pathvec, &refwwid);
720 if (coalesce_paths(vecs, NULL, refwwid,
721 FORCE_RELOAD_NONE, CMD_NONE)
723 condlog(2, "%s: coalesce_paths failed",
727 } /*we attempt to create device only once*/
729 } while (!alias && (count < 2));
732 condlog(2, "%s: add map failed", param);
735 rc = ev_add_map(dev_path, alias, vecs);
741 cli_del_map (void * v, struct strbuf *reply, void * data)
743 struct vectors * vecs = (struct vectors *)data;
744 char * param = get_keyparam(v, KEY_MAP);
749 param = convert_dev(param, 0);
750 condlog(2, "%s: remove map (operator)", param);
751 if (dm_get_major_minor(param, &major, &minor) < 0) {
752 condlog(2, "%s: not a device mapper table", param);
755 alias = dm_mapname(major, minor);
757 condlog(2, "%s: mapname not found for %d:%d",
758 param, major, minor);
761 rc = ev_remove_map(param, alias, minor, vecs);
763 append_strbuf_str(reply, "delayed\n");
770 cli_del_maps (void *v, struct strbuf *reply, void *data)
772 struct vectors * vecs = (struct vectors *)data;
773 struct multipath *mpp;
776 condlog(2, "remove maps (operator)");
777 vector_foreach_slot(vecs->mpvec, mpp, i) {
778 if (flush_map(mpp, vecs, 0))
783 /* flush any multipath maps that aren't currently known by multipathd */
784 ret |= dm_flush_maps(0, 0);
789 cli_reload(void *v, struct strbuf *reply, void *data)
791 struct vectors * vecs = (struct vectors *)data;
792 char * mapname = get_keyparam(v, KEY_MAP);
793 struct multipath *mpp;
796 mapname = convert_dev(mapname, 0);
797 condlog(2, "%s: reload map (operator)", mapname);
798 if (sscanf(mapname, "dm-%d", &minor) == 1)
799 mpp = find_mp_by_minor(vecs->mpvec, minor);
801 mpp = find_mp_by_alias(vecs->mpvec, mapname);
804 condlog(0, "%s: invalid map name. cannot reload", mapname);
807 if (mpp->wait_for_udev) {
808 condlog(2, "%s: device not fully created, failing reload",
813 return reload_and_sync_map(mpp, vecs);
817 cli_resize(void *v, struct strbuf *reply, void *data)
819 struct vectors * vecs = (struct vectors *)data;
820 char * mapname = get_keyparam(v, KEY_MAP);
821 struct multipath *mpp;
823 unsigned long long size = 0;
824 struct pathgroup *pgp;
826 unsigned int i, j, ret;
827 bool mismatch = false;
829 mapname = convert_dev(mapname, 0);
830 condlog(2, "%s: resize map (operator)", mapname);
831 if (sscanf(mapname, "dm-%d", &minor) == 1)
832 mpp = find_mp_by_minor(vecs->mpvec, minor);
834 mpp = find_mp_by_alias(vecs->mpvec, mapname);
837 condlog(0, "%s: invalid map name. cannot resize", mapname);
841 if (mpp->wait_for_udev) {
842 condlog(2, "%s: device not fully created, failing resize",
847 vector_foreach_slot(mpp->pg, pgp, i) {
848 vector_foreach_slot (pgp->paths, pp, j) {
849 sysfs_get_size(pp, &pp->size);
854 else if (pp->size != size)
859 condlog(0, "%s: couldn't get size from sysfs. cannot resize",
864 condlog(0, "%s: path size not consistent. cannot resize",
868 if (size == mpp->size) {
869 condlog(0, "%s: map is still the same size (%llu)", mapname,
873 condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
876 ret = resize_map(mpp, size, vecs);
879 condlog(0, "%s: map removed while trying to resize", mapname);
885 cli_force_no_daemon_q(void * v, struct strbuf *reply, void * data)
889 condlog(2, "force queue_without_daemon (operator)");
890 conf = get_multipath_config();
891 if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
892 conf->queue_without_daemon = QUE_NO_DAEMON_FORCE;
893 put_multipath_config(conf);
898 cli_restore_no_daemon_q(void * v, struct strbuf *reply, void * data)
902 condlog(2, "restore queue_without_daemon (operator)");
903 conf = get_multipath_config();
904 if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE)
905 conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
906 put_multipath_config(conf);
911 cli_restore_queueing(void *v, struct strbuf *reply, void *data)
913 struct vectors * vecs = (struct vectors *)data;
914 char * mapname = get_keyparam(v, KEY_MAP);
915 struct multipath *mpp;
919 mapname = convert_dev(mapname, 0);
920 condlog(2, "%s: restore map queueing (operator)", mapname);
921 if (sscanf(mapname, "dm-%d", &minor) == 1)
922 mpp = find_mp_by_minor(vecs->mpvec, minor);
924 mpp = find_mp_by_alias(vecs->mpvec, mapname);
927 condlog(0, "%s: invalid map name, cannot restore queueing", mapname);
931 mpp->disable_queueing = 0;
932 conf = get_multipath_config();
933 pthread_cleanup_push(put_multipath_config, conf);
934 select_no_path_retry(conf, mpp);
935 pthread_cleanup_pop(1);
938 * Don't call set_no_path_retry() for the NO_PATH_RETRY_FAIL case.
939 * That would disable queueing when "restorequeueing" is called,
940 * and the code never behaved that way. Users might not expect it.
941 * In almost all cases, queueing will be disabled anyway when we
944 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
945 mpp->no_path_retry != NO_PATH_RETRY_FAIL)
946 set_no_path_retry(mpp);
952 cli_restore_all_queueing(void *v, struct strbuf *reply, void *data)
954 struct vectors * vecs = (struct vectors *)data;
955 struct multipath *mpp;
958 condlog(2, "restore queueing (operator)");
959 vector_foreach_slot(vecs->mpvec, mpp, i) {
960 mpp->disable_queueing = 0;
961 struct config *conf = get_multipath_config();
962 pthread_cleanup_push(put_multipath_config, conf);
963 select_no_path_retry(conf, mpp);
964 pthread_cleanup_pop(1);
965 /* See comment in cli_restore_queueing() */
966 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
967 mpp->no_path_retry != NO_PATH_RETRY_FAIL)
968 set_no_path_retry(mpp);
974 cli_disable_queueing(void *v, struct strbuf *reply, void *data)
976 struct vectors * vecs = (struct vectors *)data;
977 char * mapname = get_keyparam(v, KEY_MAP);
978 struct multipath *mpp;
981 mapname = convert_dev(mapname, 0);
982 condlog(2, "%s: disable map queueing (operator)", mapname);
983 if (sscanf(mapname, "dm-%d", &minor) == 1)
984 mpp = find_mp_by_minor(vecs->mpvec, minor);
986 mpp = find_mp_by_alias(vecs->mpvec, mapname);
989 condlog(0, "%s: invalid map name, cannot disable queueing", mapname);
993 if (count_active_paths(mpp) == 0)
994 mpp->stat_map_failures++;
996 mpp->no_path_retry = NO_PATH_RETRY_FAIL;
997 mpp->disable_queueing = 1;
998 set_no_path_retry(mpp);
1003 cli_disable_all_queueing(void *v, struct strbuf *reply, void *data)
1005 struct vectors * vecs = (struct vectors *)data;
1006 struct multipath *mpp;
1009 condlog(2, "disable queueing (operator)");
1010 vector_foreach_slot(vecs->mpvec, mpp, i) {
1011 if (count_active_paths(mpp) == 0)
1012 mpp->stat_map_failures++;
1013 mpp->retry_tick = 0;
1014 mpp->no_path_retry = NO_PATH_RETRY_FAIL;
1015 mpp->disable_queueing = 1;
1016 set_no_path_retry(mpp);
1022 cli_switch_group(void * v, struct strbuf *reply, void * data)
1024 char * mapname = get_keyparam(v, KEY_MAP);
1025 int groupnum = atoi(get_keyparam(v, KEY_GROUP));
1027 mapname = convert_dev(mapname, 0);
1028 condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
1030 return dm_switchgroup(mapname, groupnum);
1034 cli_reconfigure(void * v, struct strbuf *reply, void * data)
1036 condlog(2, "reconfigure (operator)");
1038 schedule_reconfigure(FORCE_RELOAD_WEAK);
1043 cli_reconfigure_all(void * v, struct strbuf *reply, void * data)
1045 condlog(2, "reconfigure all (operator)");
1047 schedule_reconfigure(FORCE_RELOAD_YES);
1052 cli_suspend(void * v, struct strbuf *reply, void * data)
1054 struct vectors * vecs = (struct vectors *)data;
1055 char * param = get_keyparam(v, KEY_MAP);
1057 struct multipath * mpp;
1059 param = convert_dev(param, 0);
1060 mpp = find_mp_by_alias(vecs->mpvec, param);
1064 if (mpp->wait_for_udev) {
1065 condlog(2, "%s: device not fully created, failing suspend",
1070 r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0);
1072 condlog(2, "%s: suspend (operator)", param);
1077 dm_get_info(param, &mpp->dmi);
1082 cli_resume(void * v, struct strbuf *reply, void * data)
1084 struct vectors * vecs = (struct vectors *)data;
1085 char * param = get_keyparam(v, KEY_MAP);
1087 struct multipath * mpp;
1088 uint16_t udev_flags;
1090 param = convert_dev(param, 0);
1091 mpp = find_mp_by_alias(vecs->mpvec, param);
1095 udev_flags = (mpp->skip_kpartx)? MPATH_UDEV_NO_KPARTX_FLAG : 0;
1096 if (mpp->wait_for_udev) {
1097 condlog(2, "%s: device not fully created, failing resume",
1102 r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, udev_flags);
1104 condlog(2, "%s: resume (operator)", param);
1109 dm_get_info(param, &mpp->dmi);
1114 cli_reinstate(void * v, struct strbuf *reply, void * data)
1116 struct vectors * vecs = (struct vectors *)data;
1117 char * param = get_keyparam(v, KEY_PATH);
1120 param = convert_dev(param, 1);
1121 pp = find_path_by_dev(vecs->pathvec, param);
1124 pp = find_path_by_devt(vecs->pathvec, param);
1126 if (!pp || !pp->mpp || !pp->mpp->alias)
1129 condlog(2, "%s: reinstate path %s (operator)",
1130 pp->mpp->alias, pp->dev_t);
1132 checker_enable(&pp->checker);
1133 return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
1137 cli_reassign (void * v, struct strbuf *reply, void * data)
1139 struct vectors * vecs = (struct vectors *)data;
1140 char * param = get_keyparam(v, KEY_MAP);
1141 struct multipath *mpp;
1143 param = convert_dev(param, 0);
1144 mpp = find_mp_by_alias(vecs->mpvec, param);
1148 if (mpp->wait_for_udev) {
1149 condlog(2, "%s: device not fully created, failing reassign",
1154 condlog(3, "%s: reset devices (operator)", param);
1161 cli_fail(void * v, struct strbuf *reply, void * data)
1163 struct vectors * vecs = (struct vectors *)data;
1164 char * param = get_keyparam(v, KEY_PATH);
1168 param = convert_dev(param, 1);
1169 pp = find_path_by_dev(vecs->pathvec, param);
1172 pp = find_path_by_devt(vecs->pathvec, param);
1174 if (!pp || !pp->mpp || !pp->mpp->alias)
1177 condlog(2, "%s: fail path %s (operator)",
1178 pp->mpp->alias, pp->dev_t);
1180 r = dm_fail_path(pp->mpp->alias, pp->dev_t);
1182 * Suspend path checking to avoid auto-reinstating the path
1185 checker_disable(&pp->checker);
1190 show_blacklist (struct strbuf *reply)
1192 struct config *conf;
1195 conf = get_multipath_config();
1196 pthread_cleanup_push(put_multipath_config, conf);
1197 fail = snprint_blacklist_report(conf, reply) < 0;
1198 pthread_cleanup_pop(1);
1207 cli_list_blacklist (void * v, struct strbuf *reply, void * data)
1209 condlog(3, "list blacklist (operator)");
1211 return show_blacklist(reply);
1215 show_devices (struct strbuf *reply, struct vectors *vecs)
1217 struct config *conf;
1220 conf = get_multipath_config();
1221 pthread_cleanup_push(put_multipath_config, conf);
1222 fail = snprint_devices(conf, reply, vecs) < 0;
1223 pthread_cleanup_pop(1);
1232 cli_list_devices (void * v, struct strbuf *reply, void * data)
1234 struct vectors * vecs = (struct vectors *)data;
1236 condlog(3, "list devices (operator)");
1238 return show_devices(reply, vecs);
1242 cli_quit (void * v, struct strbuf *reply, void * data)
1248 cli_shutdown (void * v, struct strbuf *reply, void * data)
1250 condlog(3, "shutdown (operator)");
1256 cli_getprstatus (void * v, struct strbuf *reply, void * data)
1258 static const char * const prflag_str[] = {
1259 [PRFLAG_UNKNOWN] = "unknown\n",
1260 [PRFLAG_UNSET] = "unset\n",
1261 [PRFLAG_SET] = "set\n",
1263 struct multipath * mpp;
1264 struct vectors * vecs = (struct vectors *)data;
1265 char * param = get_keyparam(v, KEY_MAP);
1267 param = convert_dev(param, 0);
1268 mpp = find_mp_by_str(vecs->mpvec, param);
1273 append_strbuf_str(reply, prflag_str[mpp->prflag]);
1275 condlog(3, "%s: reply = %s", param, get_strbuf_str(reply));
1281 cli_setprstatus(void * v, struct strbuf *reply, void * data)
1283 struct multipath * mpp;
1284 struct vectors * vecs = (struct vectors *)data;
1285 char * param = get_keyparam(v, KEY_MAP);
1287 param = convert_dev(param, 0);
1288 mpp = find_mp_by_str(vecs->mpvec, param);
1293 if (mpp->prflag != PRFLAG_SET) {
1294 mpp->prflag = PRFLAG_SET;
1295 condlog(2, "%s: prflag set", param);
1303 cli_unsetprstatus(void * v, struct strbuf *reply, void * data)
1305 struct multipath * mpp;
1306 struct vectors * vecs = (struct vectors *)data;
1307 char * param = get_keyparam(v, KEY_MAP);
1309 param = convert_dev(param, 0);
1310 mpp = find_mp_by_str(vecs->mpvec, param);
1315 if (mpp->prflag != PRFLAG_UNSET) {
1316 mpp->prflag = PRFLAG_UNSET;
1317 condlog(2, "%s: prflag unset", param);
1324 cli_getprkey(void * v, struct strbuf *reply, void * data)
1326 struct multipath * mpp;
1327 struct vectors * vecs = (struct vectors *)data;
1328 char *mapname = get_keyparam(v, KEY_MAP);
1331 mapname = convert_dev(mapname, 0);
1332 condlog(3, "%s: get persistent reservation key (operator)", mapname);
1333 mpp = find_mp_by_str(vecs->mpvec, mapname);
1338 key = get_be64(mpp->reservation_key);
1340 append_strbuf_str(reply, "none\n");
1344 if (print_strbuf(reply, "0x%" PRIx64 "%s\n", key,
1345 mpp->sa_flags & MPATH_F_APTPL_MASK ? ":aptpl" : "") < 0)
1351 cli_unsetprkey(void * v, struct strbuf *reply, void * data)
1353 struct multipath * mpp;
1354 struct vectors * vecs = (struct vectors *)data;
1355 char *mapname = get_keyparam(v, KEY_MAP);
1357 struct config *conf;
1359 mapname = convert_dev(mapname, 0);
1360 condlog(3, "%s: unset persistent reservation key (operator)", mapname);
1361 mpp = find_mp_by_str(vecs->mpvec, mapname);
1366 conf = get_multipath_config();
1367 pthread_cleanup_push(put_multipath_config, conf);
1368 ret = set_prkey(conf, mpp, 0, 0);
1369 pthread_cleanup_pop(1);
1375 cli_setprkey(void * v, struct strbuf *reply, void * data)
1377 struct multipath * mpp;
1378 struct vectors * vecs = (struct vectors *)data;
1379 char *mapname = get_keyparam(v, KEY_MAP);
1380 char *keyparam = get_keyparam(v, KEY_KEY);
1384 struct config *conf;
1386 mapname = convert_dev(mapname, 0);
1387 condlog(3, "%s: set persistent reservation key (operator)", mapname);
1388 mpp = find_mp_by_str(vecs->mpvec, mapname);
1393 if (parse_prkey_flags(keyparam, &prkey, &flags) != 0) {
1394 condlog(0, "%s: invalid prkey : '%s'", mapname, keyparam);
1398 conf = get_multipath_config();
1399 pthread_cleanup_push(put_multipath_config, conf);
1400 ret = set_prkey(conf, mpp, prkey, flags);
1401 pthread_cleanup_pop(1);
1406 static int cli_set_marginal(void * v, struct strbuf *reply, void * data)
1408 struct vectors * vecs = (struct vectors *)data;
1409 char * param = get_keyparam(v, KEY_PATH);
1412 param = convert_dev(param, 1);
1413 pp = find_path_by_dev(vecs->pathvec, param);
1416 pp = find_path_by_devt(vecs->pathvec, param);
1418 if (!pp || !pp->mpp || !pp->mpp->alias)
1421 condlog(2, "%s: set marginal path %s (operator)",
1422 pp->mpp->alias, pp->dev_t);
1423 if (pp->mpp->wait_for_udev) {
1424 condlog(2, "%s: device not fully created, failing set marginal",
1430 return reload_and_sync_map(pp->mpp, vecs);
1433 static int cli_unset_marginal(void * v, struct strbuf *reply, void * data)
1435 struct vectors * vecs = (struct vectors *)data;
1436 char * param = get_keyparam(v, KEY_PATH);
1439 param = convert_dev(param, 1);
1440 pp = find_path_by_dev(vecs->pathvec, param);
1443 pp = find_path_by_devt(vecs->pathvec, param);
1445 if (!pp || !pp->mpp || !pp->mpp->alias)
1448 condlog(2, "%s: unset marginal path %s (operator)",
1449 pp->mpp->alias, pp->dev_t);
1450 if (pp->mpp->wait_for_udev) {
1451 condlog(2, "%s: device not fully created, "
1452 "failing unset marginal", pp->mpp->alias);
1457 return reload_and_sync_map(pp->mpp, vecs);
1460 static int cli_unset_all_marginal(void * v, struct strbuf *reply, void * data)
1462 struct vectors * vecs = (struct vectors *)data;
1463 char * mapname = get_keyparam(v, KEY_MAP);
1464 struct multipath *mpp;
1465 struct pathgroup * pgp;
1470 mapname = convert_dev(mapname, 0);
1471 condlog(2, "%s: unset all marginal paths (operator)",
1474 if (sscanf(mapname, "dm-%d", &minor) == 1)
1475 mpp = find_mp_by_minor(vecs->mpvec, minor);
1477 mpp = find_mp_by_alias(vecs->mpvec, mapname);
1480 condlog(0, "%s: invalid map name. "
1481 "cannot unset marginal paths", mapname);
1484 if (mpp->wait_for_udev) {
1485 condlog(2, "%s: device not fully created, "
1486 "failing unset all marginal", mpp->alias);
1490 vector_foreach_slot (mpp->pg, pgp, i)
1491 vector_foreach_slot (pgp->paths, pp, j)
1494 return reload_and_sync_map(mpp, vecs);
1497 #define HANDLER(x) x
1498 #include "callbacks.c"