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