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