multipath: reset queue_if_no_path if flush failed
[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 <stdarg.h>
10 #include <string.h>
11 #include <libdevmapper.h>
12 #include <ctype.h>
13 #include <unistd.h>
14 #include <errno.h>
15
16 #include "checkers.h"
17 #include "vector.h"
18 #include "structs.h"
19 #include "debug.h"
20 #include "memory.h"
21 #include "devmapper.h"
22 #include "config.h"
23 #include "sysfs.h"
24
25 #include "log_pthread.h"
26 #include <sys/types.h>
27 #include <time.h>
28
29 #define MAX_WAIT 5
30 #define LOOPS_PER_SEC 5
31
32 #define UUID_PREFIX "mpath-"
33 #define UUID_PREFIX_LEN 6
34
35 #ifndef LIBDM_API_COOKIE
36 static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a)
37 {
38         return 1;
39 }
40
41 void udev_wait(unsigned int c)
42 {
43 }
44
45 void udev_set_sync_support(int c)
46 {
47 }
48 #else
49 void udev_wait(unsigned int c)
50 {
51         dm_udev_wait(c);
52 }
53
54 void udev_set_sync_support(int c)
55 {
56         dm_udev_set_sync_support(c);
57 }
58 #endif
59
60 static void
61 dm_write_log (int level, const char *file, int line, const char *f, ...)
62 {
63         va_list ap;
64         int thres;
65
66         if (level > 6)
67                 level = 6;
68
69         thres = (conf) ? conf->verbosity : 0;
70         if (thres <= 3 || level > thres)
71                 return;
72
73         va_start(ap, f);
74         if (!logsink) {
75                 time_t t = time(NULL);
76                 struct tm *tb = localtime(&t);
77                 char buff[16];
78
79                 strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb);
80                 buff[sizeof(buff)-1] = '\0';
81
82                 fprintf(stdout, "%s | ", buff);
83                 fprintf(stdout, "libdevmapper: %s(%i): ", file, line);
84                 vfprintf(stdout, f, ap);
85                 fprintf(stdout, "\n");
86         } else {
87                 condlog(level, "libdevmapper: %s(%i): ", file, line);
88                 log_safe(level + 3, f, ap);
89         }
90         va_end(ap);
91
92         return;
93 }
94
95 extern void
96 dm_init(void) {
97         dm_log_init(&dm_write_log);
98         dm_log_init_verbose(conf ? conf->verbosity + 3 : 0);
99 }
100
101 static int
102 dm_lib_prereq (void)
103 {
104         char version[64];
105         int v[3];
106 #ifdef LIBDM_API_COOKIE
107         int minv[3] = {1, 2, 38};
108 #else
109         int minv[3] = {1, 2, 8};
110 #endif
111
112         dm_get_library_version(version, sizeof(version));
113         condlog(3, "libdevmapper version %s", version);
114         sscanf(version, "%d.%d.%d ", &v[0], &v[1], &v[2]);
115
116         if VERSION_GE(v, minv)
117                 return 0;
118         condlog(0, "libdevmapper version must be >= %d.%.2d.%.2d",
119                 minv[0], minv[1], minv[2]);
120         return 1;
121 }
122
123 int
124 dm_drv_version (unsigned int * version, char * str)
125 {
126         int r = 2;
127         struct dm_task *dmt;
128         struct dm_versions *target;
129         struct dm_versions *last_target;
130         unsigned int *v;
131
132         version[0] = 0;
133         version[1] = 0;
134         version[2] = 0;
135
136         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
137                 return 1;
138
139         dm_task_no_open_count(dmt);
140
141         if (!dm_task_run(dmt)) {
142                 condlog(0, "Can not communicate with kernel DM");
143                 goto out;
144         }
145         target = dm_task_get_versions(dmt);
146
147         do {
148                 last_target = target;
149                 if (!strncmp(str, target->name, strlen(str))) {
150                         r = 1;
151                         break;
152                 }
153                 target = (void *) target + target->next;
154         } while (last_target != target);
155
156         if (r == 2) {
157                 condlog(0, "DM %s kernel driver not loaded", str);
158                 goto out;
159         }
160         v = target->version;
161         version[0] = v[0];
162         version[1] = v[1];
163         version[2] = v[2];
164         r = 0;
165 out:
166         dm_task_destroy(dmt);
167         return r;
168 }
169
170 static int
171 dm_drv_prereq (void)
172 {
173         unsigned int minv[3] = {1, 0, 3};
174         unsigned int version[3] = {0, 0, 0};
175         unsigned int * v = version;
176
177         if (dm_drv_version(v, TGT_MPATH)) {
178                 /* in doubt return not capable */
179                 return 1;
180         }
181
182         /* test request based multipath capability */
183         condlog(3, "DM multipath kernel driver v%u.%u.%u",
184                 v[0], v[1], v[2]);
185
186         if VERSION_GE(v, minv)
187                 return 0;
188
189         condlog(0, "DM multipath kernel driver must be >= v%u.%u.%u",
190                 minv[0], minv[1], minv[2]);
191         return 1;
192 }
193
194 extern int
195 dm_prereq (void)
196 {
197         if (dm_lib_prereq())
198                 return 1;
199         return dm_drv_prereq();
200 }
201
202 static int
203 dm_simplecmd (int task, const char *name, int no_flush, int need_sync) {
204         int r = 0;
205         int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME ||
206                                             task == DM_DEVICE_REMOVE));
207         struct dm_task *dmt;
208
209         if (!(dmt = dm_task_create (task)))
210                 return 0;
211
212         if (!dm_task_set_name (dmt, name))
213                 goto out;
214
215         dm_task_no_open_count(dmt);
216         dm_task_skip_lockfs(dmt);       /* for DM_DEVICE_RESUME */
217 #ifdef LIBDM_API_FLUSH
218         if (no_flush)
219                 dm_task_no_flush(dmt);          /* for DM_DEVICE_SUSPEND/RESUME */
220 #endif
221
222         if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
223                 goto out;
224         r = dm_task_run (dmt);
225
226         out:
227         dm_task_destroy (dmt);
228         return r;
229 }
230
231 extern int
232 dm_simplecmd_flush (int task, const char *name, int needsync) {
233         return dm_simplecmd(task, name, 0, needsync);
234 }
235
236 extern int
237 dm_simplecmd_noflush (int task, const char *name) {
238         return dm_simplecmd(task, name, 1, 1);
239 }
240
241 extern int
242 dm_addmap (int task, const char *target, struct multipath *mpp, char * params,
243            int use_uuid, int ro) {
244         int r = 0;
245         struct dm_task *dmt;
246         char *prefixed_uuid = NULL;
247
248         if (!(dmt = dm_task_create (task)))
249                 return 0;
250
251         if (!dm_task_set_name (dmt, mpp->alias))
252                 goto addout;
253
254         if (!dm_task_add_target (dmt, 0, mpp->size, target, params))
255                 goto addout;
256
257         if (ro)
258                 dm_task_set_ro(dmt);
259
260         if (use_uuid && strlen(mpp->wwid) > 0){
261                 prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1);
262                 if (!prefixed_uuid) {
263                         condlog(0, "cannot create prefixed uuid : %s",
264                                 strerror(errno));
265                         goto addout;
266                 }
267                 sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid);
268                 if (!dm_task_set_uuid(dmt, prefixed_uuid))
269                         goto freeout;
270         }
271
272         if (mpp->attribute_flags & (1 << ATTR_MODE) &&
273             !dm_task_set_mode(dmt, mpp->mode))
274                 goto freeout;
275         if (mpp->attribute_flags & (1 << ATTR_UID) &&
276             !dm_task_set_uid(dmt, mpp->uid))
277                 goto freeout;
278         if (mpp->attribute_flags & (1 << ATTR_GID) &&
279             !dm_task_set_gid(dmt, mpp->gid))
280                 goto freeout;
281         condlog(4, "%s: addmap [0 %llu %s %s]", mpp->alias, mpp->size,
282                 target, params);
283
284         dm_task_no_open_count(dmt);
285
286         if (task == DM_DEVICE_CREATE &&
287             !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
288                 goto freeout;
289         r = dm_task_run (dmt);
290
291         freeout:
292         if (prefixed_uuid)
293                 FREE(prefixed_uuid);
294
295         addout:
296         dm_task_destroy (dmt);
297
298         return r;
299 }
300
301 static int
302 _dm_addmap_create (struct multipath *mpp, char * params, int ro) {
303         int r;
304         r = dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro);
305         /*
306          * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
307          * Failing the second part leaves an empty map. Clean it up.
308          */
309         if (!r && dm_map_present(mpp->alias)) {
310                 condlog(3, "%s: failed to load map (a path might be in use)",
311                         mpp->alias);
312                 dm_flush_map_nosync(mpp->alias);
313         }
314         return r;
315 }
316
317 #define ADDMAP_RW 0
318 #define ADDMAP_RO 1
319
320 extern int
321 dm_addmap_create (struct multipath *mpp, char *params) {
322         return _dm_addmap_create(mpp, params, ADDMAP_RW);
323 }
324
325 extern int
326 dm_addmap_create_ro (struct multipath *mpp, char *params) {
327         return _dm_addmap_create(mpp, params, ADDMAP_RO);
328 }
329
330 extern int
331 dm_addmap_reload (struct multipath *mpp, char *params) {
332         return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW);
333 }
334
335 extern int
336 dm_addmap_reload_ro (struct multipath *mpp, char *params) {
337         return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO);
338 }
339
340 extern int
341 dm_map_present (const char * str)
342 {
343         int r = 0;
344         struct dm_task *dmt;
345         struct dm_info info;
346
347         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
348                 return 0;
349
350         if (!dm_task_set_name(dmt, str))
351                 goto out;
352
353         dm_task_no_open_count(dmt);
354
355         if (!dm_task_run(dmt))
356                 goto out;
357
358         if (!dm_task_get_info(dmt, &info))
359                 goto out;
360
361         if (info.exists)
362                 r = 1;
363 out:
364         dm_task_destroy(dmt);
365         return r;
366 }
367
368 extern int
369 dm_get_map(const char * name, unsigned long long * size, char * outparams)
370 {
371         int r = 1;
372         struct dm_task *dmt;
373         void *next = NULL;
374         uint64_t start, length;
375         char *target_type = NULL;
376         char *params = NULL;
377
378         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
379                 return 1;
380
381         if (!dm_task_set_name(dmt, name))
382                 goto out;
383
384         dm_task_no_open_count(dmt);
385
386         if (!dm_task_run(dmt))
387                 goto out;
388
389         /* Fetch 1st target */
390         next = dm_get_next_target(dmt, next, &start, &length,
391                                   &target_type, &params);
392
393         if (size)
394                 *size = length;
395
396         if (!outparams) {
397                 r = 0;
398                 goto out;
399         }
400         if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
401                 r = 0;
402 out:
403         dm_task_destroy(dmt);
404         return r;
405 }
406
407 static int
408 dm_get_prefixed_uuid(const char *name, char *uuid)
409 {
410         struct dm_task *dmt;
411         const char *uuidtmp;
412         int r = 1;
413
414         dmt = dm_task_create(DM_DEVICE_INFO);
415         if (!dmt)
416                 return 1;
417
418         if (!dm_task_set_name (dmt, name))
419                 goto uuidout;
420
421         if (!dm_task_run(dmt))
422                 goto uuidout;
423
424         uuidtmp = dm_task_get_uuid(dmt);
425         if (uuidtmp)
426                 strcpy(uuid, uuidtmp);
427         else
428                 uuid[0] = '\0';
429
430         r = 0;
431 uuidout:
432         dm_task_destroy(dmt);
433         return r;
434 }
435
436 extern int
437 dm_get_uuid(char *name, char *uuid)
438 {
439         char uuidtmp[WWID_SIZE];
440
441         if (dm_get_prefixed_uuid(name, uuidtmp))
442                 return 1;
443
444         if (!strncmp(uuidtmp, UUID_PREFIX, UUID_PREFIX_LEN))
445                 strcpy(uuid, uuidtmp + UUID_PREFIX_LEN);
446         else
447                 strcpy(uuid, uuidtmp);
448
449         return 0;
450 }
451
452 /*
453  * returns:
454  *    0 : if both uuids end with same suffix which starts with UUID_PREFIX
455  *    1 : otherwise
456  */
457 int
458 dm_compare_uuid(const char* mapname1, const char* mapname2)
459 {
460         char *p1, *p2;
461         char uuid1[WWID_SIZE], uuid2[WWID_SIZE];
462
463         if (dm_get_prefixed_uuid(mapname1, uuid1))
464                 return 1;
465
466         if (dm_get_prefixed_uuid(mapname2, uuid2))
467                 return 1;
468
469         p1 = strstr(uuid1, UUID_PREFIX);
470         p2 = strstr(uuid2, UUID_PREFIX);
471         if (p1 && p2 && !strcmp(p1, p2))
472                 return 0;
473
474         return 1;
475 }
476
477 extern int
478 dm_get_status(char * name, char * outstatus)
479 {
480         int r = 1;
481         struct dm_task *dmt;
482         void *next = NULL;
483         uint64_t start, length;
484         char *target_type;
485         char *status;
486
487         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
488                 return 1;
489
490         if (!dm_task_set_name(dmt, name))
491                 goto out;
492
493         dm_task_no_open_count(dmt);
494
495         if (!dm_task_run(dmt))
496                 goto out;
497
498         /* Fetch 1st target */
499         next = dm_get_next_target(dmt, next, &start, &length,
500                                   &target_type, &status);
501
502         if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
503                 r = 0;
504 out:
505         if (r)
506                 condlog(0, "%s: error getting map status string", name);
507
508         dm_task_destroy(dmt);
509         return r;
510 }
511
512 /*
513  * returns:
514  *    1 : match
515  *    0 : no match
516  *   -1 : empty map
517  */
518 extern int
519 dm_type(const char * name, char * type)
520 {
521         int r = 0;
522         struct dm_task *dmt;
523         void *next = NULL;
524         uint64_t start, length;
525         char *target_type = NULL;
526         char *params;
527
528         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
529                 return 0;
530
531         if (!dm_task_set_name(dmt, name))
532                 goto out;
533
534         dm_task_no_open_count(dmt);
535
536         if (!dm_task_run(dmt))
537                 goto out;
538
539         /* Fetch 1st target */
540         next = dm_get_next_target(dmt, next, &start, &length,
541                                   &target_type, &params);
542
543         if (!target_type)
544                 r = -1;
545         else if (!strcmp(target_type, type))
546                 r = 1;
547
548 out:
549         dm_task_destroy(dmt);
550         return r;
551 }
552
553 static int
554 dm_dev_t (const char * mapname, char * dev_t, int len)
555 {
556         int r = 1;
557         struct dm_task *dmt;
558         struct dm_info info;
559
560         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
561                 return 0;
562
563         if (!dm_task_set_name(dmt, mapname))
564                 goto out;
565
566         if (!dm_task_run(dmt))
567                 goto out;
568
569         if (!dm_task_get_info(dmt, &info))
570                 goto out;
571
572         r = info.open_count;
573         if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
574                     goto out;
575
576         r = 0;
577 out:
578         dm_task_destroy(dmt);
579         return r;
580 }
581
582 int
583 dm_get_opencount (const char * mapname)
584 {
585         int r = -1;
586         struct dm_task *dmt;
587         struct dm_info info;
588
589         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
590                 return 0;
591
592         if (!dm_task_set_name(dmt, mapname))
593                 goto out;
594
595         if (!dm_task_run(dmt))
596                 goto out;
597
598         if (!dm_task_get_info(dmt, &info))
599                 goto out;
600
601         r = info.open_count;
602 out:
603         dm_task_destroy(dmt);
604         return r;
605 }
606
607 int
608 dm_get_major (char * mapname)
609 {
610         int r = -1;
611         struct dm_task *dmt;
612         struct dm_info info;
613
614         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
615                 return 0;
616
617         if (!dm_task_set_name(dmt, mapname))
618                 goto out;
619
620         if (!dm_task_run(dmt))
621                 goto out;
622
623         if (!dm_task_get_info(dmt, &info))
624                 goto out;
625
626         r = info.major;
627 out:
628         dm_task_destroy(dmt);
629         return r;
630 }
631
632 int
633 dm_get_minor (char * mapname)
634 {
635         int r = -1;
636         struct dm_task *dmt;
637         struct dm_info info;
638
639         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
640                 return 0;
641
642         if (!dm_task_set_name(dmt, mapname))
643                 goto out;
644
645         if (!dm_task_run(dmt))
646                 goto out;
647
648         if (!dm_task_get_info(dmt, &info))
649                 goto out;
650
651         r = info.minor;
652 out:
653         dm_task_destroy(dmt);
654         return r;
655 }
656
657 extern int
658 _dm_flush_map (const char * mapname, int need_sync)
659 {
660         int r;
661
662         if (!dm_map_present(mapname))
663                 return 0;
664
665         if (dm_type(mapname, TGT_MPATH) <= 0)
666                 return 0; /* nothing to do */
667
668         if (dm_remove_partmaps(mapname, need_sync))
669                 return 1;
670
671         if (dm_get_opencount(mapname)) {
672                 condlog(2, "%s: map in use", mapname);
673                 return 1;
674         }
675
676         r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync);
677
678         if (r) {
679                 condlog(4, "multipath map %s removed", mapname);
680                 return 0;
681         }
682         return 1;
683 }
684
685 extern int
686 dm_suspend_and_flush_map (const char * mapname)
687 {
688         int s = 0, queue_if_no_path = 0;
689         unsigned long long mapsize;
690         char params[PARAMS_SIZE] = {0};
691
692         if (!dm_map_present(mapname))
693                 return 0;
694
695         if (dm_type(mapname, TGT_MPATH) <= 0)
696                 return 0; /* nothing to do */
697
698         if (!dm_get_map(mapname, &mapsize, params)) {
699                 if (strstr(params, "queue_if_no_path"))
700                         queue_if_no_path = 1;
701         }
702
703         if (queue_if_no_path)
704                 s = dm_queue_if_no_path((char *)mapname, 0);
705         /* Leave queue_if_no_path alone if unset failed */
706         if (s)
707                 queue_if_no_path = 0;
708         else
709                 s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0);
710
711         if (!dm_flush_map(mapname)) {
712                 condlog(4, "multipath map %s removed", mapname);
713                 return 0;
714         }
715         condlog(2, "failed to remove multipath map %s", mapname);
716         dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname);
717         if (queue_if_no_path)
718                 s = dm_queue_if_no_path((char *)mapname, 1);
719         return 1;
720 }
721
722 extern int
723 dm_flush_maps (void)
724 {
725         int r = 0;
726         struct dm_task *dmt;
727         struct dm_names *names;
728         unsigned next = 0;
729
730         if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
731                 return 0;
732
733         dm_task_no_open_count(dmt);
734
735         if (!dm_task_run (dmt))
736                 goto out;
737
738         if (!(names = dm_task_get_names (dmt)))
739                 goto out;
740
741         if (!names->dev)
742                 goto out;
743
744         do {
745                 r |= dm_suspend_and_flush_map(names->name);
746                 next = names->next;
747                 names = (void *) names + next;
748         } while (next);
749
750         out:
751         dm_task_destroy (dmt);
752         return r;
753 }
754
755 int
756 dm_message(char * mapname, char * message)
757 {
758         int r = 1;
759         struct dm_task *dmt;
760
761         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
762                 return 1;
763
764         if (!dm_task_set_name(dmt, mapname))
765                 goto out;
766
767         if (!dm_task_set_sector(dmt, 0))
768                 goto out;
769
770         if (!dm_task_set_message(dmt, message))
771                 goto out;
772
773         dm_task_no_open_count(dmt);
774
775         if (!dm_task_run(dmt))
776                 goto out;
777
778         r = 0;
779 out:
780         if (r)
781                 condlog(0, "DM message failed [%s]", message);
782
783         dm_task_destroy(dmt);
784         return r;
785 }
786
787 int
788 dm_fail_path(char * mapname, char * path)
789 {
790         char message[32];
791
792         if (snprintf(message, 32, "fail_path %s", path) > 32)
793                 return 1;
794
795         return dm_message(mapname, message);
796 }
797
798 int
799 dm_reinstate_path(char * mapname, char * path)
800 {
801         char message[32];
802
803         if (snprintf(message, 32, "reinstate_path %s", path) > 32)
804                 return 1;
805
806         return dm_message(mapname, message);
807 }
808
809 int
810 dm_queue_if_no_path(char *mapname, int enable)
811 {
812         char *message;
813
814         if (enable)
815                 message = "queue_if_no_path";
816         else
817                 message = "fail_if_no_path";
818
819         return dm_message(mapname, message);
820 }
821
822 static int
823 dm_groupmsg (char * msg, char * mapname, int index)
824 {
825         char message[32];
826
827         if (snprintf(message, 32, "%s_group %i", msg, index) > 32)
828                 return 1;
829
830         return dm_message(mapname, message);
831 }
832
833 int
834 dm_switchgroup(char * mapname, int index)
835 {
836         return dm_groupmsg("switch", mapname, index);
837 }
838
839 int
840 dm_enablegroup(char * mapname, int index)
841 {
842         return dm_groupmsg("enable", mapname, index);
843 }
844
845 int
846 dm_disablegroup(char * mapname, int index)
847 {
848         return dm_groupmsg("disable", mapname, index);
849 }
850
851 int
852 dm_get_maps (vector mp)
853 {
854         struct multipath * mpp;
855         int r = 1;
856         int info;
857         struct dm_task *dmt;
858         struct dm_names *names;
859         unsigned next = 0;
860
861         if (!mp)
862                 return 1;
863
864         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
865                 return 1;
866
867         dm_task_no_open_count(dmt);
868
869         if (!dm_task_run(dmt))
870                 goto out;
871
872         if (!(names = dm_task_get_names(dmt)))
873                 goto out;
874
875         if (!names->dev) {
876                 r = 0; /* this is perfectly valid */
877                 goto out;
878         }
879
880         do {
881                 info = dm_type(names->name, TGT_MPATH);
882
883                 if (info <= 0)
884                         goto next;
885
886                 mpp = alloc_multipath();
887
888                 if (!mpp)
889                         goto out;
890
891                 mpp->alias = STRDUP(names->name);
892
893                 if (!mpp->alias)
894                         goto out1;
895
896                 if (info > 0) {
897                         if (dm_get_map(names->name, &mpp->size, NULL))
898                                 goto out1;
899
900                         dm_get_uuid(names->name, mpp->wwid);
901                         dm_get_info(names->name, &mpp->dmi);
902                 }
903
904                 if (!vector_alloc_slot(mp))
905                         goto out1;
906
907                 vector_set_slot(mp, mpp);
908                 mpp = NULL;
909 next:
910                 next = names->next;
911                 names = (void *) names + next;
912         } while (next);
913
914         r = 0;
915         goto out;
916 out1:
917         free_multipath(mpp, KEEP_PATHS);
918 out:
919         dm_task_destroy (dmt);
920         return r;
921 }
922
923 extern char *
924 dm_get_name(char *uuid)
925 {
926         struct dm_task *dmt;
927         struct dm_info info;
928         char *prefixed_uuid, *name = NULL;
929         const char *nametmp;
930
931         dmt = dm_task_create(DM_DEVICE_INFO);
932         if (!dmt)
933                 return NULL;
934
935         prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
936         if (!prefixed_uuid) {
937                 condlog(0, "cannot create prefixed uuid : %s",
938                         strerror(errno));
939                 goto freeout;
940         }
941         sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid);
942         if (!dm_task_set_uuid(dmt, prefixed_uuid))
943                 goto freeout;
944
945         if (!dm_task_run(dmt))
946                 goto freeout;
947
948         if (!dm_task_get_info(dmt, &info) || !info.exists)
949                 goto freeout;
950
951         nametmp = dm_task_get_name(dmt);
952         if (nametmp && strlen(nametmp)) {
953                 name = MALLOC(strlen(nametmp) + 1);
954                 if (name)
955                         strcpy(name, nametmp);
956         } else {
957                 condlog(2, "%s: no device-mapper name found", uuid);
958         }
959
960 freeout:
961         if (prefixed_uuid)
962                 FREE(prefixed_uuid);
963         dm_task_destroy(dmt);
964
965         return name;
966 }
967
968 int
969 dm_geteventnr (char *name)
970 {
971         struct dm_task *dmt;
972         struct dm_info info;
973         int event = -1;
974
975         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
976                 return -1;
977
978         if (!dm_task_set_name(dmt, name))
979                 goto out;
980
981         dm_task_no_open_count(dmt);
982
983         if (!dm_task_run(dmt))
984                 goto out;
985
986         if (!dm_task_get_info(dmt, &info))
987                 goto out;
988
989         if (info.exists)
990                 event = info.event_nr;
991
992 out:
993         dm_task_destroy(dmt);
994
995         return event;
996 }
997
998 char *
999 dm_mapname(int major, int minor)
1000 {
1001         char * response = NULL;
1002         const char *map;
1003         struct dm_task *dmt;
1004         int r;
1005         int loop = MAX_WAIT * LOOPS_PER_SEC;
1006
1007         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
1008                 return NULL;
1009
1010         if (!dm_task_set_major(dmt, major) ||
1011             !dm_task_set_minor(dmt, minor))
1012                 goto bad;
1013
1014         dm_task_no_open_count(dmt);
1015
1016         /*
1017          * device map might not be ready when we get here from
1018          * daemon uev_trigger -> uev_add_map
1019          */
1020         while (--loop) {
1021                 r = dm_task_run(dmt);
1022
1023                 if (r)
1024                         break;
1025
1026                 usleep(1000 * 1000 / LOOPS_PER_SEC);
1027         }
1028
1029         if (!r) {
1030                 condlog(0, "%i:%i: timeout fetching map name", major, minor);
1031                 goto bad;
1032         }
1033
1034         map = dm_task_get_name(dmt);
1035         if (map && strlen(map))
1036                 response = STRDUP((char *)dm_task_get_name(dmt));
1037
1038         dm_task_destroy(dmt);
1039         return response;
1040 bad:
1041         dm_task_destroy(dmt);
1042         condlog(0, "%i:%i: error fetching map name", major, minor);
1043         return NULL;
1044 }
1045
1046 int
1047 dm_remove_partmaps (const char * mapname, int need_sync)
1048 {
1049         struct dm_task *dmt;
1050         struct dm_names *names;
1051         unsigned next = 0;
1052         char params[PARAMS_SIZE];
1053         unsigned long long size;
1054         char dev_t[32];
1055         int r = 1;
1056
1057         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
1058                 return 1;
1059
1060         dm_task_no_open_count(dmt);
1061
1062         if (!dm_task_run(dmt))
1063                 goto out;
1064
1065         if (!(names = dm_task_get_names(dmt)))
1066                 goto out;
1067
1068         if (!names->dev) {
1069                 r = 0; /* this is perfectly valid */
1070                 goto out;
1071         }
1072
1073         if (dm_dev_t(mapname, &dev_t[0], 32))
1074                 goto out;
1075
1076         do {
1077                 if (
1078                     /*
1079                      * if devmap target is "linear"
1080                      */
1081                     (dm_type(names->name, TGT_PART) > 0) &&
1082
1083                     /*
1084                      * and both uuid end with same suffix starting
1085                      * at UUID_PREFIX
1086                      */
1087                     (!dm_compare_uuid(names->name, mapname)) &&
1088
1089                     /*
1090                      * and we can fetch the map table from the kernel
1091                      */
1092                     !dm_get_map(names->name, &size, &params[0]) &&
1093
1094                     /*
1095                      * and the table maps over the multipath map
1096                      */
1097                     strstr(params, dev_t)
1098                    ) {
1099                         /*
1100                          * then it's a kpartx generated partition.
1101                          * remove it.
1102                          */
1103                         /*
1104                          * if the opencount is 0 maybe some other
1105                          * partitions depend on it.
1106                          */
1107                         if (dm_get_opencount(names->name)) {
1108                                 dm_remove_partmaps(names->name, need_sync);
1109                                 if (dm_get_opencount(names->name)) {
1110                                         condlog(2, "%s: map in use",
1111                                                 names->name);
1112                                         goto out;
1113                                 }
1114                         }
1115                         condlog(4, "partition map %s removed",
1116                                 names->name);
1117                         dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name,
1118                                            need_sync);
1119                 }
1120
1121                 next = names->next;
1122                 names = (void *) names + next;
1123         } while (next);
1124
1125         r = 0;
1126 out:
1127         dm_task_destroy (dmt);
1128         return r;
1129 }
1130
1131 static struct dm_info *
1132 alloc_dminfo (void)
1133 {
1134         return MALLOC(sizeof(struct dm_info));
1135 }
1136
1137 int
1138 dm_get_info (char * mapname, struct dm_info ** dmi)
1139 {
1140         int r = 1;
1141         struct dm_task *dmt = NULL;
1142
1143         if (!mapname)
1144                 return 1;
1145
1146         if (!*dmi)
1147                 *dmi = alloc_dminfo();
1148
1149         if (!*dmi)
1150                 return 1;
1151
1152         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
1153                 goto out;
1154
1155         if (!dm_task_set_name(dmt, mapname))
1156                 goto out;
1157
1158         dm_task_no_open_count(dmt);
1159
1160         if (!dm_task_run(dmt))
1161                 goto out;
1162
1163         if (!dm_task_get_info(dmt, *dmi))
1164                 goto out;
1165
1166         r = 0;
1167 out:
1168         if (r) {
1169                 memset(*dmi, 0, sizeof(struct dm_info));
1170                 FREE(*dmi);
1171                 *dmi = NULL;
1172         }
1173
1174         if (dmt)
1175                 dm_task_destroy(dmt);
1176
1177         return r;
1178 }
1179
1180 int
1181 dm_rename_partmaps (char * old, char * new)
1182 {
1183         struct dm_task *dmt;
1184         struct dm_names *names;
1185         unsigned next = 0;
1186         char buff[PARAMS_SIZE];
1187         unsigned long long size;
1188         char dev_t[32];
1189         int r = 1;
1190
1191         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
1192                 return 1;
1193
1194         dm_task_no_open_count(dmt);
1195
1196         if (!dm_task_run(dmt))
1197                 goto out;
1198
1199         if (!(names = dm_task_get_names(dmt)))
1200                 goto out;
1201
1202         if (!names->dev) {
1203                 r = 0; /* this is perfectly valid */
1204                 goto out;
1205         }
1206
1207         if (dm_dev_t(old, &dev_t[0], 32))
1208                 goto out;
1209
1210         do {
1211                 if (
1212                     /*
1213                      * if devmap target is "linear"
1214                      */
1215                     (dm_type(names->name, TGT_PART) > 0) &&
1216
1217                     /*
1218                      * and the multipath mapname and the part mapname start
1219                      * the same
1220                      */
1221                     !strncmp(names->name, old, strlen(old)) &&
1222
1223                     /*
1224                      * and we can fetch the map table from the kernel
1225                      */
1226                     !dm_get_map(names->name, &size, &buff[0]) &&
1227
1228                     /*
1229                      * and the table maps over the multipath map
1230                      */
1231                     strstr(buff, dev_t)
1232                    ) {
1233                                 /*
1234                                  * then it's a kpartx generated partition.
1235                                  * Rename it.
1236                                  */
1237                                 snprintf(buff, PARAMS_SIZE, "%s%s",
1238                                          new, names->name + strlen(old));
1239                                 dm_rename(names->name, buff);
1240                                 condlog(4, "partition map %s renamed",
1241                                         names->name);
1242                    }
1243
1244                 next = names->next;
1245                 names = (void *) names + next;
1246         } while (next);
1247
1248         r = 0;
1249 out:
1250         dm_task_destroy (dmt);
1251         return r;
1252 }
1253
1254 int
1255 dm_rename (char * old, char * new)
1256 {
1257         int r = 0;
1258         struct dm_task *dmt;
1259
1260         if (dm_rename_partmaps(old, new))
1261                 return r;
1262
1263         if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
1264                 return r;
1265
1266         if (!dm_task_set_name(dmt, old))
1267                 goto out;
1268
1269         if (!dm_task_set_newname(dmt, new))
1270                 goto out;
1271
1272         dm_task_no_open_count(dmt);
1273
1274         if (!dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
1275                 goto out;
1276         if (!dm_task_run(dmt))
1277                 goto out;
1278
1279         r = 1;
1280 out:
1281         dm_task_destroy(dmt);
1282         return r;
1283 }
1284
1285 void dm_reassign_deps(char *table, char *dep, char *newdep)
1286 {
1287         char *p, *n;
1288         char newtable[PARAMS_SIZE];
1289
1290         strcpy(newtable, table);
1291         p = strstr(newtable, dep);
1292         n = table + (p - newtable);
1293         strcpy(n, newdep);
1294         n += strlen(newdep);
1295         p += strlen(dep);
1296         strcat(n, p);
1297 }
1298
1299 int dm_reassign_table(const char *name, char *old, char *new)
1300 {
1301         int r, modified = 0;
1302         uint64_t start, length;
1303         struct dm_task *dmt, *reload_dmt;
1304         char *target, *params = NULL;
1305         char buff[PARAMS_SIZE];
1306         void *next = NULL;
1307
1308         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
1309                 return 0;
1310
1311         if (!dm_task_set_name(dmt, name))
1312                 goto out;
1313
1314         dm_task_no_open_count(dmt);
1315
1316         if (!dm_task_run(dmt))
1317                 goto out;
1318         if (!(reload_dmt = dm_task_create(DM_DEVICE_RELOAD)))
1319                 goto out;
1320         if (!dm_task_set_name(reload_dmt, name))
1321                 goto out_reload;
1322
1323         do {
1324                 next = dm_get_next_target(dmt, next, &start, &length,
1325                                           &target, &params);
1326                 memset(buff, 0, PARAMS_SIZE);
1327                 strcpy(buff, params);
1328                 if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
1329                         condlog(3, "%s: replace target %s %s",
1330                                 name, target, buff);
1331                         dm_reassign_deps(buff, old, new);
1332                         condlog(3, "%s: with target %s %s",
1333                                 name, target, buff);
1334                         modified++;
1335                 }
1336                 dm_task_add_target(reload_dmt, start, length, target, buff);
1337         } while (next);
1338
1339         if (modified) {
1340                 dm_task_no_open_count(reload_dmt);
1341
1342                 if (!dm_task_run(reload_dmt)) {
1343                         condlog(3, "%s: failed to reassign targets", name);
1344                         goto out_reload;
1345                 }
1346                 dm_simplecmd_noflush(DM_DEVICE_RESUME, name);
1347         }
1348         r = 1;
1349
1350 out_reload:
1351         dm_task_destroy(reload_dmt);
1352 out:
1353         dm_task_destroy(dmt);
1354         return r;
1355 }
1356
1357
1358 /*
1359  * Reassign existing device-mapper table(s) to not use
1360  * the block devices but point to the multipathed
1361  * device instead
1362  */
1363 int dm_reassign(const char *mapname)
1364 {
1365         struct dm_deps *deps;
1366         struct dm_task *dmt;
1367         struct dm_info info;
1368         char dev_t[32], dm_dep[32];
1369         int r = 0, i;
1370
1371         if (dm_dev_t(mapname, &dev_t[0], 32)) {
1372                 condlog(3, "%s: failed to get device number", mapname);
1373                 return 1;
1374         }
1375
1376         if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) {
1377                 condlog(3, "%s: couldn't make dm task", mapname);
1378                 return 0;
1379         }
1380
1381         if (!dm_task_set_name(dmt, mapname))
1382                 goto out;
1383
1384         dm_task_no_open_count(dmt);
1385
1386         if (!dm_task_run(dmt))
1387                 goto out;
1388
1389         if (!dm_task_get_info(dmt, &info))
1390                 goto out;
1391
1392         if (!(deps = dm_task_get_deps(dmt)))
1393                 goto out;
1394
1395         if (!info.exists)
1396                 goto out;
1397
1398         for (i = 0; i < deps->count; i++) {
1399                 sprintf(dm_dep, "%d:%d",
1400                         major(deps->device[i]),
1401                         minor(deps->device[i]));
1402                 sysfs_check_holders(dm_dep, dev_t);
1403         }
1404
1405         dm_task_destroy (dmt);
1406
1407         r = 1;
1408 out:
1409         return r;
1410 }
1411
1412 int dm_setgeometry(struct multipath *mpp)
1413 {
1414         struct dm_task *dmt;
1415         struct path *pp;
1416         char heads[4], sectors[4];
1417         char cylinders[10], start[32];
1418         int r = 0;
1419
1420         if (!mpp)
1421                 return 1;
1422
1423         pp = first_path(mpp);
1424         if (!pp) {
1425                 condlog(3, "%s: no path for geometry", mpp->alias);
1426                 return 1;
1427         }
1428         if (pp->geom.cylinders == 0 ||
1429             pp->geom.heads == 0 ||
1430             pp->geom.sectors == 0) {
1431                 condlog(3, "%s: invalid geometry on %s", mpp->alias, pp->dev);
1432                 return 1;
1433         }
1434
1435         if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
1436                 return 0;
1437
1438         if (!dm_task_set_name(dmt, mpp->alias))
1439                 goto out;
1440
1441         dm_task_no_open_count(dmt);
1442
1443         /* What a sick interface ... */
1444         snprintf(heads, 4, "%u", pp->geom.heads);
1445         snprintf(sectors, 4, "%u", pp->geom.sectors);
1446         snprintf(cylinders, 10, "%u", pp->geom.cylinders);
1447         snprintf(start, 32, "%lu", pp->geom.start);
1448         if (!dm_task_set_geometry(dmt, cylinders, heads, sectors, start)) {
1449                 condlog(3, "%s: Failed to set geometry", mpp->alias);
1450                 goto out;
1451         }
1452
1453         r = dm_task_run(dmt);
1454 out:
1455         dm_task_destroy(dmt);
1456
1457         return r;
1458 }