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