2 * Copyright (c) 2005 Christophe Varoqui
8 #include <structs_vec.h>
9 #include <libdevmapper.h>
10 #include <devmapper.h>
11 #include <discovery.h>
13 #include <configure.h>
14 #include <blacklist.h>
26 #define REALLOC_REPLY(r, a, m) \
29 (r) = REALLOC((r), (m) * 2); \
31 memset((r) + (m), 0, (m)); \
38 show_paths (char ** r, int * len, struct vectors * vecs, char * style)
44 unsigned int maxlen = INITIAL_REPLY_LEN;
47 get_path_layout(vecs->pathvec, 1);
48 reply = MALLOC(maxlen);
56 if (VECTOR_SIZE(vecs->pathvec) > 0)
57 c += snprint_path_header(c, reply + maxlen - c,
60 vector_foreach_slot(vecs->pathvec, pp, i)
61 c += snprint_path(c, reply + maxlen - c,
64 again = ((c - reply) == (maxlen - 1));
66 REALLOC_REPLY(reply, again, maxlen);
69 *len = (int)(c - reply + 1);
74 show_map_topology (char ** r, int * len, struct multipath * mpp,
75 struct vectors * vecs)
79 unsigned int maxlen = INITIAL_REPLY_LEN;
82 if (update_multipath(vecs, mpp->alias, 0))
84 reply = MALLOC(maxlen);
92 c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
93 again = ((c - reply) == (maxlen - 1));
95 REALLOC_REPLY(reply, again, maxlen);
98 *len = (int)(c - reply + 1);
103 show_maps_topology (char ** r, int * len, struct vectors * vecs)
106 struct multipath * mpp;
109 unsigned int maxlen = INITIAL_REPLY_LEN;
112 get_path_layout(vecs->pathvec, 0);
113 reply = MALLOC(maxlen);
121 vector_foreach_slot(vecs->mpvec, mpp, i) {
122 if (update_multipath(vecs, mpp->alias, 0)) {
126 c += snprint_multipath_topology(c, reply + maxlen - c,
130 again = ((c - reply) == (maxlen - 1));
132 REALLOC_REPLY(reply, again, maxlen);
135 *len = (int)(c - reply + 1);
140 show_config (char ** r, int * len)
144 unsigned int maxlen = INITIAL_REPLY_LEN;
147 reply = MALLOC(maxlen);
153 c += snprint_defaults(c, reply + maxlen - c);
154 again = ((c - reply) == maxlen);
156 reply = REALLOC(reply, maxlen * 2);
159 memset(reply + maxlen, 0, maxlen);
163 c += snprint_blacklist(c, reply + maxlen - c);
164 again = ((c - reply) == maxlen);
166 reply = REALLOC(reply, maxlen * 2);
169 memset(reply + maxlen, 0, maxlen);
173 c += snprint_blacklist_except(c, reply + maxlen - c);
174 again = ((c - reply) == maxlen);
176 reply = REALLOC(reply, maxlen * 2);
179 memset(reply + maxlen, 0, maxlen);
183 c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
184 again = ((c - reply) == maxlen);
186 reply = REALLOC(reply, maxlen * 2);
189 memset(reply + maxlen, 0, maxlen);
193 c += snprint_mptable(c, reply + maxlen - c, conf->mptable);
194 again = ((c - reply) == maxlen);
195 REALLOC_REPLY(reply, again, maxlen);
198 *len = (int)(c - reply + 1);
203 cli_list_config (void * v, char ** reply, int * len, void * data)
205 condlog(3, "list config (operator)");
207 return show_config(reply, len);
211 cli_list_paths (void * v, char ** reply, int * len, void * data)
213 struct vectors * vecs = (struct vectors *)data;
215 condlog(3, "list paths (operator)");
217 return show_paths(reply, len, vecs, PRINT_PATH_CHECKER);
221 cli_list_paths_fmt (void * v, char ** reply, int * len, void * data)
223 struct vectors * vecs = (struct vectors *)data;
224 char * fmt = get_keyparam(v, FMT);
226 condlog(3, "list paths (operator)");
228 return show_paths(reply, len, vecs, fmt);
232 cli_list_map_topology (void * v, char ** reply, int * len, void * data)
234 struct multipath * mpp;
235 struct vectors * vecs = (struct vectors *)data;
236 char * param = get_keyparam(v, MAP);
238 get_path_layout(vecs->pathvec, 0);
239 mpp = find_mp_by_str(vecs->mpvec, param);
244 condlog(3, "list multipath %s (operator)", param);
246 return show_map_topology(reply, len, mpp, vecs);
250 cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
252 struct vectors * vecs = (struct vectors *)data;
254 condlog(3, "list multipaths (operator)");
256 return show_maps_topology(reply, len, vecs);
260 cli_list_wildcards (void * v, char ** reply, int * len, void * data)
264 *reply = MALLOC(INITIAL_REPLY_LEN);
270 c += snprint_wildcards(c, INITIAL_REPLY_LEN);
272 *len = INITIAL_REPLY_LEN;
277 show_status (char ** r, int *len, struct vectors * vecs)
282 unsigned int maxlen = INITIAL_REPLY_LEN;
283 reply = MALLOC(maxlen);
289 c += snprint_status(c, reply + maxlen - c, vecs);
292 *len = (int)(c - reply + 1);
297 show_daemon (char ** r, int *len)
302 unsigned int maxlen = INITIAL_REPLY_LEN;
303 reply = MALLOC(maxlen);
309 c += snprintf(c, INITIAL_REPLY_LEN, "pid %d %s\n",
310 daemon_pid, daemon_status());
313 *len = (int)(c - reply + 1);
318 show_maps (char ** r, int *len, struct vectors * vecs, char * style)
321 struct multipath * mpp;
324 unsigned int maxlen = INITIAL_REPLY_LEN;
327 get_multipath_layout(vecs->mpvec, 1);
328 reply = MALLOC(maxlen);
335 if (VECTOR_SIZE(vecs->mpvec) > 0)
336 c += snprint_multipath_header(c, reply + maxlen - c,
339 vector_foreach_slot(vecs->mpvec, mpp, i)
340 c += snprint_multipath(c, reply + maxlen - c,
343 again = ((c - reply) == (maxlen - 1));
345 REALLOC_REPLY(reply, again, maxlen);
348 *len = (int)(c - reply + 1);
353 cli_list_maps_fmt (void * v, char ** reply, int * len, void * data)
355 struct vectors * vecs = (struct vectors *)data;
356 char * fmt = get_keyparam(v, FMT);
358 condlog(3, "list maps (operator)");
360 return show_maps(reply, len, vecs, fmt);
364 cli_list_maps (void * v, char ** reply, int * len, void * data)
366 struct vectors * vecs = (struct vectors *)data;
368 condlog(3, "list maps (operator)");
370 return show_maps(reply, len, vecs, PRINT_MAP_NAMES);
374 cli_list_status (void * v, char ** reply, int * len, void * data)
376 struct vectors * vecs = (struct vectors *)data;
378 condlog(3, "list status (operator)");
380 return show_status(reply, len, vecs);
384 cli_list_maps_status (void * v, char ** reply, int * len, void * data)
386 struct vectors * vecs = (struct vectors *)data;
388 condlog(3, "list maps status (operator)");
390 return show_maps(reply, len, vecs, PRINT_MAP_STATUS);
394 cli_list_maps_stats (void * v, char ** reply, int * len, void * data)
396 struct vectors * vecs = (struct vectors *)data;
398 condlog(3, "list maps stats (operator)");
400 return show_maps(reply, len, vecs, PRINT_MAP_STATS);
404 cli_list_daemon (void * v, char ** reply, int * len, void * data)
406 condlog(3, "list daemon (operator)");
408 return show_daemon(reply, len);
412 cli_add_path (void * v, char ** reply, int * len, void * data)
414 struct vectors * vecs = (struct vectors *)data;
415 char * param = get_keyparam(v, PATH);
419 condlog(2, "%s: add path (operator)", param);
421 if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
425 pp = find_path_by_dev(vecs->pathvec, param);
427 condlog(2, "%s: path already in pathvec", param);
431 struct udev_device *udevice;
433 udevice = udev_device_new_from_subsystem_sysname(conf->udev,
436 r = store_pathinfo(vecs->pathvec, conf->hwtable,
437 udevice, DI_ALL, &pp);
438 udev_device_unref(udevice);
442 condlog(0, "%s: failed to store path info", param);
445 pp->checkint = conf->checkint;
447 return ev_add_path(pp, vecs);
449 *reply = strdup("blacklisted\n");
450 *len = strlen(*reply) + 1;
451 condlog(2, "%s: path blacklisted", param);
456 cli_del_path (void * v, char ** reply, int * len, void * data)
458 struct vectors * vecs = (struct vectors *)data;
459 char * param = get_keyparam(v, PATH);
462 condlog(2, "%s: remove path (operator)", param);
463 pp = find_path_by_dev(vecs->pathvec, param);
465 condlog(0, "%s: path already removed", param);
468 return ev_remove_path(pp, vecs);
472 cli_add_map (void * v, char ** reply, int * len, void * data)
474 struct vectors * vecs = (struct vectors *)data;
475 char * param = get_keyparam(v, MAP);
477 char dev_path[PATH_SIZE];
481 condlog(2, "%s: add map (operator)", param);
483 if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param) > 0) {
484 *reply = strdup("blacklisted\n");
485 *len = strlen(*reply) + 1;
486 condlog(2, "%s: map blacklisted", param);
489 minor = dm_get_minor(param);
491 condlog(2, "%s: not a device mapper table", param);
494 major = dm_get_major(param);
496 condlog(2, "%s: not a device mapper table", param);
499 sprintf(dev_path,"dm-%d", minor);
500 alias = dm_mapname(major, minor);
502 condlog(2, "%s: mapname not found for %d:%d",
503 param, major, minor);
506 rc = ev_add_map(dev_path, alias, vecs);
512 cli_del_map (void * v, char ** reply, int * len, void * data)
514 struct vectors * vecs = (struct vectors *)data;
515 char * param = get_keyparam(v, MAP);
517 char dev_path[PATH_SIZE];
521 condlog(2, "%s: remove map (operator)", param);
522 minor = dm_get_minor(param);
524 condlog(2, "%s: not a device mapper table", param);
527 major = dm_get_major(param);
529 condlog(2, "%s: not a device mapper table", param);
532 sprintf(dev_path,"dm-%d", minor);
533 alias = dm_mapname(major, minor);
535 condlog(2, "%s: mapname not found for %d:%d",
536 param, major, minor);
539 rc = ev_remove_map(param, alias, minor, vecs);
545 cli_reload(void *v, char **reply, int *len, void *data)
547 struct vectors * vecs = (struct vectors *)data;
548 char * mapname = get_keyparam(v, MAP);
549 struct multipath *mpp;
552 condlog(2, "%s: reload map (operator)", mapname);
553 if (sscanf(mapname, "dm-%d", &minor) == 1)
554 mpp = find_mp_by_minor(vecs->mpvec, minor);
556 mpp = find_mp_by_alias(vecs->mpvec, mapname);
559 condlog(0, "%s: invalid map name. cannot reload", mapname);
563 return reload_map(vecs, mpp, 0);
566 int resize_map(struct multipath *mpp, unsigned long long size,
567 struct vectors * vecs)
569 char params[PARAMS_SIZE] = {0};
572 update_mpp_paths(mpp, vecs->pathvec);
573 setup_map(mpp, params, PARAMS_SIZE);
574 mpp->action = ACT_RESIZE;
575 if (domap(mpp, params) <= 0) {
576 condlog(0, "%s: failed to resize map : %s", mpp->alias,
584 cli_resize(void *v, char **reply, int *len, void *data)
586 struct vectors * vecs = (struct vectors *)data;
587 char * mapname = get_keyparam(v, MAP);
588 struct multipath *mpp;
590 unsigned long long size;
591 struct pathgroup *pgp;
594 condlog(2, "%s: resize map (operator)", mapname);
595 if (sscanf(mapname, "dm-%d", &minor) == 1)
596 mpp = find_mp_by_minor(vecs->mpvec, minor);
598 mpp = find_mp_by_alias(vecs->mpvec, mapname);
601 condlog(0, "%s: invalid map name. cannot resize", mapname);
605 pgp = VECTOR_SLOT(mpp->pg, 0);
606 pp = VECTOR_SLOT(pgp->paths, 0);
607 if (!pp->udev || sysfs_get_size(pp, &size)) {
608 condlog(0, "%s: couldn't get size for sysfs. cannot resize",
612 if (size == mpp->size) {
613 condlog(0, "%s: map is still the same size (%llu)", mapname,
617 condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
620 if (resize_map(mpp, size, vecs) != 0)
624 setup_multipath(vecs, mpp);
631 cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data)
633 condlog(2, "force queue_without_daemon (operator)");
634 if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
635 conf->queue_without_daemon = QUE_NO_DAEMON_FORCE;
640 cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data)
642 condlog(2, "restore queue_without_daemon (operator)");
643 if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE)
644 conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
649 cli_restore_queueing(void *v, char **reply, int *len, void *data)
651 struct vectors * vecs = (struct vectors *)data;
652 char * mapname = get_keyparam(v, MAP);
653 struct multipath *mpp;
656 condlog(2, "%s: restore map queueing (operator)", mapname);
657 if (sscanf(mapname, "dm-%d", &minor) == 1)
658 mpp = find_mp_by_minor(vecs->mpvec, minor);
660 mpp = find_mp_by_alias(vecs->mpvec, mapname);
663 condlog(0, "%s: invalid map name, cannot restore queueing", mapname);
667 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
668 mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
669 dm_queue_if_no_path(mpp->alias, 1);
670 if (mpp->nr_active > 0)
673 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
679 cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
681 struct vectors * vecs = (struct vectors *)data;
682 struct multipath *mpp;
685 condlog(2, "restore queueing (operator)");
686 vector_foreach_slot(vecs->mpvec, mpp, i) {
687 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
688 mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
689 dm_queue_if_no_path(mpp->alias, 1);
690 if (mpp->nr_active > 0)
693 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
700 cli_disable_queueing(void *v, char **reply, int *len, void *data)
702 struct vectors * vecs = (struct vectors *)data;
703 char * mapname = get_keyparam(v, MAP);
704 struct multipath *mpp;
707 condlog(2, "%s: disable map queueing (operator)", mapname);
708 if (sscanf(mapname, "dm-%d", &minor) == 1)
709 mpp = find_mp_by_minor(vecs->mpvec, minor);
711 mpp = find_mp_by_alias(vecs->mpvec, mapname);
714 condlog(0, "%s: invalid map name, cannot disable queueing", mapname);
719 dm_queue_if_no_path(mpp->alias, 0);
724 cli_disable_all_queueing(void *v, char **reply, int *len, void *data)
726 struct vectors * vecs = (struct vectors *)data;
727 struct multipath *mpp;
730 condlog(2, "disable queueing (operator)");
731 vector_foreach_slot(vecs->mpvec, mpp, i) {
733 dm_queue_if_no_path(mpp->alias, 0);
739 cli_switch_group(void * v, char ** reply, int * len, void * data)
741 char * mapname = get_keyparam(v, MAP);
742 int groupnum = atoi(get_keyparam(v, GROUP));
744 condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
746 return dm_switchgroup(mapname, groupnum);
750 cli_reconfigure(void * v, char ** reply, int * len, void * data)
752 struct vectors * vecs = (struct vectors *)data;
754 condlog(2, "reconfigure (operator)");
756 return reconfigure(vecs);
760 cli_suspend(void * v, char ** reply, int * len, void * data)
762 struct vectors * vecs = (struct vectors *)data;
763 char * param = get_keyparam(v, MAP);
764 int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param);
766 condlog(2, "%s: suspend (operator)", param);
771 struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
776 dm_get_info(param, &mpp->dmi);
781 cli_resume(void * v, char ** reply, int * len, void * data)
783 struct vectors * vecs = (struct vectors *)data;
784 char * param = get_keyparam(v, MAP);
785 int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param);
787 condlog(2, "%s: resume (operator)", param);
792 struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
797 dm_get_info(param, &mpp->dmi);
802 cli_reinstate(void * v, char ** reply, int * len, void * data)
804 struct vectors * vecs = (struct vectors *)data;
805 char * param = get_keyparam(v, PATH);
808 pp = find_path_by_dev(vecs->pathvec, param);
811 pp = find_path_by_devt(vecs->pathvec, param);
813 if (!pp || !pp->mpp || !pp->mpp->alias)
816 condlog(2, "%s: reinstate path %s (operator)",
817 pp->mpp->alias, pp->dev_t);
819 checker_enable(&pp->checker);
820 return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
824 cli_reassign (void * v, char ** reply, int * len, void * data)
826 char * param = get_keyparam(v, MAP);
828 condlog(3, "%s: reset devices (operator)", param);
835 cli_fail(void * v, char ** reply, int * len, void * data)
837 struct vectors * vecs = (struct vectors *)data;
838 char * param = get_keyparam(v, PATH);
842 pp = find_path_by_dev(vecs->pathvec, param);
845 pp = find_path_by_devt(vecs->pathvec, param);
847 if (!pp || !pp->mpp || !pp->mpp->alias)
850 condlog(2, "%s: fail path %s (operator)",
851 pp->mpp->alias, pp->dev_t);
853 r = dm_fail_path(pp->mpp->alias, pp->dev_t);
855 * Suspend path checking to avoid auto-reinstating the path
858 checker_disable(&pp->checker);
863 show_blacklist (char ** r, int * len)
867 unsigned int maxlen = INITIAL_REPLY_LEN;
870 reply = MALLOC(maxlen);
877 c += snprint_blacklist_report(c, maxlen);
878 again = ((c - reply) == maxlen);
879 REALLOC_REPLY(reply, again, maxlen);
883 *len = (int)(c - reply + 1);
889 cli_list_blacklist (void * v, char ** reply, int * len, void * data)
891 condlog(3, "list blacklist (operator)");
893 return show_blacklist(reply, len);
897 show_devices (char ** r, int * len, struct vectors *vecs)
901 unsigned int maxlen = INITIAL_REPLY_LEN;
904 reply = MALLOC(maxlen);
911 c += snprint_devices(c, maxlen, vecs);
912 again = ((c - reply) == maxlen);
913 REALLOC_REPLY(reply, again, maxlen);
917 *len = (int)(c - reply + 1);
923 cli_list_devices (void * v, char ** reply, int * len, void * data)
925 struct vectors * vecs = (struct vectors *)data;
927 condlog(3, "list devices (operator)");
929 return show_devices(reply, len, vecs);
933 cli_quit (void * v, char ** reply, int * len, void * data)
939 cli_shutdown (void * v, char ** reply, int * len, void * data)
941 condlog(3, "shutdown (operator)");
947 cli_getprstatus (void * v, char ** reply, int * len, void * data)
949 struct multipath * mpp;
950 struct vectors * vecs = (struct vectors *)data;
951 char * param = get_keyparam(v, MAP);
953 get_path_layout(vecs->pathvec, 0);
954 mpp = find_mp_by_str(vecs->mpvec, param);
959 condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag);
961 *reply =(char *)malloc(2);
966 sprintf(*reply,"%d",mpp->prflag);
970 condlog(3, "%s: reply = %s", param, *reply);
976 cli_setprstatus(void * v, char ** reply, int * len, void * data)
978 struct multipath * mpp;
979 struct vectors * vecs = (struct vectors *)data;
980 char * param = get_keyparam(v, MAP);
982 get_path_layout(vecs->pathvec, 0);
983 mpp = find_mp_by_str(vecs->mpvec, param);
990 condlog(2, "%s: prflag set", param);
998 cli_unsetprstatus(void * v, char ** reply, int * len, void * data)
1000 struct multipath * mpp;
1001 struct vectors * vecs = (struct vectors *)data;
1002 char * param = get_keyparam(v, MAP);
1004 get_path_layout(vecs->pathvec, 0);
1005 mpp = find_mp_by_str(vecs->mpvec, param);
1012 condlog(2, "%s: prflag unset", param);