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