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