2 * Copyright (c) 2005 Christophe Varoqui
8 #include <structs_vec.h>
9 #include <libdevmapper.h>
10 #include <devmapper.h>
12 #include <configure.h>
13 #include <blacklist.h>
23 #define REALLOC_REPLY(r, a, m) \
26 (r) = REALLOC((r), (m) * 2); \
28 memset((r) + (m), 0, (m)); \
35 show_paths (char ** r, int * len, struct vectors * vecs, char * style)
41 unsigned int maxlen = INITIAL_REPLY_LEN;
44 get_path_layout(vecs->pathvec, 1);
45 reply = MALLOC(maxlen);
53 if (VECTOR_SIZE(vecs->pathvec) > 0)
54 c += snprint_path_header(c, reply + maxlen - c,
57 vector_foreach_slot(vecs->pathvec, pp, i)
58 c += snprint_path(c, reply + maxlen - c,
61 again = ((c - reply) == (maxlen - 1));
63 REALLOC_REPLY(reply, again, maxlen);
66 *len = (int)(c - reply + 1);
71 show_map_topology (char ** r, int * len, struct multipath * mpp)
75 unsigned int maxlen = INITIAL_REPLY_LEN;
78 reply = MALLOC(maxlen);
86 c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
87 again = ((c - reply) == (maxlen - 1));
89 REALLOC_REPLY(reply, again, maxlen);
92 *len = (int)(c - reply + 1);
97 show_maps_topology (char ** r, int * len, struct vectors * vecs)
100 struct multipath * mpp;
103 unsigned int maxlen = INITIAL_REPLY_LEN;
106 get_path_layout(vecs->pathvec, 0);
107 reply = MALLOC(maxlen);
115 vector_foreach_slot(vecs->mpvec, mpp, i)
116 c += snprint_multipath_topology(c, reply + maxlen - c,
119 again = ((c - reply) == (maxlen - 1));
121 REALLOC_REPLY(reply, again, maxlen);
124 *len = (int)(c - reply + 1);
129 show_config (char ** r, int * len)
133 unsigned int maxlen = INITIAL_REPLY_LEN;
136 reply = MALLOC(maxlen);
142 c += snprint_defaults(c, reply + maxlen - c);
143 again = ((c - reply) == maxlen);
145 reply = REALLOC(reply, maxlen * 2);
148 memset(reply + maxlen, 0, maxlen);
152 c += snprint_blacklist(c, reply + maxlen - c);
153 again = ((c - reply) == maxlen);
155 reply = REALLOC(reply, maxlen * 2);
158 memset(reply + maxlen, 0, maxlen);
162 c += snprint_blacklist_except(c, reply + maxlen - c);
163 again = ((c - reply) == maxlen);
165 reply = REALLOC(reply, maxlen * 2);
168 memset(reply + maxlen, 0, maxlen);
172 c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
173 again = ((c - reply) == maxlen);
175 reply = REALLOC(reply, maxlen * 2);
178 memset(reply + maxlen, 0, maxlen);
182 c += snprint_mptable(c, reply + maxlen - c, conf->mptable);
183 again = ((c - reply) == maxlen);
184 REALLOC_REPLY(reply, again, maxlen);
187 *len = (int)(c - reply + 1);
192 cli_list_config (void * v, char ** reply, int * len, void * data)
194 condlog(3, "list config (operator)");
196 return show_config(reply, len);
200 cli_list_paths (void * v, char ** reply, int * len, void * data)
202 struct vectors * vecs = (struct vectors *)data;
204 condlog(3, "list paths (operator)");
206 return show_paths(reply, len, vecs, PRINT_PATH_CHECKER);
210 cli_list_paths_fmt (void * v, char ** reply, int * len, void * data)
212 struct vectors * vecs = (struct vectors *)data;
213 char * fmt = get_keyparam(v, FMT);
215 condlog(3, "list paths (operator)");
217 return show_paths(reply, len, vecs, fmt);
221 cli_list_map_topology (void * v, char ** reply, int * len, void * data)
223 struct multipath * mpp;
224 struct vectors * vecs = (struct vectors *)data;
225 char * param = get_keyparam(v, MAP);
227 get_path_layout(vecs->pathvec, 0);
228 mpp = find_mp_by_str(vecs->mpvec, param);
233 condlog(3, "list multipath %s (operator)", param);
235 return show_map_topology(reply, len, mpp);
239 cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
241 struct vectors * vecs = (struct vectors *)data;
243 condlog(3, "list multipaths (operator)");
245 return show_maps_topology(reply, len, vecs);
249 cli_list_wildcards (void * v, char ** reply, int * len, void * data)
253 *reply = MALLOC(INITIAL_REPLY_LEN);
259 c += snprint_wildcards(c, INITIAL_REPLY_LEN);
261 *len = INITIAL_REPLY_LEN;
266 show_status (char ** r, int *len, struct vectors * vecs)
271 unsigned int maxlen = INITIAL_REPLY_LEN;
272 reply = MALLOC(maxlen);
278 c += snprint_status(c, reply + maxlen - c, vecs);
281 *len = (int)(c - reply + 1);
286 show_daemon (char ** r, int *len)
291 unsigned int maxlen = INITIAL_REPLY_LEN;
292 reply = MALLOC(maxlen);
298 c += snprintf(c, INITIAL_REPLY_LEN, "pid %d %s\n",
299 daemon_pid, daemon_status());
302 *len = (int)(c - reply + 1);
307 show_maps (char ** r, int *len, struct vectors * vecs, char * style)
310 struct multipath * mpp;
313 unsigned int maxlen = INITIAL_REPLY_LEN;
316 get_multipath_layout(vecs->mpvec, 1);
317 reply = MALLOC(maxlen);
324 if (VECTOR_SIZE(vecs->mpvec) > 0)
325 c += snprint_multipath_header(c, reply + maxlen - c,
328 vector_foreach_slot(vecs->mpvec, mpp, i)
329 c += snprint_multipath(c, reply + maxlen - c,
332 again = ((c - reply) == (maxlen - 1));
334 REALLOC_REPLY(reply, again, maxlen);
337 *len = (int)(c - reply + 1);
342 cli_list_maps_fmt (void * v, char ** reply, int * len, void * data)
344 struct vectors * vecs = (struct vectors *)data;
345 char * fmt = get_keyparam(v, FMT);
347 condlog(3, "list maps (operator)");
349 return show_maps(reply, len, vecs, fmt);
353 cli_list_maps (void * v, char ** reply, int * len, void * data)
355 struct vectors * vecs = (struct vectors *)data;
357 condlog(3, "list maps (operator)");
359 return show_maps(reply, len, vecs, PRINT_MAP_NAMES);
363 cli_list_status (void * v, char ** reply, int * len, void * data)
365 struct vectors * vecs = (struct vectors *)data;
367 condlog(3, "list status (operator)");
369 return show_status(reply, len, vecs);
373 cli_list_maps_status (void * v, char ** reply, int * len, void * data)
375 struct vectors * vecs = (struct vectors *)data;
377 condlog(3, "list maps status (operator)");
379 return show_maps(reply, len, vecs, PRINT_MAP_STATUS);
383 cli_list_maps_stats (void * v, char ** reply, int * len, void * data)
385 struct vectors * vecs = (struct vectors *)data;
387 condlog(3, "list maps stats (operator)");
389 return show_maps(reply, len, vecs, PRINT_MAP_STATS);
393 cli_list_daemon (void * v, char ** reply, int * len, void * data)
395 condlog(3, "list daemon (operator)");
397 return show_daemon(reply, len);
401 cli_add_path (void * v, char ** reply, int * len, void * data)
403 struct vectors * vecs = (struct vectors *)data;
404 char * param = get_keyparam(v, PATH);
407 condlog(2, "%s: add path (operator)", param);
409 if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
410 param) > 0 || (r = ev_add_path(param, vecs)) == 2) {
411 *reply = strdup("blacklisted\n");
412 *len = strlen(*reply) + 1;
413 condlog(2, "%s: path blacklisted", param);
420 cli_del_path (void * v, char ** reply, int * len, void * data)
422 struct vectors * vecs = (struct vectors *)data;
423 char * param = get_keyparam(v, PATH);
425 condlog(2, "%s: remove path (operator)", param);
427 return ev_remove_path(param, vecs);
431 cli_add_map (void * v, char ** reply, int * len, void * data)
433 struct vectors * vecs = (struct vectors *)data;
434 char * param = get_keyparam(v, MAP);
436 char dev_path[PATH_SIZE];
440 condlog(2, "%s: add map (operator)", param);
442 if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param) > 0) {
443 *reply = strdup("blacklisted\n");
444 *len = strlen(*reply) + 1;
445 condlog(2, "%s: map blacklisted", param);
448 minor = dm_get_minor(param);
450 condlog(2, "%s: not a device mapper table", param);
453 major = dm_get_major(param);
455 condlog(2, "%s: not a device mapper table", param);
458 sprintf(dev_path,"dm-%d", minor);
459 alias = dm_mapname(major, minor);
461 condlog(2, "%s: mapname not found for %d:%d",
462 param, major, minor);
465 rc = ev_add_map(dev_path, alias, vecs);
471 cli_del_map (void * v, char ** reply, int * len, void * data)
473 struct vectors * vecs = (struct vectors *)data;
474 char * param = get_keyparam(v, MAP);
476 char dev_path[PATH_SIZE];
480 condlog(2, "%s: remove map (operator)", param);
481 minor = dm_get_minor(param);
483 condlog(2, "%s: not a device mapper table", param);
486 major = dm_get_major(param);
488 condlog(2, "%s: not a device mapper table", param);
491 sprintf(dev_path,"dm-%d", minor);
492 alias = dm_mapname(major, minor);
494 condlog(2, "%s: mapname not found for %d:%d",
495 param, major, minor);
498 rc = ev_remove_map(param, alias, minor, vecs);
504 cli_reload(void *v, char **reply, int *len, void *data)
506 struct vectors * vecs = (struct vectors *)data;
507 char * mapname = get_keyparam(v, MAP);
508 struct multipath *mpp;
511 condlog(2, "%s: reload map (operator)", mapname);
512 if (sscanf(mapname, "dm-%d", &minor) == 1)
513 mpp = find_mp_by_minor(vecs->mpvec, minor);
515 mpp = find_mp_by_alias(vecs->mpvec, mapname);
518 condlog(0, "%s: invalid map name. cannot reload", mapname);
522 return reload_map(vecs, mpp);
525 int resize_map(struct multipath *mpp, unsigned long long size,
526 struct vectors * vecs)
528 char params[PARAMS_SIZE] = {0};
531 update_mpp_paths(mpp, vecs->pathvec);
532 setup_map(mpp, params, PARAMS_SIZE);
533 mpp->action = ACT_RESIZE;
534 if (domap(mpp, params) <= 0) {
535 condlog(0, "%s: failed to resize map : %s", mpp->alias,
543 cli_resize(void *v, char **reply, int *len, void *data)
545 struct vectors * vecs = (struct vectors *)data;
546 char * mapname = get_keyparam(v, MAP);
547 struct multipath *mpp;
549 unsigned long long size;
550 struct pathgroup *pgp;
553 condlog(2, "%s: resize map (operator)", mapname);
554 if (sscanf(mapname, "dm-%d", &minor) == 1)
555 mpp = find_mp_by_minor(vecs->mpvec, minor);
557 mpp = find_mp_by_alias(vecs->mpvec, mapname);
560 condlog(0, "%s: invalid map name. cannot resize", mapname);
564 pgp = VECTOR_SLOT(mpp->pg, 0);
565 pp = VECTOR_SLOT(pgp->paths, 0);
566 if (sysfs_get_size(pp->sysdev, &size)) {
567 condlog(0, "%s: couldn't get size for sysfs. cannot resize",
571 if (size == mpp->size) {
572 condlog(0, "%s: map is still the same size (%llu)", mapname,
576 condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
579 if (resize_map(mpp, size, vecs) != 0)
583 setup_multipath(vecs, mpp);
590 cli_restore_queueing(void *v, char **reply, int *len, void *data)
592 struct vectors * vecs = (struct vectors *)data;
593 char * mapname = get_keyparam(v, MAP);
594 struct multipath *mpp;
597 condlog(2, "%s: restore map queueing (operator)", mapname);
598 if (sscanf(mapname, "dm-%d", &minor) == 1)
599 mpp = find_mp_by_minor(vecs->mpvec, minor);
601 mpp = find_mp_by_alias(vecs->mpvec, mapname);
604 condlog(0, "%s: invalid map name, cannot restore queueing", mapname);
608 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
609 mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
610 dm_queue_if_no_path(mpp->alias, 1);
611 if (mpp->nr_active > 0)
614 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
620 cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
622 struct vectors * vecs = (struct vectors *)data;
623 struct multipath *mpp;
626 condlog(2, "restore queueing (operator)");
627 vector_foreach_slot(vecs->mpvec, mpp, i) {
628 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
629 mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
630 dm_queue_if_no_path(mpp->alias, 1);
631 if (mpp->nr_active > 0)
634 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
641 cli_disable_queueing(void *v, char **reply, int *len, void *data)
643 struct vectors * vecs = (struct vectors *)data;
644 char * mapname = get_keyparam(v, MAP);
645 struct multipath *mpp;
648 condlog(2, "%s: disable map queueing (operator)", mapname);
649 if (sscanf(mapname, "dm-%d", &minor) == 1)
650 mpp = find_mp_by_minor(vecs->mpvec, minor);
652 mpp = find_mp_by_alias(vecs->mpvec, mapname);
655 condlog(0, "%s: invalid map name, cannot disable queueing", mapname);
660 dm_queue_if_no_path(mpp->alias, 0);
665 cli_disable_all_queueing(void *v, char **reply, int *len, void *data)
667 struct vectors * vecs = (struct vectors *)data;
668 struct multipath *mpp;
671 condlog(2, "disable queueing (operator)");
672 vector_foreach_slot(vecs->mpvec, mpp, i) {
674 dm_queue_if_no_path(mpp->alias, 0);
680 cli_switch_group(void * v, char ** reply, int * len, void * data)
682 char * mapname = get_keyparam(v, MAP);
683 int groupnum = atoi(get_keyparam(v, GROUP));
685 condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
687 return dm_switchgroup(mapname, groupnum);
691 cli_reconfigure(void * v, char ** reply, int * len, void * data)
693 struct vectors * vecs = (struct vectors *)data;
695 condlog(2, "reconfigure (operator)");
697 return reconfigure(vecs);
701 cli_suspend(void * v, char ** reply, int * len, void * data)
703 struct vectors * vecs = (struct vectors *)data;
704 char * param = get_keyparam(v, MAP);
705 int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param);
707 condlog(2, "%s: suspend (operator)", param);
712 struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
717 dm_get_info(param, &mpp->dmi);
722 cli_resume(void * v, char ** reply, int * len, void * data)
724 struct vectors * vecs = (struct vectors *)data;
725 char * param = get_keyparam(v, MAP);
726 int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param);
728 condlog(2, "%s: resume (operator)", param);
733 struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
738 dm_get_info(param, &mpp->dmi);
743 cli_reinstate(void * v, char ** reply, int * len, void * data)
745 struct vectors * vecs = (struct vectors *)data;
746 char * param = get_keyparam(v, PATH);
749 pp = find_path_by_dev(vecs->pathvec, param);
752 pp = find_path_by_devt(vecs->pathvec, param);
754 if (!pp || !pp->mpp || !pp->mpp->alias)
757 condlog(2, "%s: reinstate path %s (operator)",
758 pp->mpp->alias, pp->dev_t);
760 checker_enable(&pp->checker);
761 return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
765 cli_reassign (void * v, char ** reply, int * len, void * data)
767 char * param = get_keyparam(v, MAP);
769 condlog(3, "%s: reset devices (operator)", param);
776 cli_fail(void * v, char ** reply, int * len, void * data)
778 struct vectors * vecs = (struct vectors *)data;
779 char * param = get_keyparam(v, PATH);
783 pp = find_path_by_dev(vecs->pathvec, param);
786 pp = find_path_by_devt(vecs->pathvec, param);
788 if (!pp || !pp->mpp || !pp->mpp->alias)
791 condlog(2, "%s: fail path %s (operator)",
792 pp->mpp->alias, pp->dev_t);
794 r = dm_fail_path(pp->mpp->alias, pp->dev_t);
796 * Suspend path checking to avoid auto-reinstating the path
799 checker_disable(&pp->checker);
804 show_blacklist (char ** r, int * len)
808 unsigned int maxlen = INITIAL_REPLY_LEN;
811 reply = MALLOC(maxlen);
818 c += snprint_blacklist_report(c, maxlen);
819 again = ((c - reply) == maxlen);
820 REALLOC_REPLY(reply, again, maxlen);
824 *len = (int)(c - reply + 1);
830 cli_list_blacklist (void * v, char ** reply, int * len, void * data)
832 condlog(3, "list blacklist (operator)");
834 return show_blacklist(reply, len);
838 show_devices (char ** r, int * len, struct vectors *vecs)
842 unsigned int maxlen = INITIAL_REPLY_LEN;
845 reply = MALLOC(maxlen);
852 c += snprint_devices(c, maxlen, vecs);
853 again = ((c - reply) == maxlen);
854 REALLOC_REPLY(reply, again, maxlen);
858 *len = (int)(c - reply + 1);
864 cli_list_devices (void * v, char ** reply, int * len, void * data)
866 struct vectors * vecs = (struct vectors *)data;
868 condlog(3, "list devices (operator)");
870 return show_devices(reply, len, vecs);
874 cli_quit (void * v, char ** reply, int * len, void * data)
880 cli_shutdown (void * v, char ** reply, int * len, void * data)
882 condlog(3, "shutdown (operator)");
884 return exit_daemon(0);