ba50fb8fb03eb965c0cbeb00cd5e2cb18300ef37
[multipath-tools/.git] / multipathd / cli_handlers.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  */
4
5 #define _GNU_SOURCE
6
7 #include "checkers.h"
8 #include "memory.h"
9 #include "vector.h"
10 #include "structs.h"
11 #include "structs_vec.h"
12 #include <libdevmapper.h>
13 #include "devmapper.h"
14 #include "discovery.h"
15 #include "config.h"
16 #include "configure.h"
17 #include "blacklist.h"
18 #include "debug.h"
19 #include "dm-generic.h"
20 #include "print.h"
21 #include "sysfs.h"
22 #include <errno.h>
23 #include <libudev.h>
24 #include "util.h"
25 #include "prkey.h"
26 #include "propsel.h"
27 #include "main.h"
28 #include "cli.h"
29 #include "uevent.h"
30 #include "foreign.h"
31 #include "cli_handlers.h"
32
33 int
34 show_paths (char ** r, int * len, struct vectors * vecs, char * style,
35             int pretty)
36 {
37         int i;
38         struct path * pp;
39         char * c;
40         char * reply, * header;
41         unsigned int maxlen = INITIAL_REPLY_LEN;
42         int again = 1;
43
44         get_path_layout(vecs->pathvec, 1);
45         foreign_path_layout();
46
47         reply = MALLOC(maxlen);
48
49         while (again) {
50                 if (!reply)
51                         return 1;
52
53                 c = reply;
54
55                 if (pretty)
56                         c += snprint_path_header(c, reply + maxlen - c,
57                                                  style);
58                 header = c;
59
60                 vector_foreach_slot(vecs->pathvec, pp, i)
61                         c += snprint_path(c, reply + maxlen - c,
62                                           style, pp, pretty);
63
64                 c += snprint_foreign_paths(c, reply + maxlen - c,
65                                            style, pretty);
66
67                 again = ((c - reply) == (maxlen - 1));
68
69                 REALLOC_REPLY(reply, again, maxlen);
70         }
71
72         if (pretty && c == header) {
73                 /* No output - clear header */
74                 *reply = '\0';
75                 c = reply;
76         }
77
78         *r = reply;
79         *len = (int)(c - reply + 1);
80         return 0;
81 }
82
83 int
84 show_path (char ** r, int * len, struct vectors * vecs, struct path *pp,
85            char * style)
86 {
87         char * c;
88         char * reply;
89         unsigned int maxlen = INITIAL_REPLY_LEN;
90         int again = 1;
91
92         get_path_layout(vecs->pathvec, 1);
93         reply = MALLOC(maxlen);
94
95         while (again) {
96                 if (!reply)
97                         return 1;
98
99                 c = reply;
100
101                 c += snprint_path(c, reply + maxlen - c, style, pp, 0);
102
103                 again = ((c - reply) == (maxlen - 1));
104
105                 REALLOC_REPLY(reply, again, maxlen);
106         }
107         *r = reply;
108         *len = (int)(c - reply + 1);
109         return 0;
110 }
111
112 int
113 show_map_topology (char ** r, int * len, struct multipath * mpp,
114                    struct vectors * vecs)
115 {
116         char * c;
117         char * reply;
118         unsigned int maxlen = INITIAL_REPLY_LEN;
119         int again = 1;
120
121         if (update_multipath(vecs, mpp->alias, 0))
122                 return 1;
123         reply = MALLOC(maxlen);
124
125         while (again) {
126                 if (!reply)
127                         return 1;
128
129                 c = reply;
130
131                 c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
132                 again = ((c - reply) == (maxlen - 1));
133
134                 REALLOC_REPLY(reply, again, maxlen);
135         }
136         *r = reply;
137         *len = (int)(c - reply + 1);
138         return 0;
139 }
140
141 int
142 show_maps_topology (char ** r, int * len, struct vectors * vecs)
143 {
144         int i;
145         struct multipath * mpp;
146         char * c;
147         char * reply;
148         unsigned int maxlen = INITIAL_REPLY_LEN;
149         int again = 1;
150
151         get_path_layout(vecs->pathvec, 0);
152         foreign_path_layout();
153
154         reply = MALLOC(maxlen);
155
156         while (again) {
157                 if (!reply)
158                         return 1;
159
160                 c = reply;
161
162                 vector_foreach_slot(vecs->mpvec, mpp, i) {
163                         if (update_multipath(vecs, mpp->alias, 0)) {
164                                 i--;
165                                 continue;
166                         }
167                         c += snprint_multipath_topology(c, reply + maxlen - c,
168                                                         mpp, 2);
169                 }
170                 c += snprint_foreign_topology(c, reply + maxlen - c, 2);
171
172                 again = ((c - reply) == (maxlen - 1));
173
174                 REALLOC_REPLY(reply, again, maxlen);
175         }
176
177         *r = reply;
178         *len = (int)(c - reply + 1);
179         return 0;
180 }
181
182 int
183 show_maps_json (char ** r, int * len, struct vectors * vecs)
184 {
185         int i;
186         struct multipath * mpp;
187         char * c;
188         char * reply;
189         unsigned int maxlen = INITIAL_REPLY_LEN;
190         int again = 1;
191
192         if (VECTOR_SIZE(vecs->mpvec) > 0)
193                 maxlen *= PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec);
194
195         vector_foreach_slot(vecs->mpvec, mpp, i) {
196                 if (update_multipath(vecs, mpp->alias, 0)) {
197                         return 1;
198                 }
199         }
200
201         reply = MALLOC(maxlen);
202
203         while (again) {
204                 if (!reply)
205                         return 1;
206
207                 c = reply;
208
209                 c += snprint_multipath_topology_json(c, maxlen, vecs);
210                 again = ((c - reply) == maxlen);
211
212                 REALLOC_REPLY(reply, again, maxlen);
213         }
214         *r = reply;
215         *len = (int)(c - reply);
216         return 0;
217 }
218
219 int
220 show_map_json (char ** r, int * len, struct multipath * mpp,
221                    struct vectors * vecs)
222 {
223         char * c;
224         char * reply;
225         unsigned int maxlen = INITIAL_REPLY_LEN;
226         int again = 1;
227
228         if (update_multipath(vecs, mpp->alias, 0))
229                 return 1;
230         reply = MALLOC(maxlen);
231
232         while (again) {
233                 if (!reply)
234                         return 1;
235
236                 c = reply;
237
238                 c += snprint_multipath_map_json(c, maxlen, mpp, 1);
239                 again = ((c - reply) == maxlen);
240
241                 REALLOC_REPLY(reply, again, maxlen);
242         }
243         *r = reply;
244         *len = (int)(c - reply);
245         return 0;
246 }
247
248 int
249 show_config (char ** r, int * len)
250 {
251         char * c;
252         char * reply;
253         unsigned int maxlen = INITIAL_REPLY_LEN;
254         int again = 1;
255         struct config *conf;
256         int fail = 0;
257
258         c = reply = MALLOC(maxlen);
259
260         conf = get_multipath_config();
261         pthread_cleanup_push(put_multipath_config, conf);
262         while (again) {
263                 if (!reply) {
264                         fail = 1;
265                         break;
266                 }
267                 c = reply;
268                 c += snprint_defaults(conf, c, reply + maxlen - c);
269                 again = ((c - reply) == maxlen);
270                 REALLOC_REPLY(reply, again, maxlen);
271                 if (again)
272                         continue;
273                 c += snprint_blacklist(conf, c, reply + maxlen - c);
274                 again = ((c - reply) == maxlen);
275                 REALLOC_REPLY(reply, again, maxlen);
276                 if (again)
277                         continue;
278                 c += snprint_blacklist_except(conf, c, reply + maxlen - c);
279                 again = ((c - reply) == maxlen);
280                 REALLOC_REPLY(reply, again, maxlen);
281                 if (again)
282                         continue;
283                 c += snprint_hwtable(conf, c, reply + maxlen - c,
284                                      conf->hwtable);
285                 again = ((c - reply) == maxlen);
286                 REALLOC_REPLY(reply, again, maxlen);
287                 if (again)
288                         continue;
289                 c += snprint_overrides(conf, c, reply + maxlen - c,
290                                        conf->overrides);
291                 again = ((c - reply) == maxlen);
292                 REALLOC_REPLY(reply, again, maxlen);
293                 if (again)
294                         continue;
295                 if (VECTOR_SIZE(conf->mptable) > 0) {
296                         c += snprint_mptable(conf, c, reply + maxlen - c,
297                                              conf->mptable);
298                         again = ((c - reply) == maxlen);
299                         REALLOC_REPLY(reply, again, maxlen);
300                 }
301         }
302         pthread_cleanup_pop(1);
303         if (fail)
304                 return 1;
305         *r = reply;
306         *len = (int)(c - reply + 1);
307         return 0;
308 }
309
310 void
311 reset_stats(struct multipath * mpp)
312 {
313         mpp->stat_switchgroup = 0;
314         mpp->stat_path_failures = 0;
315         mpp->stat_map_loads = 0;
316         mpp->stat_total_queueing_time = 0;
317         mpp->stat_queueing_timeouts = 0;
318         mpp->stat_map_failures = 0;
319 }
320
321 int
322 cli_list_config (void * v, char ** reply, int * len, void * data)
323 {
324         condlog(3, "list config (operator)");
325
326         return show_config(reply, len);
327 }
328
329 int
330 cli_list_paths (void * v, char ** reply, int * len, void * data)
331 {
332         struct vectors * vecs = (struct vectors *)data;
333
334         condlog(3, "list paths (operator)");
335
336         return show_paths(reply, len, vecs, PRINT_PATH_CHECKER, 1);
337 }
338
339 int
340 cli_list_paths_fmt (void * v, char ** reply, int * len, void * data)
341 {
342         struct vectors * vecs = (struct vectors *)data;
343         char * fmt = get_keyparam(v, FMT);
344
345         condlog(3, "list paths (operator)");
346
347         return show_paths(reply, len, vecs, fmt, 1);
348 }
349
350 int
351 cli_list_paths_raw (void * v, char ** reply, int * len, void * data)
352 {
353         struct vectors * vecs = (struct vectors *)data;
354         char * fmt = get_keyparam(v, FMT);
355
356         condlog(3, "list paths (operator)");
357
358         return show_paths(reply, len, vecs, fmt, 0);
359 }
360
361 int
362 cli_list_path (void * v, char ** reply, int * len, void * data)
363 {
364         struct vectors * vecs = (struct vectors *)data;
365         char * param = get_keyparam(v, PATH);
366         struct path *pp;
367
368         param = convert_dev(param, 1);
369         condlog(3, "%s: list path (operator)", param);
370
371         pp = find_path_by_dev(vecs->pathvec, param);
372
373         return show_path(reply, len, vecs, pp, "%o");
374 }
375
376 int
377 cli_list_map_topology (void * v, char ** reply, int * len, void * data)
378 {
379         struct multipath * mpp;
380         struct vectors * vecs = (struct vectors *)data;
381         char * param = get_keyparam(v, MAP);
382
383         param = convert_dev(param, 0);
384         get_path_layout(vecs->pathvec, 0);
385         mpp = find_mp_by_str(vecs->mpvec, param);
386
387         if (!mpp)
388                 return 1;
389
390         condlog(3, "list multipath %s (operator)", param);
391
392         return show_map_topology(reply, len, mpp, vecs);
393 }
394
395 int
396 cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
397 {
398         struct vectors * vecs = (struct vectors *)data;
399
400         condlog(3, "list multipaths (operator)");
401
402         return show_maps_topology(reply, len, vecs);
403 }
404
405 int
406 cli_list_map_json (void * v, char ** reply, int * len, void * data)
407 {
408         struct multipath * mpp;
409         struct vectors * vecs = (struct vectors *)data;
410         char * param = get_keyparam(v, MAP);
411
412         param = convert_dev(param, 0);
413         get_path_layout(vecs->pathvec, 0);
414         mpp = find_mp_by_str(vecs->mpvec, param);
415
416         if (!mpp)
417                 return 1;
418
419         condlog(3, "list multipath json %s (operator)", param);
420
421         return show_map_json(reply, len, mpp, vecs);
422 }
423
424 int
425 cli_list_maps_json (void * v, char ** reply, int * len, void * data)
426 {
427         struct vectors * vecs = (struct vectors *)data;
428
429         condlog(3, "list multipaths json (operator)");
430
431         return show_maps_json(reply, len, vecs);
432 }
433
434 int
435 cli_list_wildcards (void * v, char ** reply, int * len, void * data)
436 {
437         char * c;
438
439         *reply = MALLOC(INITIAL_REPLY_LEN);
440
441         if (!*reply)
442                 return 1;
443
444         c = *reply;
445         c += snprint_wildcards(c, INITIAL_REPLY_LEN);
446
447         *len = INITIAL_REPLY_LEN;
448         return 0;
449 }
450
451 int
452 show_status (char ** r, int *len, struct vectors * vecs)
453 {
454         char * c;
455         char * reply;
456
457         unsigned int maxlen = INITIAL_REPLY_LEN;
458         reply = MALLOC(maxlen);
459
460         if (!reply)
461                 return 1;
462
463         c = reply;
464         c += snprint_status(c, reply + maxlen - c, vecs);
465
466         *r = reply;
467         *len = (int)(c - reply + 1);
468         return 0;
469 }
470
471 int
472 show_daemon (char ** r, int *len)
473 {
474         char * c;
475         char * reply;
476
477         unsigned int maxlen = INITIAL_REPLY_LEN;
478         reply = MALLOC(maxlen);
479
480         if (!reply)
481                 return 1;
482
483         c = reply;
484         c += snprintf(c, INITIAL_REPLY_LEN, "pid %d %s\n",
485                       daemon_pid, daemon_status());
486
487         *r = reply;
488         *len = (int)(c - reply + 1);
489         return 0;
490 }
491
492 int
493 show_map (char ** r, int *len, struct multipath * mpp, char * style,
494           int pretty)
495 {
496         char * c;
497         char * reply;
498         unsigned int maxlen = INITIAL_REPLY_LEN;
499         int again = 1;
500
501         reply = MALLOC(maxlen);
502         while (again) {
503                 if (!reply)
504                         return 1;
505
506                 c = reply;
507                 c += snprint_multipath(c, reply + maxlen - c, style,
508                                        mpp, pretty);
509
510                 again = ((c - reply) == (maxlen - 1));
511
512                 REALLOC_REPLY(reply, again, maxlen);
513         }
514         *r = reply;
515         *len = (int)(c - reply + 1);
516         return 0;
517 }
518
519 int
520 show_maps (char ** r, int *len, struct vectors * vecs, char * style,
521            int pretty)
522 {
523         int i;
524         struct multipath * mpp;
525         char * c, *header;
526         char * reply;
527         unsigned int maxlen = INITIAL_REPLY_LEN;
528         int again = 1;
529
530         get_multipath_layout(vecs->mpvec, 1);
531         foreign_multipath_layout();
532
533         reply = MALLOC(maxlen);
534
535         while (again) {
536                 if (!reply)
537                         return 1;
538
539                 c = reply;
540                 if (pretty)
541                         c += snprint_multipath_header(c, reply + maxlen - c,
542                                                       style);
543                 header = c;
544
545                 vector_foreach_slot(vecs->mpvec, mpp, i) {
546                         if (update_multipath(vecs, mpp->alias, 0)) {
547                                 i--;
548                                 continue;
549                         }
550                         c += snprint_multipath(c, reply + maxlen - c,
551                                                style, mpp, pretty);
552
553                 }
554                 c += snprint_foreign_multipaths(c, reply + maxlen - c,
555                                                 style, pretty);
556                 again = ((c - reply) == (maxlen - 1));
557
558                 REALLOC_REPLY(reply, again, maxlen);
559         }
560
561         if (pretty && c == header) {
562                 /* No output - clear header */
563                 *reply = '\0';
564                 c = reply;
565         }
566         *r = reply;
567         *len = (int)(c - reply + 1);
568         return 0;
569 }
570
571 int
572 cli_list_maps_fmt (void * v, char ** reply, int * len, void * data)
573 {
574         struct vectors * vecs = (struct vectors *)data;
575         char * fmt = get_keyparam(v, FMT);
576
577         condlog(3, "list maps (operator)");
578
579         return show_maps(reply, len, vecs, fmt, 1);
580 }
581
582 int
583 cli_list_maps_raw (void * v, char ** reply, int * len, void * data)
584 {
585         struct vectors * vecs = (struct vectors *)data;
586         char * fmt = get_keyparam(v, FMT);
587
588         condlog(3, "list maps (operator)");
589
590         return show_maps(reply, len, vecs, fmt, 0);
591 }
592
593 int
594 cli_list_map_fmt (void * v, char ** reply, int * len, void * data)
595 {
596         struct multipath * mpp;
597         struct vectors * vecs = (struct vectors *)data;
598         char * param = get_keyparam(v, MAP);
599         char * fmt = get_keyparam(v, FMT);
600
601         param = convert_dev(param, 0);
602         get_path_layout(vecs->pathvec, 0);
603         get_multipath_layout(vecs->mpvec, 1);
604         mpp = find_mp_by_str(vecs->mpvec, param);
605         if (!mpp)
606                 return 1;
607
608         condlog(3, "list map %s fmt %s (operator)", param, fmt);
609
610         return show_map(reply, len, mpp, fmt, 1);
611 }
612
613 int
614 cli_list_map_raw (void * v, char ** reply, int * len, void * data)
615 {
616         struct multipath * mpp;
617         struct vectors * vecs = (struct vectors *)data;
618         char * param = get_keyparam(v, MAP);
619         char * fmt = get_keyparam(v, FMT);
620
621         param = convert_dev(param, 0);
622         get_path_layout(vecs->pathvec, 0);
623         get_multipath_layout(vecs->mpvec, 1);
624         mpp = find_mp_by_str(vecs->mpvec, param);
625         if (!mpp)
626                 return 1;
627
628         condlog(3, "list map %s fmt %s (operator)", param, fmt);
629
630         return show_map(reply, len, mpp, fmt, 0);
631 }
632
633 int
634 cli_list_maps (void * v, char ** reply, int * len, void * data)
635 {
636         struct vectors * vecs = (struct vectors *)data;
637
638         condlog(3, "list maps (operator)");
639
640         return show_maps(reply, len, vecs, PRINT_MAP_NAMES, 1);
641 }
642
643 int
644 cli_list_status (void * v, char ** reply, int * len, void * data)
645 {
646         struct vectors * vecs = (struct vectors *)data;
647
648         condlog(3, "list status (operator)");
649
650         return show_status(reply, len, vecs);
651 }
652
653 int
654 cli_list_maps_status (void * v, char ** reply, int * len, void * data)
655 {
656         struct vectors * vecs = (struct vectors *)data;
657
658         condlog(3, "list maps status (operator)");
659
660         return show_maps(reply, len, vecs, PRINT_MAP_STATUS, 1);
661 }
662
663 int
664 cli_list_maps_stats (void * v, char ** reply, int * len, void * data)
665 {
666         struct vectors * vecs = (struct vectors *)data;
667
668         condlog(3, "list maps stats (operator)");
669
670         return show_maps(reply, len, vecs, PRINT_MAP_STATS, 1);
671 }
672
673 int
674 cli_list_daemon (void * v, char ** reply, int * len, void * data)
675 {
676         condlog(3, "list daemon (operator)");
677
678         return show_daemon(reply, len);
679 }
680
681 int
682 cli_reset_maps_stats (void * v, char ** reply, int * len, void * data)
683 {
684         struct vectors * vecs = (struct vectors *)data;
685         int i;
686         struct multipath * mpp;
687
688         condlog(3, "reset multipaths stats (operator)");
689
690         vector_foreach_slot(vecs->mpvec, mpp, i) {
691                 reset_stats(mpp);
692         }
693         return 0;
694 }
695
696 int
697 cli_reset_map_stats (void * v, char ** reply, int * len, void * data)
698 {
699         struct vectors * vecs = (struct vectors *)data;
700         struct multipath * mpp;
701         char * param = get_keyparam(v, MAP);
702
703         param = convert_dev(param, 0);
704         mpp = find_mp_by_str(vecs->mpvec, param);
705
706         if (!mpp)
707                 return 1;
708
709         condlog(3, "reset multipath %s stats (operator)", param);
710         reset_stats(mpp);
711         return 0;
712 }
713
714 int
715 cli_add_path (void * v, char ** reply, int * len, void * data)
716 {
717         struct vectors * vecs = (struct vectors *)data;
718         char * param = get_keyparam(v, PATH);
719         struct path *pp;
720         int r;
721         struct config *conf;
722         int invalid = 0;
723
724         param = convert_dev(param, 1);
725         condlog(2, "%s: add path (operator)", param);
726         conf = get_multipath_config();
727         pthread_cleanup_push(put_multipath_config, conf);
728         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
729                            param) > 0)
730                 invalid = 1;
731         pthread_cleanup_pop(1);
732         if (invalid)
733                 goto blacklisted;
734
735         pp = find_path_by_dev(vecs->pathvec, param);
736         if (pp) {
737                 condlog(2, "%s: path already in pathvec", param);
738                 if (pp->mpp)
739                         return 0;
740         } else {
741                 struct udev_device *udevice;
742
743                 udevice = udev_device_new_from_subsystem_sysname(udev,
744                                                                  "block",
745                                                                  param);
746                 conf = get_multipath_config();
747                 pthread_cleanup_push(put_multipath_config, conf);
748                 r = store_pathinfo(vecs->pathvec, conf,
749                                    udevice, DI_ALL, &pp);
750                 pthread_cleanup_pop(1);
751                 udev_device_unref(udevice);
752                 if (!pp) {
753                         if (r == 2)
754                                 goto blacklisted;
755                         condlog(0, "%s: failed to store path info", param);
756                         return 1;
757                 }
758                 pp->checkint = conf->checkint;
759         }
760         return ev_add_path(pp, vecs, 1);
761 blacklisted:
762         *reply = strdup("blacklisted\n");
763         *len = strlen(*reply) + 1;
764         condlog(2, "%s: path blacklisted", param);
765         return 0;
766 }
767
768 int
769 cli_del_path (void * v, char ** reply, int * len, void * data)
770 {
771         struct vectors * vecs = (struct vectors *)data;
772         char * param = get_keyparam(v, PATH);
773         struct path *pp;
774
775         param = convert_dev(param, 1);
776         condlog(2, "%s: remove path (operator)", param);
777         pp = find_path_by_dev(vecs->pathvec, param);
778         if (!pp) {
779                 condlog(0, "%s: path already removed", param);
780                 return 1;
781         }
782         return ev_remove_path(pp, vecs, 1);
783 }
784
785 int
786 cli_add_map (void * v, char ** reply, int * len, void * data)
787 {
788         struct vectors * vecs = (struct vectors *)data;
789         char * param = get_keyparam(v, MAP);
790         int major, minor;
791         char dev_path[PATH_SIZE];
792         char *refwwid, *alias = NULL;
793         int rc, count = 0;
794         struct config *conf;
795         int invalid = 0;
796
797         param = convert_dev(param, 0);
798         condlog(2, "%s: add map (operator)", param);
799
800         conf = get_multipath_config();
801         pthread_cleanup_push(put_multipath_config, conf);
802         if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0)
803                 invalid = 1;
804         pthread_cleanup_pop(1);
805         if (invalid) {
806                 *reply = strdup("blacklisted\n");
807                 *len = strlen(*reply) + 1;
808                 condlog(2, "%s: map blacklisted", param);
809                 return 1;
810         }
811         do {
812                 if (dm_get_major_minor(param, &major, &minor) < 0)
813                         condlog(2, "%s: not a device mapper table", param);
814                 else {
815                         sprintf(dev_path, "dm-%d", minor);
816                         alias = dm_mapname(major, minor);
817                 }
818                 /*if there is no mapname found, we first create the device*/
819                 if (!alias && !count) {
820                         condlog(2, "%s: mapname not found for %d:%d",
821                                 param, major, minor);
822                         rc = get_refwwid(CMD_NONE, param, DEV_DEVMAP,
823                                          vecs->pathvec, &refwwid);
824                         if (refwwid) {
825                                 if (coalesce_paths(vecs, NULL, refwwid,
826                                                    FORCE_RELOAD_NONE, CMD_NONE))
827                                         condlog(2, "%s: coalesce_paths failed",
828                                                                         param);
829                                 dm_lib_release();
830                                 FREE(refwwid);
831                         }
832                 } /*we attempt to create device only once*/
833                 count++;
834         } while (!alias && (count < 2));
835
836         if (!alias) {
837                 condlog(2, "%s: add map failed", param);
838                 return 1;
839         }
840         rc = ev_add_map(dev_path, alias, vecs);
841         FREE(alias);
842         return rc;
843 }
844
845 int
846 cli_del_map (void * v, char ** reply, int * len, void * data)
847 {
848         struct vectors * vecs = (struct vectors *)data;
849         char * param = get_keyparam(v, MAP);
850         int major, minor;
851         char *alias;
852         int rc;
853
854         param = convert_dev(param, 0);
855         condlog(2, "%s: remove map (operator)", param);
856         if (dm_get_major_minor(param, &major, &minor) < 0) {
857                 condlog(2, "%s: not a device mapper table", param);
858                 return 1;
859         }
860         alias = dm_mapname(major, minor);
861         if (!alias) {
862                 condlog(2, "%s: mapname not found for %d:%d",
863                         param, major, minor);
864                 return 1;
865         }
866         rc = ev_remove_map(param, alias, minor, vecs);
867         FREE(alias);
868         return rc;
869 }
870
871 int
872 cli_reload(void *v, char **reply, int *len, void *data)
873 {
874         struct vectors * vecs = (struct vectors *)data;
875         char * mapname = get_keyparam(v, MAP);
876         struct multipath *mpp;
877         int minor;
878
879         mapname = convert_dev(mapname, 0);
880         condlog(2, "%s: reload map (operator)", mapname);
881         if (sscanf(mapname, "dm-%d", &minor) == 1)
882                 mpp = find_mp_by_minor(vecs->mpvec, minor);
883         else
884                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
885
886         if (!mpp) {
887                 condlog(0, "%s: invalid map name. cannot reload", mapname);
888                 return 1;
889         }
890         if (mpp->wait_for_udev) {
891                 condlog(2, "%s: device not fully created, failing reload",
892                         mpp->alias);
893                 return 1;
894         }
895
896         return reload_map(vecs, mpp, 0, 1);
897 }
898
899 int resize_map(struct multipath *mpp, unsigned long long size,
900                struct vectors * vecs)
901 {
902         char params[PARAMS_SIZE] = {0};
903         unsigned long long orig_size = mpp->size;
904
905         mpp->size = size;
906         update_mpp_paths(mpp, vecs->pathvec);
907         setup_map(mpp, params, PARAMS_SIZE, vecs);
908         mpp->action = ACT_RESIZE;
909         mpp->force_udev_reload = 1;
910         if (domap(mpp, params, 1) <= 0) {
911                 condlog(0, "%s: failed to resize map : %s", mpp->alias,
912                         strerror(errno));
913                 mpp->size = orig_size;
914                 return 1;
915         }
916         return 0;
917 }
918
919 int
920 cli_resize(void *v, char **reply, int *len, void *data)
921 {
922         struct vectors * vecs = (struct vectors *)data;
923         char * mapname = get_keyparam(v, MAP);
924         struct multipath *mpp;
925         int minor;
926         unsigned long long size;
927         struct pathgroup *pgp;
928         struct path *pp;
929
930         mapname = convert_dev(mapname, 0);
931         condlog(2, "%s: resize map (operator)", mapname);
932         if (sscanf(mapname, "dm-%d", &minor) == 1)
933                 mpp = find_mp_by_minor(vecs->mpvec, minor);
934         else
935                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
936
937         if (!mpp) {
938                 condlog(0, "%s: invalid map name. cannot resize", mapname);
939                 return 1;
940         }
941
942         if (mpp->wait_for_udev) {
943                 condlog(2, "%s: device not fully created, failing resize",
944                         mpp->alias);
945                 return 1;
946         }
947
948         pgp = VECTOR_SLOT(mpp->pg, 0);
949
950         if (!pgp){
951                 condlog(0, "%s: couldn't get path group. cannot resize",
952                         mapname);
953                 return 1;
954         }
955         pp = VECTOR_SLOT(pgp->paths, 0);
956
957         if (!pp){
958                 condlog(0, "%s: couldn't get path. cannot resize", mapname);
959                 return 1;
960         }
961         if (!pp->udev || sysfs_get_size(pp, &size)) {
962                 condlog(0, "%s: couldn't get size for sysfs. cannot resize",
963                         mapname);
964                 return 1;
965         }
966         if (size == mpp->size) {
967                 condlog(0, "%s: map is still the same size (%llu)", mapname,
968                         mpp->size);
969                 return 0;
970         }
971         condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
972                 size);
973
974         if (resize_map(mpp, size, vecs) != 0)
975                 return 1;
976
977         dm_lib_release();
978         if (setup_multipath(vecs, mpp) != 0)
979                 return 1;
980         sync_map_state(mpp);
981
982         return 0;
983 }
984
985 int
986 cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data)
987 {
988         struct config *conf;
989
990         condlog(2, "force queue_without_daemon (operator)");
991         conf = get_multipath_config();
992         if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
993                 conf->queue_without_daemon = QUE_NO_DAEMON_FORCE;
994         put_multipath_config(conf);
995         return 0;
996 }
997
998 int
999 cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data)
1000 {
1001         struct config *conf;
1002
1003         condlog(2, "restore queue_without_daemon (operator)");
1004         conf = get_multipath_config();
1005         if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE)
1006                 conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
1007         put_multipath_config(conf);
1008         return 0;
1009 }
1010
1011 int
1012 cli_restore_queueing(void *v, char **reply, int *len, void *data)
1013 {
1014         struct vectors * vecs = (struct vectors *)data;
1015         char * mapname = get_keyparam(v, MAP);
1016         struct multipath *mpp;
1017         int minor;
1018         struct config *conf;
1019
1020         mapname = convert_dev(mapname, 0);
1021         condlog(2, "%s: restore map queueing (operator)", mapname);
1022         if (sscanf(mapname, "dm-%d", &minor) == 1)
1023                 mpp = find_mp_by_minor(vecs->mpvec, minor);
1024         else
1025                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
1026
1027         if (!mpp) {
1028                 condlog(0, "%s: invalid map name, cannot restore queueing", mapname);
1029                 return 1;
1030         }
1031
1032         mpp->disable_queueing = 0;
1033         conf = get_multipath_config();
1034         pthread_cleanup_push(put_multipath_config, conf);
1035         select_no_path_retry(conf, mpp);
1036         pthread_cleanup_pop(1);
1037
1038         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
1039                         mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
1040                 dm_queue_if_no_path(mpp->alias, 1);
1041                 if (mpp->no_path_retry > 0) {
1042                         if (mpp->nr_active > 0)
1043                                 mpp->retry_tick = 0;
1044                         else
1045                                 enter_recovery_mode(mpp);
1046                 }
1047         }
1048         return 0;
1049 }
1050
1051 int
1052 cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
1053 {
1054         struct vectors * vecs = (struct vectors *)data;
1055         struct multipath *mpp;
1056         int i;
1057
1058         condlog(2, "restore queueing (operator)");
1059         vector_foreach_slot(vecs->mpvec, mpp, i) {
1060                 mpp->disable_queueing = 0;
1061                 struct config *conf = get_multipath_config();
1062                 pthread_cleanup_push(put_multipath_config, conf);
1063                 select_no_path_retry(conf, mpp);
1064                 pthread_cleanup_pop(1);
1065                 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
1066                     mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
1067                         dm_queue_if_no_path(mpp->alias, 1);
1068                         if (mpp->no_path_retry > 0) {
1069                                 if (mpp->nr_active > 0)
1070                                         mpp->retry_tick = 0;
1071                                 else
1072                                         enter_recovery_mode(mpp);
1073                         }
1074                 }
1075         }
1076         return 0;
1077 }
1078
1079 int
1080 cli_disable_queueing(void *v, char **reply, int *len, void *data)
1081 {
1082         struct vectors * vecs = (struct vectors *)data;
1083         char * mapname = get_keyparam(v, MAP);
1084         struct multipath *mpp;
1085         int minor;
1086
1087         mapname = convert_dev(mapname, 0);
1088         condlog(2, "%s: disable map queueing (operator)", mapname);
1089         if (sscanf(mapname, "dm-%d", &minor) == 1)
1090                 mpp = find_mp_by_minor(vecs->mpvec, minor);
1091         else
1092                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
1093
1094         if (!mpp) {
1095                 condlog(0, "%s: invalid map name, cannot disable queueing", mapname);
1096                 return 1;
1097         }
1098
1099         if (mpp->nr_active == 0)
1100                 mpp->stat_map_failures++;
1101         mpp->retry_tick = 0;
1102         mpp->no_path_retry = NO_PATH_RETRY_FAIL;
1103         mpp->disable_queueing = 1;
1104         dm_queue_if_no_path(mpp->alias, 0);
1105         return 0;
1106 }
1107
1108 int
1109 cli_disable_all_queueing(void *v, char **reply, int *len, void *data)
1110 {
1111         struct vectors * vecs = (struct vectors *)data;
1112         struct multipath *mpp;
1113         int i;
1114
1115         condlog(2, "disable queueing (operator)");
1116         vector_foreach_slot(vecs->mpvec, mpp, i) {
1117                 if (mpp->nr_active == 0)
1118                         mpp->stat_map_failures++;
1119                 mpp->retry_tick = 0;
1120                 mpp->no_path_retry = NO_PATH_RETRY_FAIL;
1121                 mpp->disable_queueing = 1;
1122                 dm_queue_if_no_path(mpp->alias, 0);
1123         }
1124         return 0;
1125 }
1126
1127 int
1128 cli_switch_group(void * v, char ** reply, int * len, void * data)
1129 {
1130         char * mapname = get_keyparam(v, MAP);
1131         int groupnum = atoi(get_keyparam(v, GROUP));
1132
1133         mapname = convert_dev(mapname, 0);
1134         condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
1135
1136         return dm_switchgroup(mapname, groupnum);
1137 }
1138
1139 int
1140 cli_reconfigure(void * v, char ** reply, int * len, void * data)
1141 {
1142         condlog(2, "reconfigure (operator)");
1143
1144         if (set_config_state(DAEMON_CONFIGURE) == ETIMEDOUT) {
1145                 condlog(2, "timeout starting reconfiguration");
1146                 return 1;
1147         }
1148         return 0;
1149 }
1150
1151 int
1152 cli_suspend(void * v, char ** reply, int * len, void * data)
1153 {
1154         struct vectors * vecs = (struct vectors *)data;
1155         char * param = get_keyparam(v, MAP);
1156         int r;
1157         struct multipath * mpp;
1158
1159         param = convert_dev(param, 0);
1160         mpp = find_mp_by_alias(vecs->mpvec, param);
1161         if (!mpp)
1162                 return 1;
1163
1164         if (mpp->wait_for_udev) {
1165                 condlog(2, "%s: device not fully created, failing suspend",
1166                         mpp->alias);
1167                 return 1;
1168         }
1169
1170         r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0);
1171
1172         condlog(2, "%s: suspend (operator)", param);
1173
1174         if (!r) /* error */
1175                 return 1;
1176
1177         dm_get_info(param, &mpp->dmi);
1178         return 0;
1179 }
1180
1181 int
1182 cli_resume(void * v, char ** reply, int * len, void * data)
1183 {
1184         struct vectors * vecs = (struct vectors *)data;
1185         char * param = get_keyparam(v, MAP);
1186         int r;
1187         struct multipath * mpp;
1188         uint16_t udev_flags;
1189
1190         param = convert_dev(param, 0);
1191         mpp = find_mp_by_alias(vecs->mpvec, param);
1192         if (!mpp)
1193                 return 1;
1194
1195         udev_flags = (mpp->skip_kpartx)? MPATH_UDEV_NO_KPARTX_FLAG : 0;
1196         if (mpp->wait_for_udev) {
1197                 condlog(2, "%s: device not fully created, failing resume",
1198                         mpp->alias);
1199                 return 1;
1200         }
1201
1202         r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, udev_flags);
1203
1204         condlog(2, "%s: resume (operator)", param);
1205
1206         if (!r) /* error */
1207                 return 1;
1208
1209         dm_get_info(param, &mpp->dmi);
1210         return 0;
1211 }
1212
1213 int
1214 cli_reinstate(void * v, char ** reply, int * len, void * data)
1215 {
1216         struct vectors * vecs = (struct vectors *)data;
1217         char * param = get_keyparam(v, PATH);
1218         struct path * pp;
1219
1220         param = convert_dev(param, 1);
1221         pp = find_path_by_dev(vecs->pathvec, param);
1222
1223         if (!pp)
1224                  pp = find_path_by_devt(vecs->pathvec, param);
1225
1226         if (!pp || !pp->mpp || !pp->mpp->alias)
1227                 return 1;
1228
1229         condlog(2, "%s: reinstate path %s (operator)",
1230                 pp->mpp->alias, pp->dev_t);
1231
1232         checker_enable(&pp->checker);
1233         return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
1234 }
1235
1236 int
1237 cli_reassign (void * v, char ** reply, int * len, void * data)
1238 {
1239         struct vectors * vecs = (struct vectors *)data;
1240         char * param = get_keyparam(v, MAP);
1241         struct multipath *mpp;
1242
1243         param = convert_dev(param, 0);
1244         mpp = find_mp_by_alias(vecs->mpvec, param);
1245         if (!mpp)
1246                 return 1;
1247
1248         if (mpp->wait_for_udev) {
1249                 condlog(2, "%s: device not fully created, failing reassign",
1250                         mpp->alias);
1251                 return 1;
1252         }
1253
1254         condlog(3, "%s: reset devices (operator)", param);
1255
1256         dm_reassign(param);
1257         return 0;
1258 }
1259
1260 int
1261 cli_fail(void * v, char ** reply, int * len, void * data)
1262 {
1263         struct vectors * vecs = (struct vectors *)data;
1264         char * param = get_keyparam(v, PATH);
1265         struct path * pp;
1266         int r;
1267
1268         param = convert_dev(param, 1);
1269         pp = find_path_by_dev(vecs->pathvec, param);
1270
1271         if (!pp)
1272                  pp = find_path_by_devt(vecs->pathvec, param);
1273
1274         if (!pp || !pp->mpp || !pp->mpp->alias)
1275                 return 1;
1276
1277         condlog(2, "%s: fail path %s (operator)",
1278                 pp->mpp->alias, pp->dev_t);
1279
1280         r = dm_fail_path(pp->mpp->alias, pp->dev_t);
1281         /*
1282          * Suspend path checking to avoid auto-reinstating the path
1283          */
1284         if (!r)
1285                 checker_disable(&pp->checker);
1286         return r;
1287 }
1288
1289 int
1290 show_blacklist (char ** r, int * len)
1291 {
1292         char *c = NULL;
1293         char *reply = NULL;
1294         unsigned int maxlen = INITIAL_REPLY_LEN;
1295         int again = 1;
1296         struct config *conf;
1297         int fail = 0;
1298
1299         reply = MALLOC(maxlen);
1300
1301         conf = get_multipath_config();
1302         pthread_cleanup_push(put_multipath_config, conf);
1303         while (again) {
1304                 if (!reply) {
1305                         fail = 1;
1306                         break;
1307                 }
1308
1309                 c = reply;
1310                 c += snprint_blacklist_report(conf, c, maxlen);
1311                 again = ((c - reply) == maxlen);
1312                 REALLOC_REPLY(reply, again, maxlen);
1313         }
1314         pthread_cleanup_pop(1);
1315
1316         if (fail)
1317                 return 1;
1318         *r = reply;
1319         *len = (int)(c - reply + 1);
1320         return 0;
1321 }
1322
1323 int
1324 cli_list_blacklist (void * v, char ** reply, int * len, void * data)
1325 {
1326         condlog(3, "list blacklist (operator)");
1327
1328         return show_blacklist(reply, len);
1329 }
1330
1331 int
1332 show_devices (char ** r, int * len, struct vectors *vecs)
1333 {
1334         char *c = NULL;
1335         char *reply = NULL;
1336         unsigned int maxlen = INITIAL_REPLY_LEN;
1337         int again = 1;
1338         struct config *conf;
1339         int fail = 0;
1340
1341         reply = MALLOC(maxlen);
1342
1343         conf = get_multipath_config();
1344         pthread_cleanup_push(put_multipath_config, conf);
1345         while (again) {
1346                 if (!reply) {
1347                         fail = 1;
1348                         break;
1349                 }
1350
1351                 c = reply;
1352                 c += snprint_devices(conf, c, maxlen, vecs);
1353                 again = ((c - reply) == maxlen);
1354                 REALLOC_REPLY(reply, again, maxlen);
1355         }
1356         pthread_cleanup_pop(1);
1357
1358         if (fail)
1359                 return 1;
1360         *r = reply;
1361         *len = (int)(c - reply + 1);
1362
1363         return 0;
1364 }
1365
1366 int
1367 cli_list_devices (void * v, char ** reply, int * len, void * data)
1368 {
1369         struct vectors * vecs = (struct vectors *)data;
1370
1371         condlog(3, "list devices (operator)");
1372
1373         return show_devices(reply, len, vecs);
1374 }
1375
1376 int
1377 cli_quit (void * v, char ** reply, int * len, void * data)
1378 {
1379         return 0;
1380 }
1381
1382 int
1383 cli_shutdown (void * v, char ** reply, int * len, void * data)
1384 {
1385         condlog(3, "shutdown (operator)");
1386         exit_daemon();
1387         return 0;
1388 }
1389
1390 int
1391 cli_getprstatus (void * v, char ** reply, int * len, void * data)
1392 {
1393         struct multipath * mpp;
1394         struct vectors * vecs = (struct vectors *)data;
1395         char * param = get_keyparam(v, MAP);
1396
1397         param = convert_dev(param, 0);
1398         get_path_layout(vecs->pathvec, 0);
1399         mpp = find_mp_by_str(vecs->mpvec, param);
1400
1401         if (!mpp)
1402                 return 1;
1403
1404         condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag);
1405
1406         *len = asprintf(reply, "%d", mpp->prflag);
1407         if (*len < 0)
1408                 return 1;
1409
1410         condlog(3, "%s: reply = %s", param, *reply);
1411
1412         return 0;
1413 }
1414
1415 int
1416 cli_setprstatus(void * v, char ** reply, int * len, void * data)
1417 {
1418         struct multipath * mpp;
1419         struct vectors * vecs = (struct vectors *)data;
1420         char * param = get_keyparam(v, MAP);
1421
1422         param = convert_dev(param, 0);
1423         get_path_layout(vecs->pathvec, 0);
1424         mpp = find_mp_by_str(vecs->mpvec, param);
1425
1426         if (!mpp)
1427                 return 1;
1428
1429         if (!mpp->prflag) {
1430                 mpp->prflag = 1;
1431                 condlog(2, "%s: prflag set", param);
1432         }
1433
1434
1435         return 0;
1436 }
1437
1438 int
1439 cli_unsetprstatus(void * v, char ** reply, int * len, void * data)
1440 {
1441         struct multipath * mpp;
1442         struct vectors * vecs = (struct vectors *)data;
1443         char * param = get_keyparam(v, MAP);
1444
1445         param = convert_dev(param, 0);
1446         get_path_layout(vecs->pathvec, 0);
1447         mpp = find_mp_by_str(vecs->mpvec, param);
1448
1449         if (!mpp)
1450                 return 1;
1451
1452         if (mpp->prflag) {
1453                 mpp->prflag = 0;
1454                 condlog(2, "%s: prflag unset", param);
1455         }
1456
1457         return 0;
1458 }
1459
1460 int
1461 cli_getprkey(void * v, char ** reply, int * len, void * data)
1462 {
1463         struct multipath * mpp;
1464         struct vectors * vecs = (struct vectors *)data;
1465         char *mapname = get_keyparam(v, MAP);
1466
1467         mapname = convert_dev(mapname, 0);
1468         condlog(3, "%s: get persistent reservation key (operator)", mapname);
1469         mpp = find_mp_by_str(vecs->mpvec, mapname);
1470
1471         if (!mpp)
1472                 return 1;
1473
1474         *reply = malloc(20);
1475
1476         if (!get_be64(mpp->reservation_key)) {
1477                 sprintf(*reply, "none\n");
1478                 *len = strlen(*reply) + 1;
1479                 return 0;
1480         }
1481         snprintf(*reply, 20, "0x%" PRIx64 "\n",
1482                  get_be64(mpp->reservation_key));
1483         (*reply)[19] = '\0';
1484         *len = strlen(*reply) + 1;
1485         return 0;
1486 }
1487
1488 int
1489 cli_unsetprkey(void * v, char ** reply, int * len, void * data)
1490 {
1491         struct multipath * mpp;
1492         struct vectors * vecs = (struct vectors *)data;
1493         char *mapname = get_keyparam(v, MAP);
1494         int ret;
1495         struct config *conf;
1496
1497         mapname = convert_dev(mapname, 0);
1498         condlog(3, "%s: unset persistent reservation key (operator)", mapname);
1499         mpp = find_mp_by_str(vecs->mpvec, mapname);
1500
1501         if (!mpp)
1502                 return 1;
1503
1504         conf = get_multipath_config();
1505         pthread_cleanup_push(put_multipath_config, conf);
1506         ret = set_prkey(conf, mpp, 0);
1507         pthread_cleanup_pop(1);
1508
1509         return ret;
1510 }
1511
1512 int
1513 cli_setprkey(void * v, char ** reply, int * len, void * data)
1514 {
1515         struct multipath * mpp;
1516         struct vectors * vecs = (struct vectors *)data;
1517         char *mapname = get_keyparam(v, MAP);
1518         char *keyparam = get_keyparam(v, KEY);
1519         uint64_t prkey;
1520         int ret;
1521         struct config *conf;
1522
1523         mapname = convert_dev(mapname, 0);
1524         condlog(3, "%s: set persistent reservation key (operator)", mapname);
1525         mpp = find_mp_by_str(vecs->mpvec, mapname);
1526
1527         if (!mpp)
1528                 return 1;
1529
1530         if (parse_prkey(keyparam, &prkey) != 0) {
1531                 condlog(0, "%s: invalid prkey : '%s'", mapname, keyparam);
1532                 return 1;
1533         }
1534
1535         conf = get_multipath_config();
1536         pthread_cleanup_push(put_multipath_config, conf);
1537         ret = set_prkey(conf, mpp, prkey);
1538         pthread_cleanup_pop(1);
1539
1540         return ret;
1541 }