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