Merge branch 'master' of git://git.kernel.org/pub/scm/linux/storage/multipath-tools/
[platform/upstream/multipath-tools.git] / libmultipath / devmapper.c
1 /*
2  * snippets copied from device-mapper dmsetup.c
3  * Copyright (c) 2004, 2005 Christophe Varoqui
4  * Copyright (c) 2005 Kiyoshi Ueda, NEC
5  * Copyright (c) 2005 Patrick Caulfield, Redhat
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <libdevmapper.h>
11 #include <ctype.h>
12 #include <linux/kdev_t.h>
13 #include <unistd.h>
14 #include <errno.h>
15
16 #include <checkers.h>
17
18 #include "vector.h"
19 #include "structs.h"
20 #include "debug.h"
21 #include "memory.h"
22 #include "devmapper.h"
23
24 #define MAX_WAIT 5
25 #define LOOPS_PER_SEC 5
26
27 #define UUID_PREFIX "mpath-"
28 #define UUID_PREFIX_LEN 6
29
30
31 static void
32 dm_dummy_log (int level, const char *file, int line, const char *f, ...)
33 {
34         return;
35 }
36
37 void
38 dm_restore_log (void)
39 {
40         dm_log_init(NULL);
41 }
42
43 void
44 dm_shut_log (void)
45 {
46         dm_log_init(&dm_dummy_log);
47 }
48
49 extern int
50 dm_prereq (char * str, int x, int y, int z)
51 {
52         int r = 2;
53         struct dm_task *dmt;
54         struct dm_versions *target;
55         struct dm_versions *last_target;
56
57         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
58                 return 3;
59
60         dm_task_no_open_count(dmt);
61
62         if (!dm_task_run(dmt)) {
63                 condlog(0, "Can not communicate with kernel DM");
64                 goto out;
65         }
66
67         target = dm_task_get_versions(dmt);
68
69         do {
70                 last_target = target;
71
72                 if (!strncmp(str, target->name, strlen(str))) {
73                         r--;
74                         
75                         if (target->version[0] >= x &&
76                             target->version[1] >= y &&
77                             target->version[2] >= z)
78                                 r--;
79
80                         break;
81                 }
82
83                 target = (void *) target + target->next;
84         } while (last_target != target);
85
86         if (r == 2)
87                 condlog(0, "DM multipath kernel driver not loaded");
88         else if (r == 1)
89                 condlog(0, "DM multipath kernel driver version too old");
90
91 out:
92         dm_task_destroy(dmt);
93         return r;
94 }
95
96 extern int
97 dm_simplecmd (int task, const char *name) {
98         int r = 0;
99         struct dm_task *dmt;
100
101         if (!(dmt = dm_task_create (task)))
102                 return 0;
103
104         if (!dm_task_set_name (dmt, name))
105                 goto out;
106
107         dm_task_no_open_count(dmt);
108         dm_task_skip_lockfs(dmt);       /* for DM_DEVICE_RESUME */
109
110         r = dm_task_run (dmt);
111
112         out:
113         dm_task_destroy (dmt);
114         return r;
115 }
116
117 extern int
118 dm_addmap (int task, const char *name, const char *target,
119            const char *params, unsigned long long size, const char *uuid) {
120         int r = 0;
121         struct dm_task *dmt;
122         char *prefixed_uuid = NULL;
123
124         if (!(dmt = dm_task_create (task)))
125                 return 0;
126
127         if (!dm_task_set_name (dmt, name))
128                 goto addout;
129
130         if (!dm_task_add_target (dmt, 0, size, target, params))
131                 goto addout;
132
133         if (uuid){
134                 prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
135                 if (!prefixed_uuid) {
136                         condlog(0, "cannot create prefixed uuid : %s\n",
137                                 strerror(errno));
138                         goto addout;
139                 }
140                 sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid);
141                 if (!dm_task_set_uuid(dmt, prefixed_uuid))
142                         goto freeout;
143         }
144
145         dm_task_no_open_count(dmt);
146
147         r = dm_task_run (dmt);
148
149         freeout:
150         if (prefixed_uuid)
151                 free(prefixed_uuid);
152
153         addout:
154         dm_task_destroy (dmt);
155         return r;
156 }
157
158 extern int
159 dm_map_present (char * str)
160 {
161         int r = 0;
162         struct dm_task *dmt;
163         struct dm_info info;
164
165         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
166                 return 0;
167
168         if (!dm_task_set_name(dmt, str))
169                 goto out;
170
171         dm_task_no_open_count(dmt);
172
173         if (!dm_task_run(dmt))
174                 goto out;
175
176         if (!dm_task_get_info(dmt, &info))
177                 goto out;
178
179         if (info.exists)
180                 r = 1;
181 out:
182         dm_task_destroy(dmt);
183         return r;
184 }
185
186 extern int
187 dm_get_map(char * name, unsigned long long * size, char * outparams)
188 {
189         int r = 1;
190         struct dm_task *dmt;
191         void *next = NULL;
192         uint64_t start, length;
193         char *target_type = NULL;
194         char *params = NULL;
195
196         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
197                 return 1;
198
199         if (!dm_task_set_name(dmt, name))
200                 goto out;
201
202         dm_task_no_open_count(dmt);
203
204         if (!dm_task_run(dmt))
205                 goto out;
206
207         /* Fetch 1st target */
208         next = dm_get_next_target(dmt, next, &start, &length,
209                                   &target_type, &params);
210
211         if (size)
212                 *size = length;
213
214         if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
215                 r = 0;
216 out:
217         dm_task_destroy(dmt);
218         return r;
219 }
220
221 extern int
222 dm_get_uuid(char *name, char *uuid)
223 {
224         struct dm_task *dmt;
225         const char *uuidtmp;
226         int r = 1;
227
228         dmt = dm_task_create(DM_DEVICE_INFO);
229         if (!dmt)
230                 return 1;
231
232         if (!dm_task_set_name (dmt, name))
233                 goto uuidout;
234
235         if (!dm_task_run(dmt))
236                 goto uuidout;
237
238         uuidtmp = dm_task_get_uuid(dmt);
239         if (uuidtmp) {
240                 if (!strncmp(uuidtmp, UUID_PREFIX, UUID_PREFIX_LEN))
241                         strcpy(uuid, uuidtmp + UUID_PREFIX_LEN);
242                 else
243                         strcpy(uuid, uuidtmp);
244         }
245         else
246                 uuid[0] = '\0';
247
248         r = 0;
249 uuidout:
250         dm_task_destroy(dmt);
251         return r;
252 }
253
254 extern int
255 dm_get_status(char * name, char * outstatus)
256 {
257         int r = 1;
258         struct dm_task *dmt;
259         void *next = NULL;
260         uint64_t start, length;
261         char *target_type;
262         char *status;
263
264         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
265                 return 1;
266
267         if (!dm_task_set_name(dmt, name))
268                 goto out;
269
270         dm_task_no_open_count(dmt);
271
272         if (!dm_task_run(dmt))
273                 goto out;
274
275         /* Fetch 1st target */
276         next = dm_get_next_target(dmt, next, &start, &length,
277                                   &target_type, &status);
278
279         if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
280                 r = 0;
281 out:
282         if (r)
283                 condlog(0, "%s: error getting map status string", name);
284
285         dm_task_destroy(dmt);
286         return r;
287 }
288
289 /*
290  * returns:
291  *    1 : match
292  *    0 : no match
293  *   -1 : empty map
294  */
295 extern int
296 dm_type(char * name, char * type)
297 {
298         int r = 0;
299         struct dm_task *dmt;
300         void *next = NULL;
301         uint64_t start, length;
302         char *target_type = NULL;
303         char *params;
304
305         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
306                 return 0;
307
308         if (!dm_task_set_name(dmt, name))
309                 goto out;
310
311         dm_task_no_open_count(dmt);
312
313         if (!dm_task_run(dmt))
314                 goto out;
315
316         /* Fetch 1st target */
317         next = dm_get_next_target(dmt, next, &start, &length,
318                                   &target_type, &params);
319
320         if (!target_type)
321                 r = -1;
322         else if (!strcmp(target_type, type))
323                 r = 1;
324
325 out:
326         dm_task_destroy(dmt);
327         return r;
328 }
329
330 static int
331 dm_dev_t (char * mapname, char * dev_t, int len)
332 {
333         int r = 1;
334         struct dm_task *dmt;
335         struct dm_info info;
336
337         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
338                 return 0;
339
340         if (!dm_task_set_name(dmt, mapname))
341                 goto out;
342
343         if (!dm_task_run(dmt))
344                 goto out;
345
346         if (!dm_task_get_info(dmt, &info))
347                 goto out;
348
349         r = info.open_count;
350         if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
351                     goto out;
352
353         r = 0;
354 out:
355         dm_task_destroy(dmt);
356         return r;
357 }
358         
359 int
360 dm_get_opencount (char * mapname)
361 {
362         int r = -1;
363         struct dm_task *dmt;
364         struct dm_info info;
365
366         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
367                 return 0;
368
369         if (!dm_task_set_name(dmt, mapname))
370                 goto out;
371
372         if (!dm_task_run(dmt))
373                 goto out;
374
375         if (!dm_task_get_info(dmt, &info))
376                 goto out;
377
378         r = info.open_count;
379 out:
380         dm_task_destroy(dmt);
381         return r;
382 }
383         
384 int
385 dm_get_minor (char * mapname)
386 {
387         int r = -1;
388         struct dm_task *dmt;
389         struct dm_info info;
390
391         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
392                 return 0;
393
394         if (!dm_task_set_name(dmt, mapname))
395                 goto out;
396
397         if (!dm_task_run(dmt))
398                 goto out;
399
400         if (!dm_task_get_info(dmt, &info))
401                 goto out;
402
403         r = info.minor;
404 out:
405         dm_task_destroy(dmt);
406         return r;
407 }
408         
409 extern int
410 dm_flush_map (char * mapname, char * type)
411 {
412         int r;
413
414         if (!dm_map_present(mapname))
415                 return 0;
416
417         if (dm_type(mapname, type) <= 0)
418                 return 1;
419
420         if (dm_remove_partmaps(mapname))
421                 return 1;
422
423         if (dm_get_opencount(mapname)) {
424                 condlog(2, "%s: map in use", mapname);
425                 return 1;
426         }       
427
428         r = dm_simplecmd(DM_DEVICE_REMOVE, mapname);
429
430         if (r) {
431                 condlog(4, "multipath map %s removed", mapname);
432                 return 0;
433         }
434         return 1;
435 }
436
437 extern int
438 dm_flush_maps (char * type)
439 {
440         int r = 0;
441         struct dm_task *dmt;
442         struct dm_names *names;
443         unsigned next = 0;
444
445         if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
446                 return 0;
447
448         dm_task_no_open_count(dmt);
449
450         if (!dm_task_run (dmt))
451                 goto out;
452
453         if (!(names = dm_task_get_names (dmt)))
454                 goto out;
455
456         if (!names->dev)
457                 goto out;
458
459         do {
460                 r += dm_flush_map(names->name, type);
461                 next = names->next;
462                 names = (void *) names + next;
463         } while (next);
464
465         out:
466         dm_task_destroy (dmt);
467         return r;
468 }
469
470 int
471 dm_message(char * mapname, char * message)
472 {
473         int r = 1;
474         struct dm_task *dmt;
475
476         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
477                 return 1;
478
479         if (!dm_task_set_name(dmt, mapname))
480                 goto out;
481
482         if (!dm_task_set_sector(dmt, 0))
483                 goto out;
484
485         if (!dm_task_set_message(dmt, message))
486                 goto out;
487
488         dm_task_no_open_count(dmt);
489
490         if (!dm_task_run(dmt))
491                 goto out;
492
493         r = 0;
494 out:
495         if (r)
496                 condlog(0, "DM message failed [%s]", message);
497
498         dm_task_destroy(dmt);
499         return r;
500 }
501
502 int
503 dm_fail_path(char * mapname, char * path)
504 {
505         char message[32];
506
507         if (snprintf(message, 32, "fail_path %s\n", path) > 32)
508                 return 1;
509
510         return dm_message(mapname, message);
511 }
512
513 int
514 dm_reinstate_path(char * mapname, char * path)
515 {
516         char message[32];
517
518         if (snprintf(message, 32, "reinstate_path %s\n", path) > 32)
519                 return 1;
520
521         return dm_message(mapname, message);
522 }
523
524 int
525 dm_queue_if_no_path(char *mapname, int enable)
526 {
527         char *message;
528
529         if (enable)
530                 message = "queue_if_no_path\n";
531         else
532                 message = "fail_if_no_path\n";
533
534         return dm_message(mapname, message);
535 }
536
537 static int
538 dm_groupmsg (char * msg, char * mapname, int index)
539 {
540         char message[32];
541
542         if (snprintf(message, 32, "%s_group %i\n", msg, index) > 32)
543                 return 1;
544
545         return dm_message(mapname, message);
546 }
547
548 int
549 dm_switchgroup(char * mapname, int index)
550 {
551         return dm_groupmsg("switch", mapname, index);
552 }
553
554 int
555 dm_enablegroup(char * mapname, int index)
556 {
557         return dm_groupmsg("enable", mapname, index);
558 }
559
560 int
561 dm_disablegroup(char * mapname, int index)
562 {
563         return dm_groupmsg("disable", mapname, index);
564 }
565
566 int
567 dm_get_maps (vector mp, char * type)
568 {
569         struct multipath * mpp;
570         int r = 1;
571         int info;
572         struct dm_task *dmt;
573         struct dm_names *names;
574         unsigned next = 0;
575
576         if (!type || !mp)
577                 return 1;
578
579         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
580                 return 1;
581
582         dm_task_no_open_count(dmt);
583
584         if (!dm_task_run(dmt))
585                 goto out;
586
587         if (!(names = dm_task_get_names(dmt)))
588                 goto out;
589
590         if (!names->dev) {
591                 r = 0; /* this is perfectly valid */
592                 goto out;
593         }
594
595         do {
596                 info = dm_type(names->name, type);
597
598                 if (info <= 0)
599                         goto next;
600
601                 mpp = alloc_multipath();
602
603                 if (!mpp)
604                         goto out;
605
606                 mpp->alias = STRDUP(names->name);
607
608                 if (!mpp->alias)
609                         goto out1;
610
611                 if (info > 0) {
612                         if (dm_get_map(names->name, &mpp->size, mpp->params))
613                                 goto out1;
614
615                         if (dm_get_status(names->name, mpp->status))
616                                 goto out1;
617
618                         dm_get_uuid(names->name, mpp->wwid);
619                         dm_get_info(names->name, &mpp->dmi);
620                 }
621
622                 if (!vector_alloc_slot(mp))
623                         goto out1;
624
625                 vector_set_slot(mp, mpp);
626                 mpp = NULL;
627 next:
628                 next = names->next;
629                 names = (void *) names + next;
630         } while (next);
631
632         r = 0;
633         goto out;
634 out1:
635         free_multipath(mpp, KEEP_PATHS);
636 out:
637         dm_task_destroy (dmt);
638         return r;
639 }
640
641 extern int
642 dm_get_name(char *uuid, char *type, char *name)
643 {
644         vector vec;
645         struct multipath *mpp;
646         int i;
647
648         vec = vector_alloc();
649
650         if (!vec)
651                 return 0;
652
653         if (dm_get_maps(vec, type)) {
654                 vector_free(vec);
655                 return 0;
656         }
657
658         vector_foreach_slot(vec, mpp, i) {
659                 if (!strcmp(uuid, mpp->wwid)) {
660                         vector_free(vec);
661                         strcpy(name, mpp->alias);
662                         return 1;
663                 }
664         }
665
666         vector_free(vec);
667         return 0;
668 }
669
670 int
671 dm_geteventnr (char *name)
672 {
673         struct dm_task *dmt;
674         struct dm_info info;
675
676         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
677                 return 0;
678
679         if (!dm_task_set_name(dmt, name))
680                 goto out;
681
682         dm_task_no_open_count(dmt);
683
684         if (!dm_task_run(dmt))
685                 goto out;
686
687         if (!dm_task_get_info(dmt, &info)) {
688                 info.event_nr = 0;
689                 goto out;
690         }
691
692         if (!info.exists) {
693                 info.event_nr = 0;
694                 goto out;
695         }
696
697 out:
698         dm_task_destroy(dmt);
699
700         return info.event_nr;
701 }
702
703 char *
704 dm_mapname(int major, int minor)
705 {
706         char * response = NULL;
707         const char *map;
708         struct dm_task *dmt;
709         int r;
710         int loop = MAX_WAIT * LOOPS_PER_SEC;
711
712         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
713                 return NULL;
714
715         if (!dm_task_set_major(dmt, major) ||
716             !dm_task_set_minor(dmt, minor))
717                 goto bad;
718
719         dm_task_no_open_count(dmt);
720
721         /*
722          * device map might not be ready when we get here from
723          * daemon uev_trigger -> uev_add_map
724          */
725         while (--loop) {
726                 dm_shut_log();
727                 r = dm_task_run(dmt);
728                 dm_restore_log();
729
730                 if (r)
731                         break;
732
733                 usleep(1000 * 1000 / LOOPS_PER_SEC);
734         }
735
736         if (!r) {
737                 condlog(0, "%i:%i: timeout fetching map name", major, minor);
738                 goto bad;
739         }
740
741         map = dm_task_get_name(dmt);
742         if (map && strlen(map))
743                 response = STRDUP((char *)dm_task_get_name(dmt));
744
745         dm_task_destroy(dmt);
746         return response;
747 bad:
748         dm_task_destroy(dmt);
749         condlog(0, "%i:%i: error fetching map name", major, minor);
750         return NULL;
751 }
752
753 int
754 dm_remove_partmaps (char * mapname)
755 {
756         struct dm_task *dmt;
757         struct dm_names *names;
758         unsigned next = 0;
759         char params[PARAMS_SIZE];
760         unsigned long long size;
761         char dev_t[32];
762         int r = 1;
763
764         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
765                 return 1;
766
767         dm_task_no_open_count(dmt);
768
769         if (!dm_task_run(dmt))
770                 goto out;
771
772         if (!(names = dm_task_get_names(dmt)))
773                 goto out;
774
775         if (!names->dev) {
776                 r = 0; /* this is perfectly valid */
777                 goto out;
778         }
779
780         if (dm_dev_t(mapname, &dev_t[0], 32))
781                 goto out;
782
783         do {
784                 if (
785                     /*
786                      * if devmap target is "linear"
787                      */
788                     (dm_type(names->name, "linear") > 0) &&
789
790                     /*
791                      * and the multipath mapname and the part mapname start
792                      * the same
793                      */
794                     !strncmp(names->name, mapname, strlen(mapname)) &&
795
796                     /*
797                      * and the opencount is 0 for us to allow removal
798                      */
799                     !dm_get_opencount(names->name) &&
800
801                     /*
802                      * and we can fetch the map table from the kernel
803                      */
804                     !dm_get_map(names->name, &size, &params[0]) &&
805
806                     /*
807                      * and the table maps over the multipath map
808                      */
809                     strstr(params, dev_t)
810                    ) {
811                                 /*
812                                  * then it's a kpartx generated partition.
813                                  * remove it.
814                                  */
815                                 condlog(4, "partition map %s removed",
816                                         names->name);
817                                 dm_simplecmd(DM_DEVICE_REMOVE, names->name);
818                    }
819
820                 next = names->next;
821                 names = (void *) names + next;
822         } while (next);
823
824         r = 0;
825 out:
826         dm_task_destroy (dmt);
827         return r;
828 }
829
830 static struct dm_info *
831 alloc_dminfo (void)
832 {
833         return MALLOC(sizeof(struct dm_info));
834 }
835
836 int
837 dm_get_info (char * mapname, struct dm_info ** dmi)
838 {
839         int r = 1;
840         struct dm_task *dmt = NULL;
841         
842         if (!mapname)
843                 return 1;
844
845         if (!*dmi)
846                 *dmi = alloc_dminfo();
847
848         if (!*dmi)
849                 return 1;
850
851         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
852                 goto out;
853
854         if (!dm_task_set_name(dmt, mapname))
855                 goto out;
856
857         dm_task_no_open_count(dmt);
858
859         if (!dm_task_run(dmt))
860                 goto out;
861
862         if (!dm_task_get_info(dmt, *dmi))
863                 goto out;
864
865         r = 0;
866 out:
867         if (r)
868                 memset(*dmi, 0, sizeof(struct dm_info));
869
870         if (dmt)
871                 dm_task_destroy(dmt);
872
873         return r;
874 }
875
876 int
877 dm_rename_partmaps (char * old, char * new)
878 {
879         struct dm_task *dmt;
880         struct dm_names *names;
881         unsigned next = 0;
882         char buff[PARAMS_SIZE];
883         unsigned long long size;
884         char dev_t[32];
885         int r = 1;
886
887         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
888                 return 1;
889
890         dm_task_no_open_count(dmt);
891
892         if (!dm_task_run(dmt))
893                 goto out;
894
895         if (!(names = dm_task_get_names(dmt)))
896                 goto out;
897
898         if (!names->dev) {
899                 r = 0; /* this is perfectly valid */
900                 goto out;
901         }
902
903         if (dm_dev_t(old, &dev_t[0], 32))
904                 goto out;
905
906         do {
907                 if (
908                     /*
909                      * if devmap target is "linear"
910                      */
911                     (dm_type(names->name, "linear") > 0) &&
912
913                     /*
914                      * and the multipath mapname and the part mapname start
915                      * the same
916                      */
917                     !strncmp(names->name, old, strlen(old)) &&
918
919                     /*
920                      * and we can fetch the map table from the kernel
921                      */
922                     !dm_get_map(names->name, &size, &buff[0]) &&
923
924                     /*
925                      * and the table maps over the multipath map
926                      */
927                     strstr(buff, dev_t)
928                    ) {
929                                 /*
930                                  * then it's a kpartx generated partition.
931                                  * Rename it.
932                                  */
933                                 snprintf(buff, PARAMS_SIZE, "%s%s",
934                                          new, names->name + strlen(old));
935                                 dm_rename(names->name, buff);
936                                 condlog(4, "partition map %s renamed",
937                                         names->name);
938                    }
939
940                 next = names->next;
941                 names = (void *) names + next;
942         } while (next);
943
944         r = 0;
945 out:
946         dm_task_destroy (dmt);
947         return r;
948 }
949
950 int
951 dm_rename (char * old, char * new)
952 {
953         int r = 0;
954         struct dm_task *dmt;
955
956         if (dm_rename_partmaps(old, new))
957                 return r;
958
959         if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
960                 return r;
961
962         if (!dm_task_set_name(dmt, old))
963                 goto out;
964
965         if (!dm_task_set_newname(dmt, new))
966                 goto out;
967         
968         dm_task_no_open_count(dmt);
969
970         if (!dm_task_run(dmt))
971                 goto out;
972
973         r = 1;
974 out:
975         dm_task_destroy(dmt);
976         return r;
977 }