Make multipath ignore devices without mpath prefix
[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 extern int
585 dm_is_mpath(const char * name)
586 {
587         int r = 0;
588         struct dm_task *dmt;
589         struct dm_info info;
590         uint64_t start, length;
591         char *target_type = NULL;
592         char *params;
593         const char *uuid;
594
595         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
596                 return 0;
597
598         if (!dm_task_set_name(dmt, name))
599                 goto out;
600
601         dm_task_no_open_count(dmt);
602
603         if (!dm_task_run(dmt))
604                 goto out;
605
606         if (!dm_task_get_info(dmt, &info) || !info.exists)
607                 goto out;
608
609         uuid = dm_task_get_uuid(dmt);
610
611         if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
612                 goto out;
613
614         /* Fetch 1st target */
615         dm_get_next_target(dmt, NULL, &start, &length, &target_type, &params);
616
617         if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
618                 goto out;
619
620         r = 1;
621 out:
622         dm_task_destroy(dmt);
623         return r;
624 }
625
626 static int
627 dm_dev_t (const char * mapname, char * dev_t, int len)
628 {
629         int r = 1;
630         struct dm_task *dmt;
631         struct dm_info info;
632
633         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
634                 return 0;
635
636         if (!dm_task_set_name(dmt, mapname))
637                 goto out;
638
639         if (!dm_task_run(dmt))
640                 goto out;
641
642         if (!dm_task_get_info(dmt, &info) || !info.exists)
643                 goto out;
644
645         if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
646                     goto out;
647
648         r = 0;
649 out:
650         dm_task_destroy(dmt);
651         return r;
652 }
653
654 int
655 dm_get_opencount (const char * mapname)
656 {
657         int r = -1;
658         struct dm_task *dmt;
659         struct dm_info info;
660
661         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
662                 return 0;
663
664         if (!dm_task_set_name(dmt, mapname))
665                 goto out;
666
667         if (!dm_task_run(dmt))
668                 goto out;
669
670         if (!dm_task_get_info(dmt, &info))
671                 goto out;
672
673         if (!info.exists)
674                 goto out;
675
676         r = info.open_count;
677 out:
678         dm_task_destroy(dmt);
679         return r;
680 }
681
682 int
683 dm_get_major (char * mapname)
684 {
685         int r = -1;
686         struct dm_task *dmt;
687         struct dm_info info;
688
689         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
690                 return 0;
691
692         if (!dm_task_set_name(dmt, mapname))
693                 goto out;
694
695         if (!dm_task_run(dmt))
696                 goto out;
697
698         if (!dm_task_get_info(dmt, &info))
699                 goto out;
700
701         if (!info.exists)
702                 goto out;
703
704         r = info.major;
705 out:
706         dm_task_destroy(dmt);
707         return r;
708 }
709
710 int
711 dm_get_minor (char * mapname)
712 {
713         int r = -1;
714         struct dm_task *dmt;
715         struct dm_info info;
716
717         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
718                 return 0;
719
720         if (!dm_task_set_name(dmt, mapname))
721                 goto out;
722
723         if (!dm_task_run(dmt))
724                 goto out;
725
726         if (!dm_task_get_info(dmt, &info))
727                 goto out;
728
729         if (!info.exists)
730                 goto out;
731
732         r = info.minor;
733 out:
734         dm_task_destroy(dmt);
735         return r;
736 }
737
738 extern int
739 _dm_flush_map (const char * mapname, int need_sync, int deferred_remove)
740 {
741         int r;
742
743         if (!dm_is_mpath(mapname))
744                 return 0; /* nothing to do */
745
746         if (dm_remove_partmaps(mapname, need_sync, deferred_remove))
747                 return 1;
748
749         if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) {
750                 condlog(2, "%s: map in use", mapname);
751                 return 1;
752         }
753
754         r = dm_device_remove(mapname, need_sync, deferred_remove);
755
756         if (r) {
757                 if (do_deferred(deferred_remove) && dm_map_present(mapname)) {
758                         condlog(4, "multipath map %s remove deferred",
759                                 mapname);
760                         return 2;
761                 }
762                 condlog(4, "multipath map %s removed", mapname);
763                 return 0;
764         }
765         return 1;
766 }
767
768 #ifdef LIBDM_API_DEFERRED
769
770 int
771 dm_flush_map_nopaths(const char * mapname, int deferred_remove)
772 {
773         return _dm_flush_map(mapname, 1, deferred_remove);
774 }
775
776 #else
777
778 int
779 dm_flush_map_nopaths(const char * mapname, int deferred_remove)
780 {
781         return _dm_flush_map(mapname, 1, 0);
782 }
783
784 #endif
785
786 extern int
787 dm_suspend_and_flush_map (const char * mapname)
788 {
789         int s = 0, queue_if_no_path = 0;
790         unsigned long long mapsize;
791         char params[PARAMS_SIZE] = {0};
792
793         if (!dm_is_mpath(mapname))
794                 return 0; /* nothing to do */
795
796         if (!dm_get_map(mapname, &mapsize, params)) {
797                 if (strstr(params, "queue_if_no_path"))
798                         queue_if_no_path = 1;
799         }
800
801         if (queue_if_no_path)
802                 s = dm_queue_if_no_path((char *)mapname, 0);
803         /* Leave queue_if_no_path alone if unset failed */
804         if (s)
805                 queue_if_no_path = 0;
806         else
807                 s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 1, 0);
808
809         if (!dm_flush_map(mapname)) {
810                 condlog(4, "multipath map %s removed", mapname);
811                 return 0;
812         }
813         condlog(2, "failed to remove multipath map %s", mapname);
814         dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 1, 0);
815         if (queue_if_no_path)
816                 s = dm_queue_if_no_path((char *)mapname, 1);
817         return 1;
818 }
819
820 extern int
821 dm_flush_maps (void)
822 {
823         int r = 0;
824         struct dm_task *dmt;
825         struct dm_names *names;
826         unsigned next = 0;
827
828         if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
829                 return 0;
830
831         dm_task_no_open_count(dmt);
832
833         if (!dm_task_run (dmt))
834                 goto out;
835
836         if (!(names = dm_task_get_names (dmt)))
837                 goto out;
838
839         if (!names->dev)
840                 goto out;
841
842         do {
843                 r |= dm_suspend_and_flush_map(names->name);
844                 next = names->next;
845                 names = (void *) names + next;
846         } while (next);
847
848         out:
849         dm_task_destroy (dmt);
850         return r;
851 }
852
853 int
854 dm_message(char * mapname, char * message)
855 {
856         int r = 1;
857         struct dm_task *dmt;
858
859         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
860                 return 1;
861
862         if (!dm_task_set_name(dmt, mapname))
863                 goto out;
864
865         if (!dm_task_set_sector(dmt, 0))
866                 goto out;
867
868         if (!dm_task_set_message(dmt, message))
869                 goto out;
870
871         dm_task_no_open_count(dmt);
872
873         if (!dm_task_run(dmt))
874                 goto out;
875
876         r = 0;
877 out:
878         if (r)
879                 condlog(0, "DM message failed [%s]", message);
880
881         dm_task_destroy(dmt);
882         return r;
883 }
884
885 int
886 dm_fail_path(char * mapname, char * path)
887 {
888         char message[32];
889
890         if (snprintf(message, 32, "fail_path %s", path) > 32)
891                 return 1;
892
893         return dm_message(mapname, message);
894 }
895
896 int
897 dm_reinstate_path(char * mapname, char * path)
898 {
899         char message[32];
900
901         if (snprintf(message, 32, "reinstate_path %s", path) > 32)
902                 return 1;
903
904         return dm_message(mapname, message);
905 }
906
907 int
908 dm_queue_if_no_path(char *mapname, int enable)
909 {
910         char *message;
911
912         if (enable)
913                 message = "queue_if_no_path";
914         else
915                 message = "fail_if_no_path";
916
917         return dm_message(mapname, message);
918 }
919
920 static int
921 dm_groupmsg (char * msg, char * mapname, int index)
922 {
923         char message[32];
924
925         if (snprintf(message, 32, "%s_group %i", msg, index) > 32)
926                 return 1;
927
928         return dm_message(mapname, message);
929 }
930
931 int
932 dm_switchgroup(char * mapname, int index)
933 {
934         return dm_groupmsg("switch", mapname, index);
935 }
936
937 int
938 dm_enablegroup(char * mapname, int index)
939 {
940         return dm_groupmsg("enable", mapname, index);
941 }
942
943 int
944 dm_disablegroup(char * mapname, int index)
945 {
946         return dm_groupmsg("disable", mapname, index);
947 }
948
949 int
950 dm_get_maps (vector mp)
951 {
952         struct multipath * mpp;
953         int r = 1;
954         struct dm_task *dmt;
955         struct dm_names *names;
956         unsigned next = 0;
957
958         if (!mp)
959                 return 1;
960
961         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
962                 return 1;
963
964         dm_task_no_open_count(dmt);
965
966         if (!dm_task_run(dmt))
967                 goto out;
968
969         if (!(names = dm_task_get_names(dmt)))
970                 goto out;
971
972         if (!names->dev) {
973                 r = 0; /* this is perfectly valid */
974                 goto out;
975         }
976
977         do {
978                 if (!dm_is_mpath(names->name))
979                         goto next;
980
981                 mpp = alloc_multipath();
982
983                 if (!mpp)
984                         goto out;
985
986                 mpp->alias = STRDUP(names->name);
987
988                 if (!mpp->alias)
989                         goto out1;
990
991                 if (dm_get_map(names->name, &mpp->size, NULL))
992                         goto out1;
993
994                 dm_get_uuid(names->name, mpp->wwid);
995                 dm_get_info(names->name, &mpp->dmi);
996
997                 if (!vector_alloc_slot(mp))
998                         goto out1;
999
1000                 vector_set_slot(mp, mpp);
1001                 mpp = NULL;
1002 next:
1003                 next = names->next;
1004                 names = (void *) names + next;
1005         } while (next);
1006
1007         r = 0;
1008         goto out;
1009 out1:
1010         free_multipath(mpp, KEEP_PATHS);
1011 out:
1012         dm_task_destroy (dmt);
1013         return r;
1014 }
1015
1016 int
1017 dm_geteventnr (char *name)
1018 {
1019         struct dm_task *dmt;
1020         struct dm_info info;
1021         int event = -1;
1022
1023         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
1024                 return -1;
1025
1026         if (!dm_task_set_name(dmt, name))
1027                 goto out;
1028
1029         dm_task_no_open_count(dmt);
1030
1031         if (!dm_task_run(dmt))
1032                 goto out;
1033
1034         if (!dm_task_get_info(dmt, &info))
1035                 goto out;
1036
1037         if (info.exists)
1038                 event = info.event_nr;
1039
1040 out:
1041         dm_task_destroy(dmt);
1042
1043         return event;
1044 }
1045
1046 char *
1047 dm_mapname(int major, int minor)
1048 {
1049         char * response = NULL;
1050         const char *map;
1051         struct dm_task *dmt;
1052         int r;
1053         int loop = MAX_WAIT * LOOPS_PER_SEC;
1054
1055         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
1056                 return NULL;
1057
1058         if (!dm_task_set_major(dmt, major) ||
1059             !dm_task_set_minor(dmt, minor))
1060                 goto bad;
1061
1062         dm_task_no_open_count(dmt);
1063
1064         /*
1065          * device map might not be ready when we get here from
1066          * daemon uev_trigger -> uev_add_map
1067          */
1068         while (--loop) {
1069                 r = dm_task_run(dmt);
1070
1071                 if (r)
1072                         break;
1073
1074                 usleep(1000 * 1000 / LOOPS_PER_SEC);
1075         }
1076
1077         if (!r) {
1078                 condlog(0, "%i:%i: timeout fetching map name", major, minor);
1079                 goto bad;
1080         }
1081
1082         map = dm_task_get_name(dmt);
1083         if (map && strlen(map))
1084                 response = STRDUP((char *)dm_task_get_name(dmt));
1085
1086         dm_task_destroy(dmt);
1087         return response;
1088 bad:
1089         dm_task_destroy(dmt);
1090         condlog(0, "%i:%i: error fetching map name", major, minor);
1091         return NULL;
1092 }
1093
1094 static int
1095 do_foreach_partmaps (const char * mapname, int (*partmap_func)(char *, void *),
1096                      void *data)
1097 {
1098         struct dm_task *dmt;
1099         struct dm_names *names;
1100         unsigned next = 0;
1101         char params[PARAMS_SIZE];
1102         unsigned long long size;
1103         char dev_t[32];
1104         int r = 1;
1105
1106         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
1107                 return 1;
1108
1109         dm_task_no_open_count(dmt);
1110
1111         if (!dm_task_run(dmt))
1112                 goto out;
1113
1114         if (!(names = dm_task_get_names(dmt)))
1115                 goto out;
1116
1117         if (!names->dev) {
1118                 r = 0; /* this is perfectly valid */
1119                 goto out;
1120         }
1121
1122         if (dm_dev_t(mapname, &dev_t[0], 32))
1123                 goto out;
1124
1125         do {
1126                 if (
1127                     /*
1128                      * if devmap target is "linear"
1129                      */
1130                     (dm_type(names->name, TGT_PART) > 0) &&
1131
1132                     /*
1133                      * and both uuid end with same suffix starting
1134                      * at UUID_PREFIX
1135                      */
1136                     (!dm_compare_uuid(names->name, mapname)) &&
1137
1138                     /*
1139                      * and we can fetch the map table from the kernel
1140                      */
1141                     !dm_get_map(names->name, &size, &params[0]) &&
1142
1143                     /*
1144                      * and the table maps over the multipath map
1145                      */
1146                     strstr(params, dev_t)
1147                    ) {
1148                         if (partmap_func(names->name, data) != 0)
1149                                 goto out;
1150                 }
1151
1152                 next = names->next;
1153                 names = (void *) names + next;
1154         } while (next);
1155
1156         r = 0;
1157 out:
1158         dm_task_destroy (dmt);
1159         return r;
1160 }
1161
1162 struct remove_data {
1163         int need_sync;
1164         int deferred_remove;
1165 };
1166
1167 static int
1168 remove_partmap(char *name, void *data)
1169 {
1170         struct remove_data *rd = (struct remove_data *)data;
1171
1172         if (dm_get_opencount(name)) {
1173                 dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove);
1174                 if (!do_deferred(rd->deferred_remove) &&
1175                     dm_get_opencount(name)) {
1176                         condlog(2, "%s: map in use", name);
1177                         return 1;
1178                 }
1179         }
1180         condlog(4, "partition map %s removed", name);
1181         dm_device_remove(name, rd->need_sync, rd->deferred_remove);
1182         return 0;
1183 }
1184
1185 int
1186 dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove)
1187 {
1188         struct remove_data rd = { need_sync, deferred_remove };
1189         return do_foreach_partmaps(mapname, remove_partmap, &rd);
1190 }
1191
1192 #ifdef LIBDM_API_DEFERRED
1193
1194 static int
1195 cancel_remove_partmap (char *name, void *unused)
1196 {
1197         if (dm_get_opencount(name))
1198                 dm_cancel_remove_partmaps(name);
1199         if (dm_message(name, "@cancel_deferred_remove") != 0)
1200                 condlog(0, "%s: can't cancel deferred remove: %s", name,
1201                         strerror(errno));
1202         return 0;
1203 }
1204
1205 static int
1206 dm_get_deferred_remove (char * mapname)
1207 {
1208         int r = -1;
1209         struct dm_task *dmt;
1210         struct dm_info info;
1211
1212         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
1213                 return -1;
1214
1215         if (!dm_task_set_name(dmt, mapname))
1216                 goto out;
1217
1218         if (!dm_task_run(dmt))
1219                 goto out;
1220
1221         if (!dm_task_get_info(dmt, &info))
1222                 goto out;
1223
1224         r = info.deferred_remove;
1225 out:
1226         dm_task_destroy(dmt);
1227         return r;
1228 }
1229
1230 static int
1231 dm_cancel_remove_partmaps(const char * mapname) {
1232         return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
1233 }
1234
1235 int
1236 dm_cancel_deferred_remove (struct multipath *mpp)
1237 {
1238         int r = 0;
1239
1240         if (!dm_get_deferred_remove(mpp->alias))
1241                 return 0;
1242         if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS)
1243                 mpp->deferred_remove = DEFERRED_REMOVE_ON;
1244
1245         dm_cancel_remove_partmaps(mpp->alias);
1246         r = dm_message(mpp->alias, "@cancel_deferred_remove");
1247         if (r)
1248                 condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias,
1249                                 strerror(errno));
1250         else
1251                 condlog(2, "%s: canceled deferred remove", mpp->alias);
1252         return r;
1253 }
1254
1255 #else
1256
1257 int
1258 dm_cancel_deferred_remove (struct multipath *mpp)
1259 {
1260         return 0;
1261 }
1262
1263 #endif
1264
1265 static struct dm_info *
1266 alloc_dminfo (void)
1267 {
1268         return MALLOC(sizeof(struct dm_info));
1269 }
1270
1271 int
1272 dm_get_info (char * mapname, struct dm_info ** dmi)
1273 {
1274         int r = 1;
1275         struct dm_task *dmt = NULL;
1276
1277         if (!mapname)
1278                 return 1;
1279
1280         if (!*dmi)
1281                 *dmi = alloc_dminfo();
1282
1283         if (!*dmi)
1284                 return 1;
1285
1286         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
1287                 goto out;
1288
1289         if (!dm_task_set_name(dmt, mapname))
1290                 goto out;
1291
1292         dm_task_no_open_count(dmt);
1293
1294         if (!dm_task_run(dmt))
1295                 goto out;
1296
1297         if (!dm_task_get_info(dmt, *dmi))
1298                 goto out;
1299
1300         r = 0;
1301 out:
1302         if (r) {
1303                 memset(*dmi, 0, sizeof(struct dm_info));
1304                 FREE(*dmi);
1305                 *dmi = NULL;
1306         }
1307
1308         if (dmt)
1309                 dm_task_destroy(dmt);
1310
1311         return r;
1312 }
1313
1314 struct rename_data {
1315         char *old;
1316         char *new;
1317         char *delim;
1318 };
1319
1320 static int
1321 rename_partmap (char *name, void *data)
1322 {
1323         char buff[PARAMS_SIZE];
1324         int offset;
1325         struct rename_data *rd = (struct rename_data *)data;
1326
1327         if (strncmp(name, rd->old, strlen(rd->old)) != 0)
1328                 return 0;
1329         for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */
1330         snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim,
1331                  name + offset);
1332         dm_rename(name, buff);
1333         condlog(4, "partition map %s renamed", name);
1334         return 0;
1335 }
1336
1337 int
1338 dm_rename_partmaps (char * old, char * new)
1339 {
1340         struct rename_data rd;
1341
1342         rd.old = old;
1343         rd.new = new;
1344
1345         if (conf->partition_delim)
1346                 rd.delim = conf->partition_delim;
1347         if (isdigit(new[strlen(new)-1]))
1348                 rd.delim = "p";
1349         else
1350                 rd.delim = "";
1351         return do_foreach_partmaps(old, rename_partmap, &rd);
1352 }
1353
1354 int
1355 dm_rename (char * old, char * new)
1356 {
1357         int r = 0;
1358         struct dm_task *dmt;
1359         uint32_t cookie;
1360
1361         if (dm_rename_partmaps(old, new))
1362                 return r;
1363
1364         if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
1365                 return r;
1366
1367         if (!dm_task_set_name(dmt, old))
1368                 goto out;
1369
1370         if (!dm_task_set_newname(dmt, new))
1371                 goto out;
1372
1373         dm_task_no_open_count(dmt);
1374
1375         if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
1376                 goto out;
1377         r = dm_task_run(dmt);
1378
1379         if (!r)
1380                 dm_udev_complete(cookie);
1381         else
1382                 dm_udev_wait(cookie);
1383
1384 out:
1385         dm_task_destroy(dmt);
1386
1387         return r;
1388 }
1389
1390 void dm_reassign_deps(char *table, char *dep, char *newdep)
1391 {
1392         char *p, *n;
1393         char newtable[PARAMS_SIZE];
1394
1395         strcpy(newtable, table);
1396         p = strstr(newtable, dep);
1397         n = table + (p - newtable);
1398         strcpy(n, newdep);
1399         n += strlen(newdep);
1400         p += strlen(dep);
1401         strcat(n, p);
1402 }
1403
1404 int dm_reassign_table(const char *name, char *old, char *new)
1405 {
1406         int r, modified = 0;
1407         uint64_t start, length;
1408         struct dm_task *dmt, *reload_dmt;
1409         char *target, *params = NULL;
1410         char buff[PARAMS_SIZE];
1411         void *next = NULL;
1412
1413         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
1414                 return 0;
1415
1416         if (!dm_task_set_name(dmt, name))
1417                 goto out;
1418
1419         dm_task_no_open_count(dmt);
1420
1421         if (!dm_task_run(dmt))
1422                 goto out;
1423         if (!(reload_dmt = dm_task_create(DM_DEVICE_RELOAD)))
1424                 goto out;
1425         if (!dm_task_set_name(reload_dmt, name))
1426                 goto out_reload;
1427
1428         do {
1429                 next = dm_get_next_target(dmt, next, &start, &length,
1430                                           &target, &params);
1431                 memset(buff, 0, PARAMS_SIZE);
1432                 strcpy(buff, params);
1433                 if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
1434                         condlog(3, "%s: replace target %s %s",
1435                                 name, target, buff);
1436                         dm_reassign_deps(buff, old, new);
1437                         condlog(3, "%s: with target %s %s",
1438                                 name, target, buff);
1439                         modified++;
1440                 }
1441                 dm_task_add_target(reload_dmt, start, length, target, buff);
1442         } while (next);
1443
1444         if (modified) {
1445                 dm_task_no_open_count(reload_dmt);
1446
1447                 if (!dm_task_run(reload_dmt)) {
1448                         condlog(3, "%s: failed to reassign targets", name);
1449                         goto out_reload;
1450                 }
1451                 dm_simplecmd_noflush(DM_DEVICE_RESUME, name, 1, MPATH_UDEV_RELOAD_FLAG);
1452         }
1453         r = 1;
1454
1455 out_reload:
1456         dm_task_destroy(reload_dmt);
1457 out:
1458         dm_task_destroy(dmt);
1459         return r;
1460 }
1461
1462
1463 /*
1464  * Reassign existing device-mapper table(s) to not use
1465  * the block devices but point to the multipathed
1466  * device instead
1467  */
1468 int dm_reassign(const char *mapname)
1469 {
1470         struct dm_deps *deps;
1471         struct dm_task *dmt;
1472         struct dm_info info;
1473         char dev_t[32], dm_dep[32];
1474         int r = 0, i;
1475
1476         if (dm_dev_t(mapname, &dev_t[0], 32)) {
1477                 condlog(3, "%s: failed to get device number", mapname);
1478                 return 1;
1479         }
1480
1481         if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) {
1482                 condlog(3, "%s: couldn't make dm task", mapname);
1483                 return 0;
1484         }
1485
1486         if (!dm_task_set_name(dmt, mapname))
1487                 goto out;
1488
1489         dm_task_no_open_count(dmt);
1490
1491         if (!dm_task_run(dmt))
1492                 goto out;
1493
1494         if (!dm_task_get_info(dmt, &info))
1495                 goto out;
1496
1497         if (!(deps = dm_task_get_deps(dmt)))
1498                 goto out;
1499
1500         if (!info.exists)
1501                 goto out;
1502
1503         for (i = 0; i < deps->count; i++) {
1504                 sprintf(dm_dep, "%d:%d",
1505                         major(deps->device[i]),
1506                         minor(deps->device[i]));
1507                 sysfs_check_holders(dm_dep, dev_t);
1508         }
1509
1510         dm_task_destroy (dmt);
1511
1512         r = 1;
1513 out:
1514         return r;
1515 }
1516
1517 int dm_setgeometry(struct multipath *mpp)
1518 {
1519         struct dm_task *dmt;
1520         struct path *pp;
1521         char heads[4], sectors[4];
1522         char cylinders[10], start[32];
1523         int r = 0;
1524
1525         if (!mpp)
1526                 return 1;
1527
1528         pp = first_path(mpp);
1529         if (!pp) {
1530                 condlog(3, "%s: no path for geometry", mpp->alias);
1531                 return 1;
1532         }
1533         if (pp->geom.cylinders == 0 ||
1534             pp->geom.heads == 0 ||
1535             pp->geom.sectors == 0) {
1536                 condlog(3, "%s: invalid geometry on %s", mpp->alias, pp->dev);
1537                 return 1;
1538         }
1539
1540         if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
1541                 return 0;
1542
1543         if (!dm_task_set_name(dmt, mpp->alias))
1544                 goto out;
1545
1546         dm_task_no_open_count(dmt);
1547
1548         /* What a sick interface ... */
1549         snprintf(heads, 4, "%u", pp->geom.heads);
1550         snprintf(sectors, 4, "%u", pp->geom.sectors);
1551         snprintf(cylinders, 10, "%u", pp->geom.cylinders);
1552         snprintf(start, 32, "%lu", pp->geom.start);
1553         if (!dm_task_set_geometry(dmt, cylinders, heads, sectors, start)) {
1554                 condlog(3, "%s: Failed to set geometry", mpp->alias);
1555                 goto out;
1556         }
1557
1558         r = dm_task_run(dmt);
1559 out:
1560         dm_task_destroy(dmt);
1561
1562         return r;
1563 }