36a49685967be371cb849ae4c7079858253299d4
[platform/upstream/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 <config.h>
12 #include <configure.h>
13 #include <blacklist.h>
14 #include <debug.h>
15 #include <print.h>
16 #include <sysfs.h>
17
18 #include "main.h"
19 #include "cli.h"
20
21 int
22 show_paths (char ** r, int * len, struct vectors * vecs, char * style)
23 {
24         int i;
25         struct path * pp;
26         char * c;
27         char * reply;
28         unsigned int maxlen = INITIAL_REPLY_LEN;
29         int again = 1;
30
31         get_path_layout(vecs->pathvec, 1);
32         reply = MALLOC(maxlen);
33
34         while (again) {
35                 if (!reply)
36                         return 1;
37
38                 c = reply;
39
40                 if (VECTOR_SIZE(vecs->pathvec) > 0)
41                         c += snprint_path_header(c, reply + maxlen - c,
42                                                  style);
43
44                 vector_foreach_slot(vecs->pathvec, pp, i)
45                         c += snprint_path(c, reply + maxlen - c,
46                                           style, pp);
47
48                 again = ((c - reply) == (maxlen - 1));
49
50                 if (again)
51                         reply = REALLOC(reply, maxlen *= 2);
52
53         }
54         *r = reply;
55         *len = (int)(c - reply + 1);
56         return 0;
57 }
58
59 int
60 show_map_topology (char ** r, int * len, struct multipath * mpp)
61 {
62         char * c;
63         char * reply;
64         unsigned int maxlen = INITIAL_REPLY_LEN;
65         int again = 1;
66
67         reply = MALLOC(maxlen);
68
69         while (again) {
70                 if (!reply)
71                         return 1;
72
73                 c = reply;
74
75                 c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
76                 again = ((c - reply) == (maxlen - 1));
77
78                 if (again)
79                         reply = REALLOC(reply, maxlen *= 2);
80
81         }
82         *r = reply;
83         *len = (int)(c - reply + 1);
84         return 0;
85 }
86
87 int
88 show_maps_topology (char ** r, int * len, struct vectors * vecs)
89 {
90         int i;
91         struct multipath * mpp;
92         char * c;
93         char * reply;
94         unsigned int maxlen = INITIAL_REPLY_LEN;
95         int again = 1;
96  
97         get_path_layout(vecs->pathvec, 0);
98         reply = MALLOC(maxlen);
99
100         while (again) {
101                 if (!reply)
102                         return 1;
103
104                 c = reply;
105
106                 vector_foreach_slot(vecs->mpvec, mpp, i)
107                         c += snprint_multipath_topology(c, reply + maxlen - c,
108                                                         mpp, 2);
109
110                 again = ((c - reply) == (maxlen - 1));
111
112                 if (again)
113                         reply = REALLOC(reply, maxlen *= 2);
114
115         }
116         *r = reply;
117         *len = (int)(c - reply + 1);
118         return 0;
119 }
120
121 int
122 show_config (char ** r, int * len)
123 {
124         char * c;
125         char * reply;
126         unsigned int maxlen = INITIAL_REPLY_LEN;
127         int again = 1;
128
129         reply = MALLOC(maxlen);
130
131         while (again) {
132                 if (!reply)
133                         return 1;
134                 c = reply;
135                 c += snprint_defaults(c, reply + maxlen - c);
136                 again = ((c - reply) == maxlen);
137                 if (again) {
138                         reply = REALLOC(reply, maxlen *= 2);
139                         continue;
140                 }
141                 c += snprint_blacklist(c, reply + maxlen - c);
142                 again = ((c - reply) == maxlen);
143                 if (again) {
144                         reply = REALLOC(reply, maxlen *= 2);
145                         continue;
146                 }
147                 c += snprint_blacklist_except(c, reply + maxlen - c);
148                 again = ((c - reply) == maxlen);
149                 if (again) {
150                         reply = REALLOC(reply, maxlen *= 2);
151                         continue;
152                 }
153                 c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
154                 again = ((c - reply) == maxlen);
155                 if (again) {
156                         reply = REALLOC(reply, maxlen *= 2);
157                         continue;
158                 }
159                 c += snprint_mptable(c, reply + maxlen - c, conf->mptable);
160                 again = ((c - reply) == maxlen);
161                 if (again)
162                         reply = REALLOC(reply, maxlen *= 2);
163         }
164         *r = reply;
165         *len = (int)(c - reply + 1);
166         return 0;
167 }
168
169 int
170 cli_list_config (void * v, char ** reply, int * len, void * data)
171 {
172         condlog(3, "list config (operator)");
173
174         return show_config(reply, len);
175 }
176
177 int
178 cli_list_paths (void * v, char ** reply, int * len, void * data)
179 {
180         struct vectors * vecs = (struct vectors *)data;
181
182         condlog(3, "list paths (operator)");
183
184         return show_paths(reply, len, vecs, PRINT_PATH_CHECKER);
185 }
186
187 int
188 cli_list_paths_fmt (void * v, char ** reply, int * len, void * data)
189 {
190         struct vectors * vecs = (struct vectors *)data;
191         char * fmt = get_keyparam(v, FMT);
192
193         condlog(3, "list paths (operator)");
194
195         return show_paths(reply, len, vecs, fmt);
196 }
197
198 int
199 cli_list_map_topology (void * v, char ** reply, int * len, void * data)
200 {
201         struct multipath * mpp;
202         struct vectors * vecs = (struct vectors *)data;
203         char * param = get_keyparam(v, MAP);
204         
205         get_path_layout(vecs->pathvec, 0);
206         mpp = find_mp_by_str(vecs->mpvec, param);
207
208         if (!mpp)
209                 return 1;
210
211         condlog(3, "list multipath %s (operator)", param);
212
213         return show_map_topology(reply, len, mpp);
214 }
215
216 int
217 cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
218 {
219         struct vectors * vecs = (struct vectors *)data;
220
221         condlog(3, "list multipaths (operator)");
222
223         return show_maps_topology(reply, len, vecs);
224 }
225
226 int
227 cli_list_wildcards (void * v, char ** reply, int * len, void * data)
228 {
229         char * c;
230
231         *reply = MALLOC(INITIAL_REPLY_LEN);
232
233         if (!reply)
234                 return 1;
235
236         c = *reply;
237         c += snprint_wildcards(c, INITIAL_REPLY_LEN);
238
239         *len = INITIAL_REPLY_LEN;
240         return 0;
241 }
242
243 int
244 show_status (char ** r, int *len, struct vectors * vecs)
245 {
246         char * c;
247         char * reply;
248
249         unsigned int maxlen = INITIAL_REPLY_LEN;
250         reply = MALLOC(maxlen);
251
252         if (!reply)
253                 return 1;
254
255         c = reply;
256         c += snprint_status(c, reply + maxlen - c, vecs);
257
258         *r = reply;
259         *len = (int)(c - reply + 1);
260         return 0;
261 }
262
263 int
264 show_maps (char ** r, int *len, struct vectors * vecs, char * style)
265 {
266         int i;
267         struct multipath * mpp;
268         char * c;
269         char * reply;
270         unsigned int maxlen = INITIAL_REPLY_LEN;
271         int again = 1;
272
273         get_multipath_layout(vecs->mpvec, 1);
274         reply = MALLOC(maxlen);
275
276         while (again) {
277                 if (!reply)
278                         return 1;
279
280                 c = reply;
281                 if (VECTOR_SIZE(vecs->mpvec) > 0)
282                         c += snprint_multipath_header(c, reply + maxlen - c,
283                                                       style);
284
285                 vector_foreach_slot(vecs->mpvec, mpp, i)
286                         c += snprint_multipath(c, reply + maxlen - c,
287                                                style, mpp);
288
289                 again = ((c - reply) == (maxlen - 1));
290
291                 if (again)
292                         reply = REALLOC(reply, maxlen *= 2);
293         }
294         *r = reply;
295         *len = (int)(c - reply + 1);
296         return 0;
297 }
298
299 int
300 cli_list_maps (void * v, char ** reply, int * len, void * data)
301 {
302         struct vectors * vecs = (struct vectors *)data;
303
304         condlog(3, "list maps (operator)");
305
306         return show_maps(reply, len, vecs, PRINT_MAP_NAMES);
307 }
308
309 int
310 cli_list_status (void * v, char ** reply, int * len, void * data)
311 {
312         struct vectors * vecs = (struct vectors *)data;
313
314         condlog(3, "list status (operator)");
315
316         return show_status(reply, len, vecs);
317 }
318
319 int
320 cli_list_maps_status (void * v, char ** reply, int * len, void * data)
321 {
322         struct vectors * vecs = (struct vectors *)data;
323
324         condlog(3, "list maps status (operator)");
325
326         return show_maps(reply, len, vecs, PRINT_MAP_STATUS);
327 }
328
329 int
330 cli_list_maps_stats (void * v, char ** reply, int * len, void * data)
331 {
332         struct vectors * vecs = (struct vectors *)data;
333
334         condlog(3, "list maps stats (operator)");
335
336         return show_maps(reply, len, vecs, PRINT_MAP_STATS);
337 }
338
339 int
340 cli_add_path (void * v, char ** reply, int * len, void * data)
341 {
342         struct vectors * vecs = (struct vectors *)data;
343         char * param = get_keyparam(v, PATH);
344         int r;
345
346         condlog(2, "%s: add path (operator)", param);
347
348         if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
349             param) > 0 || (r = ev_add_path(param, vecs)) == 2) {
350                 *reply = strdup("blacklisted");
351                 *len = strlen(*reply) + 1;
352                 condlog(2, "%s: path blacklisted", param);
353                 return 0;
354         }
355         return r;
356 }
357
358 int
359 cli_del_path (void * v, char ** reply, int * len, void * data)
360 {
361         struct vectors * vecs = (struct vectors *)data;
362         char * param = get_keyparam(v, PATH);
363
364         condlog(2, "%s: remove path (operator)", param);
365
366         return ev_remove_path(param, vecs);
367 }
368
369 int
370 cli_add_map (void * v, char ** reply, int * len, void * data)
371 {
372         struct vectors * vecs = (struct vectors *)data;
373         char * param = get_keyparam(v, MAP);
374         int minor;
375         char dev_path[PATH_SIZE];
376         struct sysfs_device *sysdev;
377
378         condlog(2, "%s: add map (operator)", param);
379
380         if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param) > 0) {
381                 *reply = strdup("blacklisted");
382                 *len = strlen(*reply) + 1;
383                 condlog(2, "%s: map blacklisted", param);
384                 return 0;
385         }
386         minor = dm_get_minor(param);
387         if (minor < 0) {
388                 condlog(2, "%s: not a device mapper table", param);
389                 return 0;
390         }
391         sprintf(dev_path,"/block/dm-%d", minor);
392         sysdev = sysfs_device_get(dev_path);
393         if (!sysdev) {
394                 condlog(2, "%s: not found in sysfs", param);
395                 return 0;
396         }
397         return ev_add_map(sysdev, vecs);
398 }
399
400 int
401 cli_del_map (void * v, char ** reply, int * len, void * data)
402 {
403         struct vectors * vecs = (struct vectors *)data;
404         char * param = get_keyparam(v, MAP);
405
406         condlog(2, "%s: remove map (operator)", param);
407
408         return ev_remove_map(param, vecs);
409 }
410
411 int
412 cli_switch_group(void * v, char ** reply, int * len, void * data)
413 {
414         char * mapname = get_keyparam(v, MAP);
415         int groupnum = atoi(get_keyparam(v, GROUP));
416         
417         condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum);
418
419         return dm_switchgroup(mapname, groupnum);
420 }
421
422 int
423 cli_reconfigure(void * v, char ** reply, int * len, void * data)
424 {
425         struct vectors * vecs = (struct vectors *)data;
426                         
427         condlog(2, "reconfigure (operator)");
428
429         return reconfigure(vecs);
430 }
431
432 int
433 cli_suspend(void * v, char ** reply, int * len, void * data)
434 {
435         struct vectors * vecs = (struct vectors *)data;
436         char * param = get_keyparam(v, MAP);
437         int r = dm_simplecmd(DM_DEVICE_SUSPEND, param);
438
439         condlog(2, "%s: suspend (operator)", param);
440
441         if (!r) /* error */
442                 return 1;
443         
444         struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
445
446         if (!mpp)
447                 return 1;
448         
449         dm_get_info(param, &mpp->dmi);
450         return 0;
451 }
452
453 int
454 cli_resume(void * v, char ** reply, int * len, void * data)
455 {
456         struct vectors * vecs = (struct vectors *)data;
457         char * param = get_keyparam(v, MAP);
458         int r = dm_simplecmd(DM_DEVICE_RESUME, param);
459
460         condlog(2, "%s: resume (operator)", param);
461
462         if (!r) /* error */
463                 return 1;
464         
465         struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param);
466
467         if (!mpp)
468                 return 1;
469         
470         dm_get_info(param, &mpp->dmi);
471         return 0;
472 }
473
474 int
475 cli_reinstate(void * v, char ** reply, int * len, void * data)
476 {
477         struct vectors * vecs = (struct vectors *)data;
478         char * param = get_keyparam(v, PATH);
479         struct path * pp;
480         
481         pp = find_path_by_dev(vecs->pathvec, param);
482
483         if (!pp)
484                  pp = find_path_by_devt(vecs->pathvec, param);
485
486         if (!pp || !pp->mpp || !pp->mpp->alias)
487                 return 1;
488
489         condlog(2, "%s: reinstate path %s (operator)",
490                 pp->mpp->alias, pp->dev_t);
491
492         checker_enable(&pp->checker);
493         return dm_reinstate_path(pp->mpp->alias, pp->dev_t);
494 }
495
496 int
497 cli_fail(void * v, char ** reply, int * len, void * data)
498 {
499         struct vectors * vecs = (struct vectors *)data;
500         char * param = get_keyparam(v, PATH);
501         struct path * pp;
502         int r;
503         
504         pp = find_path_by_dev(vecs->pathvec, param);
505
506         if (!pp)
507                  pp = find_path_by_devt(vecs->pathvec, param);
508
509         if (!pp || !pp->mpp || !pp->mpp->alias)
510                 return 1;
511
512         condlog(2, "%s: fail path %s (operator)",
513                 pp->mpp->alias, pp->dev_t);
514
515         r = dm_fail_path(pp->mpp->alias, pp->dev_t);
516         /*
517          * Suspend path checking to avoid auto-reinstating the path
518          */
519         if (!r)
520                 checker_disable(&pp->checker);
521         return r;
522 }
523
524 int
525 show_blacklist (char ** r, int * len)
526 {
527         char *c = NULL;
528         char *reply = NULL;
529         unsigned int maxlen = INITIAL_REPLY_LEN;
530         int again = 1;
531
532         while (again) {
533                 reply = MALLOC(maxlen);
534                 if (!reply)
535                         return 1;
536
537                 c = reply;
538                 c += snprint_blacklist_report(c, maxlen);
539                 again = ((c - reply) == maxlen);
540                 if (again) {
541                         maxlen  *= 2;
542                         FREE(reply);
543                         continue;
544                 }
545         }
546
547         *r = reply;
548         *len = (int)(c - reply + 1);
549
550         return 0;
551 }
552
553 int
554 cli_list_blacklist (void * v, char ** reply, int * len, void * data)
555 {
556         condlog(3, "list blacklist (operator)");
557
558         return show_blacklist(reply, len);
559 }
560
561 int
562 show_devices (char ** r, int * len, struct vectors *vecs)
563 {
564         char *c = NULL;
565         char *reply = NULL;
566         unsigned int maxlen = INITIAL_REPLY_LEN;
567         int again = 1;
568
569         while (again) {
570                 reply = MALLOC(maxlen);
571                 if (!reply)
572                         return 1;
573
574                 c = reply;
575                 c += snprint_devices(c, maxlen, vecs);
576                 again = ((c - reply) == maxlen);
577                 if (again) {
578                         maxlen  *= 2;
579                         FREE(reply);
580                         continue;
581                 }
582         }
583
584         *r = reply;
585         *len = (int)(c - reply + 1);
586
587         return 0;
588 }
589
590 int
591 cli_list_devices (void * v, char ** reply, int * len, void * data)
592 {
593         struct vectors * vecs = (struct vectors *)data;
594
595         condlog(3, "list devices (operator)");
596
597         return show_devices(reply, len, vecs);
598 }