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