Do not print empty multipaths section
[multipath-tools/.git] / multipathd / cli_handlers.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  */
4 #include <checkers.h>
5 #include <memory.h>
6 #include <vector.h>
7 #include <structs.h>
8 #include <structs_vec.h>
9 #include <libdevmapper.h>
10 #include <devmapper.h>
11 #include <discovery.h>
12 #include <config.h>
13 #include <configure.h>
14 #include <blacklist.h>
15 #include <debug.h>
16 #include <print.h>
17 #include <sysfs.h>
18 #include <errno.h>
19 #include <libudev.h>
20 #include <util.h>
21
22 #include "main.h"
23 #include "cli.h"
24 #include "uevent.h"
25
26 #define REALLOC_REPLY(r, a, m)                                  \
27         do {                                                    \
28                 if ((a)) {                                      \
29                         (r) = REALLOC((r), (m) * 2);            \
30                         if ((r)) {                              \
31                                 memset((r) + (m), 0, (m));      \
32                                 (m) *= 2;                       \
33                         }                                       \
34                 }                                               \
35         } while (0)
36
37 int
38 show_paths (char ** r, int * len, struct vectors * vecs, char * style)
39 {
40         int i;
41         struct path * pp;
42         char * c;
43         char * reply;
44         unsigned int maxlen = INITIAL_REPLY_LEN;
45         int again = 1;
46
47         get_path_layout(vecs->pathvec, 1);
48         reply = MALLOC(maxlen);
49
50         while (again) {
51                 if (!reply)
52                         return 1;
53
54                 c = reply;
55
56                 if (VECTOR_SIZE(vecs->pathvec) > 0)
57                         c += snprint_path_header(c, reply + maxlen - c,
58                                                  style);
59
60                 vector_foreach_slot(vecs->pathvec, pp, i)
61                         c += snprint_path(c, reply + maxlen - c,
62                                           style, pp);
63
64                 again = ((c - reply) == (maxlen - 1));
65
66                 REALLOC_REPLY(reply, again, maxlen);
67         }
68         *r = reply;
69         *len = (int)(c - reply + 1);
70         return 0;
71 }
72
73 int
74 show_path (char ** r, int * len, struct vectors * vecs, struct path *pp,
75            char * style)
76 {
77         char * c;
78         char * reply;
79         unsigned int maxlen = INITIAL_REPLY_LEN;
80         int again = 1;
81
82         get_path_layout(vecs->pathvec, 1);
83         reply = MALLOC(maxlen);
84
85         while (again) {
86                 if (!reply)
87                         return 1;
88
89                 c = reply;
90
91                 c += snprint_path(c, reply + maxlen - c, style, pp);
92
93                 again = ((c - reply) == (maxlen - 1));
94
95                 REALLOC_REPLY(reply, again, maxlen);
96         }
97         *r = reply;
98         *len = (int)(c - reply + 1);
99         return 0;
100 }
101
102 int
103 show_map_topology (char ** r, int * len, struct multipath * mpp,
104                    struct vectors * vecs)
105 {
106         char * c;
107         char * reply;
108         unsigned int maxlen = INITIAL_REPLY_LEN;
109         int again = 1;
110
111         if (update_multipath(vecs, mpp->alias, 0))
112                 return 1;
113         reply = MALLOC(maxlen);
114
115         while (again) {
116                 if (!reply)
117                         return 1;
118
119                 c = reply;
120
121                 c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
122                 again = ((c - reply) == (maxlen - 1));
123
124                 REALLOC_REPLY(reply, again, maxlen);
125         }
126         *r = reply;
127         *len = (int)(c - reply + 1);
128         return 0;
129 }
130
131 int
132 show_maps_topology (char ** r, int * len, struct vectors * vecs)
133 {
134         int i;
135         struct multipath * mpp;
136         char * c;
137         char * reply;
138         unsigned int maxlen = INITIAL_REPLY_LEN;
139         int again = 1;
140  
141         get_path_layout(vecs->pathvec, 0);
142         reply = MALLOC(maxlen);
143
144         while (again) {
145                 if (!reply)
146                         return 1;
147
148                 c = reply;
149
150                 vector_foreach_slot(vecs->mpvec, mpp, i) {
151                         if (update_multipath(vecs, mpp->alias, 0)) {
152                                 i--;
153                                 continue;
154                         }
155                         c += snprint_multipath_topology(c, reply + maxlen - c,
156                                                         mpp, 2);
157                 }
158
159                 again = ((c - reply) == (maxlen - 1));
160
161                 REALLOC_REPLY(reply, again, maxlen);
162         }
163         *r = reply;
164         *len = (int)(c - reply + 1);
165         return 0;
166 }
167
168 int
169 show_config (char ** r, int * len)
170 {
171         char * c;
172         char * reply;
173         unsigned int maxlen = INITIAL_REPLY_LEN;
174         int again = 1;
175
176         reply = MALLOC(maxlen);
177
178         while (again) {
179                 if (!reply)
180                         return 1;
181                 c = reply;
182                 c += snprint_defaults(c, reply + maxlen - c);
183                 again = ((c - reply) == maxlen);
184                 if (again) {
185                         reply = REALLOC(reply, maxlen * 2);
186                         if (!reply)
187                                 return 1;
188                         memset(reply + maxlen, 0, maxlen);
189                         maxlen *= 2;
190                         continue;
191                 }
192                 c += snprint_blacklist(c, reply + maxlen - c);
193                 again = ((c - reply) == maxlen);
194                 if (again) {
195                         reply = REALLOC(reply, maxlen * 2);
196                         if (!reply)
197                                 return 1;
198                         memset(reply + maxlen, 0, maxlen);
199                         maxlen *= 2;
200                         continue;
201                 }
202                 c += snprint_blacklist_except(c, reply + maxlen - c);
203                 again = ((c - reply) == maxlen);
204                 if (again) {
205                         reply = REALLOC(reply, maxlen * 2);
206                         if (!reply)
207                                 return 1;
208                         memset(reply + maxlen, 0, maxlen);
209                         maxlen *= 2;
210                         continue;
211                 }
212                 c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
213                 again = ((c - reply) == maxlen);
214                 if (again) {
215                         reply = REALLOC(reply, maxlen * 2);
216                         if (!reply)
217                                 return 1;
218                         memset(reply + maxlen, 0, maxlen);
219                         maxlen *= 2;
220                         continue;
221                 }
222                 c += snprint_overrides(c, reply + maxlen - c, conf->overrides);
223                 again = ((c - reply) == maxlen);
224                 if (again) {
225                         reply = REALLOC(reply, maxlen * 2);
226                         if (!reply)
227                                 return 1;
228                         memset(reply + maxlen, 0, maxlen);
229                         maxlen *= 2;
230                         continue;
231                 }
232                 if (VECTOR_SIZE(conf->mptable) > 0) {
233                         c += snprint_mptable(c, reply + maxlen - c,
234                                              conf->mptable);
235                         again = ((c - reply) == maxlen);
236                         REALLOC_REPLY(reply, again, maxlen);
237                 }
238         }
239         *r = reply;
240         *len = (int)(c - reply + 1);
241         return 0;
242 }
243
244 int
245 cli_list_config (void * v, char ** reply, int * len, void * data)
246 {
247         condlog(3, "list config (operator)");
248
249         return show_config(reply, len);
250 }
251
252 int
253 cli_list_paths (void * v, char ** reply, int * len, void * data)
254 {
255         struct vectors * vecs = (struct vectors *)data;
256
257         condlog(3, "list paths (operator)");
258
259         return show_paths(reply, len, vecs, PRINT_PATH_CHECKER);
260 }
261
262 int
263 cli_list_paths_fmt (void * v, char ** reply, int * len, void * data)
264 {
265         struct vectors * vecs = (struct vectors *)data;
266         char * fmt = get_keyparam(v, FMT);
267
268         condlog(3, "list paths (operator)");
269
270         return show_paths(reply, len, vecs, fmt);
271 }
272
273 int
274 cli_list_path (void * v, char ** reply, int * len, void * data)
275 {
276         struct vectors * vecs = (struct vectors *)data;
277         char * param = get_keyparam(v, PATH);
278         struct path *pp;
279
280         param = convert_dev(param, 1);
281         condlog(3, "%s: list path (operator)", param);
282
283         pp = find_path_by_dev(vecs->pathvec, param);
284
285         return show_path(reply, len, vecs, pp, "%o");
286 }
287
288 int
289 cli_list_map_topology (void * v, char ** reply, int * len, void * data)
290 {
291         struct multipath * mpp;
292         struct vectors * vecs = (struct vectors *)data;
293         char * param = get_keyparam(v, MAP);
294         
295         param = convert_dev(param, 0);
296         get_path_layout(vecs->pathvec, 0);
297         mpp = find_mp_by_str(vecs->mpvec, param);
298
299         if (!mpp)
300                 return 1;
301
302         condlog(3, "list multipath %s (operator)", param);
303
304         return show_map_topology(reply, len, mpp, vecs);
305 }
306
307 int
308 cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
309 {
310         struct vectors * vecs = (struct vectors *)data;
311
312         condlog(3, "list multipaths (operator)");
313
314         return show_maps_topology(reply, len, vecs);
315 }
316
317 int
318 cli_list_wildcards (void * v, char ** reply, int * len, void * data)
319 {
320         char * c;
321
322         *reply = MALLOC(INITIAL_REPLY_LEN);
323
324         if (!*reply)
325                 return 1;
326
327         c = *reply;
328         c += snprint_wildcards(c, INITIAL_REPLY_LEN);
329
330         *len = INITIAL_REPLY_LEN;
331         return 0;
332 }
333
334 int
335 show_status (char ** r, int *len, struct vectors * vecs)
336 {
337         char * c;
338         char * reply;
339
340         unsigned int maxlen = INITIAL_REPLY_LEN;
341         reply = MALLOC(maxlen);
342
343         if (!reply)
344                 return 1;
345
346         c = reply;
347         c += snprint_status(c, reply + maxlen - c, vecs);
348
349         *r = reply;
350         *len = (int)(c - reply + 1);
351         return 0;
352 }
353
354 int
355 show_daemon (char ** r, int *len)
356 {
357         char * c;
358         char * reply;
359
360         unsigned int maxlen = INITIAL_REPLY_LEN;
361         reply = MALLOC(maxlen);
362
363         if (!reply)
364                 return 1;
365
366         c = reply;
367         c += snprintf(c, INITIAL_REPLY_LEN, "pid %d %s\n",
368                       daemon_pid, daemon_status());
369
370         *r = reply;
371         *len = (int)(c - reply + 1);
372         return 0;
373 }
374
375 int
376 show_maps (char ** r, int *len, struct vectors * vecs, char * style)
377 {
378         int i;
379         struct multipath * mpp;
380         char * c;
381         char * reply;
382         unsigned int maxlen = INITIAL_REPLY_LEN;
383         int again = 1;
384
385         get_multipath_layout(vecs->mpvec, 1);
386         reply = MALLOC(maxlen);
387
388         while (again) {
389                 if (!reply)
390                         return 1;
391
392                 c = reply;
393                 if (VECTOR_SIZE(vecs->mpvec) > 0)
394                         c += snprint_multipath_header(c, reply + maxlen - c,
395                                                       style);
396
397                 vector_foreach_slot(vecs->mpvec, mpp, i)
398                         c += snprint_multipath(c, reply + maxlen - c,
399                                                style, mpp);
400
401                 again = ((c - reply) == (maxlen - 1));
402
403                 REALLOC_REPLY(reply, again, maxlen);
404         }
405         *r = reply;
406         *len = (int)(c - reply + 1);
407         return 0;
408 }
409
410 int
411 cli_list_maps_fmt (void * v, char ** reply, int * len, void * data)
412 {
413         struct vectors * vecs = (struct vectors *)data;
414         char * fmt = get_keyparam(v, FMT);
415
416         condlog(3, "list maps (operator)");
417
418         return show_maps(reply, len, vecs, fmt);
419 }
420
421 int
422 cli_list_maps (void * v, char ** reply, int * len, void * data)
423 {
424         struct vectors * vecs = (struct vectors *)data;
425
426         condlog(3, "list maps (operator)");
427
428         return show_maps(reply, len, vecs, PRINT_MAP_NAMES);
429 }
430
431 int
432 cli_list_status (void * v, char ** reply, int * len, void * data)
433 {
434         struct vectors * vecs = (struct vectors *)data;
435
436         condlog(3, "list status (operator)");
437
438         return show_status(reply, len, vecs);
439 }
440
441 int
442 cli_list_maps_status (void * v, char ** reply, int * len, void * data)
443 {
444         struct vectors * vecs = (struct vectors *)data;
445
446         condlog(3, "list maps status (operator)");
447
448         return show_maps(reply, len, vecs, PRINT_MAP_STATUS);
449 }
450
451 int
452 cli_list_maps_stats (void * v, char ** reply, int * len, void * data)
453 {
454         struct vectors * vecs = (struct vectors *)data;
455
456         condlog(3, "list maps stats (operator)");
457
458         return show_maps(reply, len, vecs, PRINT_MAP_STATS);
459 }
460
461 int
462 cli_list_daemon (void * v, char ** reply, int * len, void * data)
463 {
464         condlog(3, "list daemon (operator)");
465
466         return show_daemon(reply, len);
467 }
468
469 int
470 cli_add_path (void * v, char ** reply, int * len, void * data)
471 {
472         struct vectors * vecs = (struct vectors *)data;
473         char * param = get_keyparam(v, PATH);
474         struct path *pp;
475         int r;
476
477         param = convert_dev(param, 1);
478         condlog(2, "%s: add path (operator)", param);
479
480         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
481                            param) > 0)
482                 goto blacklisted;
483
484         pp = find_path_by_dev(vecs->pathvec, param);
485         if (pp) {
486                 condlog(2, "%s: path already in pathvec", param);
487                 if (pp->mpp)
488                         return 0;
489         } else {
490                 struct udev_device *udevice;
491
492                 udevice = udev_device_new_from_subsystem_sysname(conf->udev,
493                                                                  "block",
494                                                                  param);
495                 r = store_pathinfo(vecs->pathvec, conf->hwtable,
496                                    udevice, DI_ALL, &pp);
497                 udev_device_unref(udevice);
498                 if (!pp) {
499                         if (r == 2)
500                                 goto blacklisted;
501                         condlog(0, "%s: failed to store path info", param);
502                         return 1;
503                 }
504                 pp->checkint = conf->checkint;
505         }
506         return ev_add_path(pp, vecs);
507 blacklisted:
508         *reply = strdup("blacklisted\n");
509         *len = strlen(*reply) + 1;
510         condlog(2, "%s: path blacklisted", param);
511         return 0;
512 }
513
514 int
515 cli_del_path (void * v, char ** reply, int * len, void * data)
516 {
517         struct vectors * vecs = (struct vectors *)data;
518         char * param = get_keyparam(v, PATH);
519         struct path *pp;
520
521         param = convert_dev(param, 1);
522         condlog(2, "%s: remove path (operator)", param);
523         pp = find_path_by_dev(vecs->pathvec, param);
524         if (!pp) {
525                 condlog(0, "%s: path already removed", param);
526                 return 0;
527         }
528         return ev_remove_path(pp, vecs);
529 }
530
531 int
532 cli_add_map (void * v, char ** reply, int * len, void * data)
533 {
534         struct vectors * vecs = (struct vectors *)data;
535         char * param = get_keyparam(v, MAP);
536         int major, minor;
537         char dev_path[PATH_SIZE];
538         char *alias;
539         int rc;
540
541         param = convert_dev(param, 0);
542         condlog(2, "%s: add map (operator)", param);
543
544         if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0) {
545                 *reply = strdup("blacklisted\n");
546                 *len = strlen(*reply) + 1;
547                 condlog(2, "%s: map blacklisted", param);
548                 return 0;
549         }
550         minor = dm_get_minor(param);
551         if (minor < 0) {
552                 condlog(2, "%s: not a device mapper table", param);
553                 return 0;
554         }
555         major = dm_get_major(param);
556         if (major < 0) {
557                 condlog(2, "%s: not a device mapper table", param);
558                 return 0;
559         }
560         sprintf(dev_path,"dm-%d", minor);
561         alias = dm_mapname(major, minor);
562         if (!alias) {
563                 condlog(2, "%s: mapname not found for %d:%d",
564                         param, major, minor);
565                 return 0;
566         }
567         rc = ev_add_map(dev_path, alias, vecs);
568         FREE(alias);
569         return rc;
570 }
571
572 int
573 cli_del_map (void * v, char ** reply, int * len, void * data)
574 {
575         struct vectors * vecs = (struct vectors *)data;
576         char * param = get_keyparam(v, MAP);
577         int major, minor;
578         char dev_path[PATH_SIZE];
579         char *alias;
580         int rc;
581
582         param = convert_dev(param, 0);
583         condlog(2, "%s: remove map (operator)", param);
584         minor = dm_get_minor(param);
585         if (minor < 0) {
586                 condlog(2, "%s: not a device mapper table", param);
587                 return 0;
588         }
589         major = dm_get_major(param);
590         if (major < 0) {
591                 condlog(2, "%s: not a device mapper table", param);
592                 return 0;
593         }
594         sprintf(dev_path,"dm-%d", minor);
595         alias = dm_mapname(major, minor);
596         if (!alias) {
597                 condlog(2, "%s: mapname not found for %d:%d",
598                         param, major, minor);
599                 return 0;
600         }
601         rc = ev_remove_map(param, alias, minor, vecs);
602         FREE(alias);
603         return rc;
604 }
605
606 int
607 cli_reload(void *v, char **reply, int *len, void *data)
608 {
609         struct vectors * vecs = (struct vectors *)data;
610         char * mapname = get_keyparam(v, MAP);
611         struct multipath *mpp;
612         int minor;
613
614         mapname = convert_dev(mapname, 0);
615         condlog(2, "%s: reload map (operator)", mapname);
616         if (sscanf(mapname, "dm-%d", &minor) == 1)
617                 mpp = find_mp_by_minor(vecs->mpvec, minor);
618         else
619                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
620
621         if (!mpp) {
622                 condlog(0, "%s: invalid map name. cannot reload", mapname);
623                 return 1;
624         }
625
626         return reload_map(vecs, mpp, 0);
627 }
628
629 int resize_map(struct multipath *mpp, unsigned long long size,
630                struct vectors * vecs)
631 {
632         char params[PARAMS_SIZE] = {0};
633         unsigned long long orig_size = mpp->size;
634
635         mpp->size = size;
636         update_mpp_paths(mpp, vecs->pathvec);
637         setup_map(mpp, params, PARAMS_SIZE);
638         mpp->action = ACT_RESIZE;
639         if (domap(mpp, params) <= 0) {
640                 condlog(0, "%s: failed to resize map : %s", mpp->alias,
641                         strerror(errno));
642                 mpp->size = orig_size;
643                 return 1;
644         }
645         return 0;
646 }
647
648 int
649 cli_resize(void *v, char **reply, int *len, void *data)
650 {
651         struct vectors * vecs = (struct vectors *)data;
652         char * mapname = get_keyparam(v, MAP);
653         struct multipath *mpp;
654         int minor;
655         unsigned long long size;
656         struct pathgroup *pgp;
657         struct path *pp;
658
659         mapname = convert_dev(mapname, 0);
660         condlog(2, "%s: resize map (operator)", mapname);
661         if (sscanf(mapname, "dm-%d", &minor) == 1)
662                 mpp = find_mp_by_minor(vecs->mpvec, minor);
663         else
664                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
665
666         if (!mpp) {
667                 condlog(0, "%s: invalid map name. cannot resize", mapname);
668                 return 1;
669         }
670
671         pgp = VECTOR_SLOT(mpp->pg, 0);
672
673         if (!pgp){
674                 condlog(0, "%s: couldn't get path group. cannot resize",
675                         mapname);
676                 return 1;
677         }
678         pp = VECTOR_SLOT(pgp->paths, 0);
679
680         if (!pp){
681                 condlog(0, "%s: couldn't get path. cannot resize", mapname);
682                 return 1;
683         }
684         if (!pp->udev || sysfs_get_size(pp, &size)) {
685                 condlog(0, "%s: couldn't get size for sysfs. cannot resize",
686                         mapname);
687                 return 1;
688         }
689         if (size == mpp->size) {
690                 condlog(0, "%s: map is still the same size (%llu)", mapname,
691                         mpp->size);
692                 return 0;
693         }
694         condlog(3, "%s old size is %llu, new size is %llu", mapname, mpp->size,
695                 size);
696
697         if (resize_map(mpp, size, vecs) != 0)
698                 return 1;
699
700         dm_lib_release();
701         if (setup_multipath(vecs, mpp) != 0)
702                 return 1;
703         sync_map_state(mpp);
704
705         return 0;
706 }
707
708 int
709 cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data)
710 {
711         condlog(2, "force queue_without_daemon (operator)");
712         if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
713                 conf->queue_without_daemon = QUE_NO_DAEMON_FORCE;
714         return 0;
715 }
716
717 int
718 cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data)
719 {
720         condlog(2, "restore queue_without_daemon (operator)");
721         if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE)
722                 conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
723         return 0;
724 }
725
726 int
727 cli_restore_queueing(void *v, char **reply, int *len, void *data)
728 {
729         struct vectors * vecs = (struct vectors *)data;
730         char * mapname = get_keyparam(v, MAP);
731         struct multipath *mpp;
732         int minor;
733
734         mapname = convert_dev(mapname, 0);
735         condlog(2, "%s: restore map queueing (operator)", mapname);
736         if (sscanf(mapname, "dm-%d", &minor) == 1)
737                 mpp = find_mp_by_minor(vecs->mpvec, minor);
738         else
739                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
740
741         if (!mpp) {
742                 condlog(0, "%s: invalid map name, cannot restore queueing", mapname);
743                 return 1;
744         }
745
746         if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
747                         mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
748                 dm_queue_if_no_path(mpp->alias, 1);
749                 if (mpp->nr_active > 0)
750                         mpp->retry_tick = 0;
751                 else
752                         mpp->retry_tick = mpp->no_path_retry * conf->checkint;
753         }
754         return 0;
755 }
756
757 int
758 cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
759 {
760         struct vectors * vecs = (struct vectors *)data;
761         struct multipath *mpp;
762         int i;
763
764         condlog(2, "restore queueing (operator)");
765         vector_foreach_slot(vecs->mpvec, mpp, i) {
766                 if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
767                     mpp->no_path_retry != NO_PATH_RETRY_FAIL) {
768                         dm_queue_if_no_path(mpp->alias, 1);
769                         if (mpp->nr_active > 0)
770                                 mpp->retry_tick = 0;
771                         else
772                                 mpp->retry_tick = mpp->no_path_retry * conf->checkint;
773                 }
774         }
775         return 0;
776 }
777
778 int
779 cli_disable_queueing(void *v, char **reply, int *len, void *data)
780 {
781         struct vectors * vecs = (struct vectors *)data;
782         char * mapname = get_keyparam(v, MAP);
783         struct multipath *mpp;
784         int minor;
785
786         mapname = convert_dev(mapname, 0);
787         condlog(2, "%s: disable map queueing (operator)", mapname);
788         if (sscanf(mapname, "dm-%d", &minor) == 1)
789                 mpp = find_mp_by_minor(vecs->mpvec, minor);
790         else
791                 mpp = find_mp_by_alias(vecs->mpvec, mapname);
792
793         if (!mpp) {
794                 condlog(0, "%s: invalid map name, cannot disable queueing", mapname);
795                 return 1;
796         }
797
798         mpp->retry_tick = 0;
799         dm_queue_if_no_path(mpp->alias, 0);
800         return 0;
801 }
802
803 int
804 cli_disable_all_queueing(void *v, char **reply, int *len, void *data)
805 {
806         struct vectors * vecs = (struct vectors *)data;
807         struct multipath *mpp;
808         int i;
809
810         condlog(2, "disable queueing (operator)");
811         vector_foreach_slot(vecs->mpvec, mpp, i) {
812                 mpp->retry_tick = 0;
813                 dm_queue_if_no_path(mpp->alias, 0);
814         }
815         return 0;
816 }
817
818 int
819 cli_switch_group(void * v, char ** reply, int * len, void * data)
820 {
821         char * mapname = get_keyparam(v, MAP);
822         int groupnum = atoi(get_keyparam(v, GROUP));
823
824         mapname = convert_dev(mapname, 0);
825         condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
826
827         return dm_switchgroup(mapname, groupnum);
828 }
829
830 int
831 cli_reconfigure(void * v, char ** reply, int * len, void * data)
832 {
833         struct vectors * vecs = (struct vectors *)data;
834
835         condlog(2, "reconfigure (operator)");
836
837         return reconfigure(vecs);
838 }
839
840 int
841 cli_suspend(void * v, char ** reply, int * len, void * data)
842 {
843         struct vectors * vecs = (struct vectors *)data;
844         char * param = get_keyparam(v, MAP);
845         int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0, 0);
846
847         param = convert_dev(param, 0);
848         condlog(2, "%s: suspend (operator)", param);
849
850         if (!r) /* error */
851                 return 1;
852
853         struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
854
855         if (!mpp)
856                 return 1;
857
858         dm_get_info(param, &mpp->dmi);
859         return 0;
860 }
861
862 int
863 cli_resume(void * v, char ** reply, int * len, void * data)
864 {
865         struct vectors * vecs = (struct vectors *)data;
866         char * param = get_keyparam(v, MAP);
867         int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0, 0);
868
869         param = convert_dev(param, 0);
870         condlog(2, "%s: resume (operator)", param);
871
872         if (!r) /* error */
873                 return 1;
874
875         struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
876
877         if (!mpp)
878                 return 1;
879
880         dm_get_info(param, &mpp->dmi);
881         return 0;
882 }
883
884 int
885 cli_reinstate(void * v, char ** reply, int * len, void * data)
886 {
887         struct vectors * vecs = (struct vectors *)data;
888         char * param = get_keyparam(v, PATH);
889         struct path * pp;
890
891         param = convert_dev(param, 1);
892         pp = find_path_by_dev(vecs->pathvec, param);
893
894         if (!pp)
895                  pp = find_path_by_devt(vecs->pathvec, param);
896
897         if (!pp || !pp->mpp || !pp->mpp->alias)
898                 return 1;
899
900         condlog(2, "%s: reinstate path %s (operator)",
901                 pp->mpp->alias, pp->dev_t);
902
903         checker_enable(&pp->checker);
904         return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
905 }
906
907 int
908 cli_reassign (void * v, char ** reply, int * len, void * data)
909 {
910         char * param = get_keyparam(v, MAP);
911
912         param = convert_dev(param, 0);
913         condlog(3, "%s: reset devices (operator)", param);
914
915         dm_reassign(param);
916         return 0;
917 }
918
919 int
920 cli_fail(void * v, char ** reply, int * len, void * data)
921 {
922         struct vectors * vecs = (struct vectors *)data;
923         char * param = get_keyparam(v, PATH);
924         struct path * pp;
925         int r;
926
927         param = convert_dev(param, 1);
928         pp = find_path_by_dev(vecs->pathvec, param);
929
930         if (!pp)
931                  pp = find_path_by_devt(vecs->pathvec, param);
932
933         if (!pp || !pp->mpp || !pp->mpp->alias)
934                 return 1;
935
936         condlog(2, "%s: fail path %s (operator)",
937                 pp->mpp->alias, pp->dev_t);
938
939         r = dm_fail_path(pp->mpp->alias, pp->dev_t);
940         /*
941          * Suspend path checking to avoid auto-reinstating the path
942          */
943         if (!r)
944                 checker_disable(&pp->checker);
945         return r;
946 }
947
948 int
949 show_blacklist (char ** r, int * len)
950 {
951         char *c = NULL;
952         char *reply = NULL;
953         unsigned int maxlen = INITIAL_REPLY_LEN;
954         int again = 1;
955
956         reply = MALLOC(maxlen);
957
958         while (again) {
959                 if (!reply)
960                         return 1;
961
962                 c = reply;
963                 c += snprint_blacklist_report(c, maxlen);
964                 again = ((c - reply) == maxlen);
965                 REALLOC_REPLY(reply, again, maxlen);
966         }
967
968         *r = reply;
969         *len = (int)(c - reply + 1);
970
971         return 0;
972 }
973
974 int
975 cli_list_blacklist (void * v, char ** reply, int * len, void * data)
976 {
977         condlog(3, "list blacklist (operator)");
978
979         return show_blacklist(reply, len);
980 }
981
982 int
983 show_devices (char ** r, int * len, struct vectors *vecs)
984 {
985         char *c = NULL;
986         char *reply = NULL;
987         unsigned int maxlen = INITIAL_REPLY_LEN;
988         int again = 1;
989
990         reply = MALLOC(maxlen);
991
992         while (again) {
993                 if (!reply)
994                         return 1;
995
996                 c = reply;
997                 c += snprint_devices(c, maxlen, vecs);
998                 again = ((c - reply) == maxlen);
999                 REALLOC_REPLY(reply, again, maxlen);
1000         }
1001
1002         *r = reply;
1003         *len = (int)(c - reply + 1);
1004
1005         return 0;
1006 }
1007
1008 int
1009 cli_list_devices (void * v, char ** reply, int * len, void * data)
1010 {
1011         struct vectors * vecs = (struct vectors *)data;
1012
1013         condlog(3, "list devices (operator)");
1014
1015         return show_devices(reply, len, vecs);
1016 }
1017
1018 int
1019 cli_quit (void * v, char ** reply, int * len, void * data)
1020 {
1021         return 0;
1022 }
1023
1024 int
1025 cli_shutdown (void * v, char ** reply, int * len, void * data)
1026 {
1027         condlog(3, "shutdown (operator)");
1028         exit_daemon();
1029         return 0;
1030 }
1031
1032 int
1033 cli_getprstatus (void * v, char ** reply, int * len, void * data)
1034 {
1035         struct multipath * mpp;
1036         struct vectors * vecs = (struct vectors *)data;
1037         char * param = get_keyparam(v, MAP);
1038
1039         param = convert_dev(param, 0);
1040         get_path_layout(vecs->pathvec, 0);
1041         mpp = find_mp_by_str(vecs->mpvec, param);
1042
1043         if (!mpp)
1044                 return 1;
1045
1046         condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag);
1047
1048         *reply =(char *)malloc(2);
1049         *len = 2;
1050         memset(*reply,0,2);
1051
1052
1053         sprintf(*reply,"%d",mpp->prflag);
1054         (*reply)[1]='\0';
1055
1056
1057         condlog(3, "%s: reply = %s", param, *reply);
1058
1059         return 0;
1060 }
1061
1062 int
1063 cli_setprstatus(void * v, char ** reply, int * len, void * data)
1064 {
1065         struct multipath * mpp;
1066         struct vectors * vecs = (struct vectors *)data;
1067         char * param = get_keyparam(v, MAP);
1068
1069         param = convert_dev(param, 0);
1070         get_path_layout(vecs->pathvec, 0);
1071         mpp = find_mp_by_str(vecs->mpvec, param);
1072
1073         if (!mpp)
1074                 return 1;
1075
1076         if (!mpp->prflag) {
1077                 mpp->prflag = 1;
1078                 condlog(2, "%s: prflag set", param);
1079         }
1080
1081
1082         return 0;
1083 }
1084
1085 int
1086 cli_unsetprstatus(void * v, char ** reply, int * len, void * data)
1087 {
1088         struct multipath * mpp;
1089         struct vectors * vecs = (struct vectors *)data;
1090         char * param = get_keyparam(v, MAP);
1091
1092         param = convert_dev(param, 0);
1093         get_path_layout(vecs->pathvec, 0);
1094         mpp = find_mp_by_str(vecs->mpvec, param);
1095
1096         if (!mpp)
1097                 return 1;
1098
1099         if (mpp->prflag) {
1100                 mpp->prflag = 0;
1101                 condlog(2, "%s: prflag unset", param);
1102         }
1103
1104         return 0;
1105 }