Imported Upstream version 0.8.9
[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 #include <syslog.h>
16 #include <sys/sysmacros.h>
17 #include <linux/dm-ioctl.h>
18
19 #include "util.h"
20 #include "checkers.h"
21 #include "vector.h"
22 #include "structs.h"
23 #include "debug.h"
24 #include "devmapper.h"
25 #include "sysfs.h"
26 #include "config.h"
27 #include "wwids.h"
28 #include "version.h"
29 #include "time-util.h"
30
31 #include "log_pthread.h"
32 #include <sys/types.h>
33 #include <time.h>
34
35 #define MAX_WAIT 5
36 #define LOOPS_PER_SEC 5
37
38 #define INVALID_VERSION ~0U
39 static unsigned int dm_library_version[3] = { INVALID_VERSION, };
40 static unsigned int dm_kernel_version[3] = { INVALID_VERSION, };
41 static unsigned int dm_mpath_target_version[3] = { INVALID_VERSION, };
42
43 static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;
44 static pthread_once_t versions_initialized = PTHREAD_ONCE_INIT;
45 static pthread_mutex_t libmp_dm_lock = PTHREAD_MUTEX_INITIALIZER;
46
47 static int dm_conf_verbosity;
48
49 #ifdef LIBDM_API_DEFERRED
50 static int dm_cancel_remove_partmaps(const char * mapname);
51 #define __DR_UNUSED__ /* empty */
52 #else
53 #define __DR_UNUSED__ __attribute__((unused))
54 #endif
55
56 static int do_foreach_partmaps(const char * mapname,
57                                int (*partmap_func)(const char *, void *),
58                                void *data);
59
60 #ifndef LIBDM_API_COOKIE
61 static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a)
62 {
63         return 1;
64 }
65
66 static void libmp_udev_wait(unsigned int c)
67 {
68 }
69
70 static void dm_udev_set_sync_support(int c)
71 {
72 }
73 #else
74 static void libmp_udev_wait(unsigned int c)
75 {
76         pthread_mutex_lock(&libmp_dm_lock);
77         pthread_cleanup_push(cleanup_mutex, &libmp_dm_lock);
78         dm_udev_wait(c);
79         pthread_cleanup_pop(1);
80 }
81 #endif
82
83 int libmp_dm_task_run(struct dm_task *dmt)
84 {
85         int r;
86
87         pthread_mutex_lock(&libmp_dm_lock);
88         pthread_cleanup_push(cleanup_mutex, &libmp_dm_lock);
89         r = dm_task_run(dmt);
90         pthread_cleanup_pop(1);
91         return r;
92 }
93
94 __attribute__((format(printf, 4, 5))) static void
95 dm_write_log (int level, const char *file, int line, const char *f, ...)
96 {
97         va_list ap;
98
99         /*
100          * libdm uses the same log levels as syslog,
101          * except that EMERG/ALERT are not used
102          */
103         if (level > LOG_DEBUG)
104                 level = LOG_DEBUG;
105
106         if (level > dm_conf_verbosity)
107                 return;
108
109         va_start(ap, f);
110         if (logsink != LOGSINK_SYSLOG) {
111                 if (logsink == LOGSINK_STDERR_WITH_TIME) {
112                         struct timespec ts;
113                         char buff[32];
114
115                         get_monotonic_time(&ts);
116                         safe_sprintf(buff, "%ld.%06ld",
117                                      (long)ts.tv_sec, ts.tv_nsec/1000);
118                         fprintf(stderr, "%s | ", buff);
119                 }
120                 fprintf(stderr, "libdevmapper: %s(%i): ", file, line);
121                 vfprintf(stderr, f, ap);
122                 fprintf(stderr, "\n");
123         } else {
124                 condlog(level >= LOG_ERR ? level - LOG_ERR : 0,
125                         "libdevmapper: %s(%i): ", file, line);
126                 log_safe(level, f, ap);
127         }
128         va_end(ap);
129
130         return;
131 }
132
133 static void dm_init(int v)
134 {
135         /*
136          * This maps libdm's standard loglevel _LOG_WARN (= 4), which is rather
137          * quiet in practice, to multipathd's default verbosity 2
138          */
139         dm_conf_verbosity = v + 2;
140         dm_log_init(&dm_write_log);
141 }
142
143 static void init_dm_library_version(void)
144 {
145         char version[64];
146         unsigned int v[3];
147
148         dm_get_library_version(version, sizeof(version));
149         if (sscanf(version, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) {
150                 condlog(0, "invalid libdevmapper version %s", version);
151                 return;
152         }
153         memcpy(dm_library_version, v, sizeof(dm_library_version));
154         condlog(3, "libdevmapper version %u.%.2u.%.2u",
155                 dm_library_version[0], dm_library_version[1],
156                 dm_library_version[2]);
157 }
158
159 static int
160 dm_lib_prereq (void)
161 {
162
163 #if defined(LIBDM_API_HOLD_CONTROL)
164         unsigned int minv[3] = {1, 2, 111};
165 #elif defined(LIBDM_API_GET_ERRNO)
166         unsigned int minv[3] = {1, 2, 99};
167 #elif defined(LIBDM_API_DEFERRED)
168         unsigned int minv[3] = {1, 2, 89};
169 #elif defined(DM_SUBSYSTEM_UDEV_FLAG0)
170         unsigned int minv[3] = {1, 2, 82};
171 #elif defined(LIBDM_API_COOKIE)
172         unsigned int minv[3] = {1, 2, 38};
173 #else
174         unsigned int minv[3] = {1, 2, 8};
175 #endif
176
177         if (VERSION_GE(dm_library_version, minv))
178                 return 0;
179         condlog(0, "libdevmapper version must be >= %u.%.2u.%.2u",
180                 minv[0], minv[1], minv[2]);
181         return 1;
182 }
183
184 static void init_dm_drv_version(void)
185 {
186         char buff[64];
187         unsigned int v[3];
188
189         if (!dm_driver_version(buff, sizeof(buff))) {
190                 condlog(0, "cannot get kernel dm version");
191                 return;
192         }
193         if (sscanf(buff, "%u.%u.%u ", &v[0], &v[1], &v[2]) != 3) {
194                 condlog(0, "invalid kernel dm version '%s'", buff);
195                 return;
196         }
197         memcpy(dm_kernel_version, v, sizeof(dm_library_version));
198         condlog(3, "kernel device mapper v%u.%u.%u",
199                 dm_kernel_version[0],
200                 dm_kernel_version[1],
201                 dm_kernel_version[2]);
202 }
203
204 static int dm_tgt_version (unsigned int *version, char *str)
205 {
206         int r = 2;
207         struct dm_task *dmt;
208         struct dm_versions *target;
209         struct dm_versions *last_target;
210         unsigned int *v;
211
212         /*
213          * We have to call dm_task_create() and not libmp_dm_task_create()
214          * here to avoid a recursive invocation of
215          * pthread_once(&dm_initialized), which would cause a deadlock.
216          */
217         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
218                 return 1;
219
220         dm_task_no_open_count(dmt);
221
222         if (!libmp_dm_task_run(dmt)) {
223                 dm_log_error(2, DM_DEVICE_LIST_VERSIONS, dmt);
224                 condlog(0, "Can not communicate with kernel DM");
225                 goto out;
226         }
227         target = dm_task_get_versions(dmt);
228
229         do {
230                 last_target = target;
231                 if (!strncmp(str, target->name, strlen(str))) {
232                         r = 1;
233                         break;
234                 }
235                 target = (void *) target + target->next;
236         } while (last_target != target);
237
238         if (r == 2) {
239                 condlog(0, "DM %s kernel driver not loaded", str);
240                 goto out;
241         }
242         v = target->version;
243         version[0] = v[0];
244         version[1] = v[1];
245         version[2] = v[2];
246         r = 0;
247 out:
248         dm_task_destroy(dmt);
249         return r;
250 }
251
252 static void init_dm_mpath_version(void)
253 {
254         if (!dm_tgt_version(dm_mpath_target_version, TGT_MPATH))
255                 condlog(3, "DM multipath kernel driver v%u.%u.%u",
256                         dm_mpath_target_version[0],
257                         dm_mpath_target_version[1],
258                         dm_mpath_target_version[2]);
259 }
260
261 static int dm_tgt_prereq (unsigned int *ver)
262 {
263         unsigned int minv[3] = {1, 0, 3};
264
265         if (VERSION_GE(dm_mpath_target_version, minv)) {
266                 if (ver) {
267                         ver[0] = dm_mpath_target_version[0];
268                         ver[1] = dm_mpath_target_version[1];
269                         ver[2] = dm_mpath_target_version[2];
270                 }
271                 return 0;
272         }
273
274         condlog(0, "DM multipath kernel driver must be >= v%u.%u.%u",
275                 minv[0], minv[1], minv[2]);
276         return 1;
277 }
278
279 static void _init_versions(void)
280 {
281         /* Can't use condlog here because of how VERSION_STRING is defined */
282         if (3 <= libmp_verbosity)
283                 dlog(3, VERSION_STRING);
284         init_dm_library_version();
285         init_dm_drv_version();
286         init_dm_mpath_version();
287 }
288
289 static int init_versions(void) {
290         pthread_once(&versions_initialized, _init_versions);
291         return (dm_library_version[0] == INVALID_VERSION ||
292                 dm_kernel_version[0] == INVALID_VERSION ||
293                 dm_mpath_target_version[0] == INVALID_VERSION);
294 }
295
296 int dm_prereq(unsigned int *v)
297 {
298         if (init_versions())
299                 return 1;
300         if (dm_lib_prereq())
301                 return 1;
302         return dm_tgt_prereq(v);
303 }
304
305 int libmp_get_version(int which, unsigned int version[3])
306 {
307         unsigned int *src_version;
308
309         init_versions();
310         switch (which) {
311         case DM_LIBRARY_VERSION:
312                 src_version = dm_library_version;
313                 break;
314         case DM_KERNEL_VERSION:
315                 src_version = dm_kernel_version;
316                 break;
317         case DM_MPATH_TARGET_VERSION:
318                 src_version = dm_mpath_target_version;
319                 break;
320         case MULTIPATH_VERSION:
321                 version[0] = (VERSION_CODE >> 16) & 0xff;
322                 version[1] = (VERSION_CODE >> 8) & 0xff;
323                 version[2] = VERSION_CODE & 0xff;
324                 return 0;
325         default:
326                 condlog(0, "%s: invalid value for 'which'", __func__);
327                 return 1;
328         }
329         if (src_version[0] == INVALID_VERSION)
330                 return 1;
331         memcpy(version, src_version, 3 * sizeof(*version));
332         return 0;
333 }
334
335 static int libmp_dm_udev_sync = 0;
336
337 void libmp_udev_set_sync_support(int on)
338 {
339         libmp_dm_udev_sync = !!on;
340 }
341
342 static bool libmp_dm_init_called;
343 void libmp_dm_exit(void)
344 {
345         if (!libmp_dm_init_called)
346                 return;
347
348         /* switch back to default libdm logging */
349         dm_log_init(NULL);
350 #ifdef LIBDM_API_HOLD_CONTROL
351         /* make sure control fd is closed in dm_lib_release() */
352         dm_hold_control_dev(0);
353 #endif
354 }
355
356 static void libmp_dm_init(void)
357 {
358         unsigned int version[3];
359
360         if (dm_prereq(version))
361                 exit(1);
362         dm_init(libmp_verbosity);
363 #ifdef LIBDM_API_HOLD_CONTROL
364         dm_hold_control_dev(1);
365 #endif
366         dm_udev_set_sync_support(libmp_dm_udev_sync);
367         libmp_dm_init_called = true;
368 }
369
370 static void _do_skip_libmp_dm_init(void)
371 {
372 }
373
374 void skip_libmp_dm_init(void)
375 {
376         pthread_once(&dm_initialized, _do_skip_libmp_dm_init);
377 }
378
379 struct dm_task*
380 libmp_dm_task_create(int task)
381 {
382         pthread_once(&dm_initialized, libmp_dm_init);
383         return dm_task_create(task);
384 }
385
386 #define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS)
387
388 static int
389 dm_simplecmd (int task, const char *name, int no_flush, int need_sync,
390               uint16_t udev_flags, int deferred_remove __DR_UNUSED__) {
391         int r = 0;
392         int udev_wait_flag = ((need_sync || udev_flags) &&
393                               (task == DM_DEVICE_RESUME ||
394                                task == DM_DEVICE_REMOVE));
395         uint32_t cookie = 0;
396         struct dm_task *dmt;
397
398         if (!(dmt = libmp_dm_task_create (task)))
399                 return 0;
400
401         if (!dm_task_set_name (dmt, name))
402                 goto out;
403
404         dm_task_no_open_count(dmt);
405         dm_task_skip_lockfs(dmt);       /* for DM_DEVICE_RESUME */
406 #ifdef LIBDM_API_FLUSH
407         if (no_flush)
408                 dm_task_no_flush(dmt);          /* for DM_DEVICE_SUSPEND/RESUME */
409 #endif
410 #ifdef LIBDM_API_DEFERRED
411         if (do_deferred(deferred_remove))
412                 dm_task_deferred_remove(dmt);
413 #endif
414         if (udev_wait_flag &&
415             !dm_task_set_cookie(dmt, &cookie,
416                                 DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags))
417                 goto out;
418
419         r = libmp_dm_task_run (dmt);
420         if (!r)
421                 dm_log_error(2, task, dmt);
422
423         if (udev_wait_flag)
424                         libmp_udev_wait(cookie);
425 out:
426         dm_task_destroy (dmt);
427         return r;
428 }
429
430 int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags)
431 {
432         return dm_simplecmd(task, name, 0, 1, udev_flags, 0);
433 }
434
435 int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags)
436 {
437         return dm_simplecmd(task, name, 1, 1, udev_flags, 0);
438 }
439
440 static int
441 dm_device_remove (const char *name, int needsync, int deferred_remove) {
442         return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0,
443                             deferred_remove);
444 }
445
446 static int
447 dm_addmap (int task, const char *target, struct multipath *mpp,
448            char * params, int ro, uint16_t udev_flags) {
449         int r = 0;
450         struct dm_task *dmt;
451         char *prefixed_uuid = NULL;
452         uint32_t cookie = 0;
453
454         if (task == DM_DEVICE_CREATE && strlen(mpp->wwid) == 0) {
455                 condlog(1, "%s: refusing to create map with empty WWID",
456                         mpp->alias);
457                 return 0;
458         }
459
460         /* Need to add this here to allow 0 to be passed in udev_flags */
461         udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
462
463         if (!(dmt = libmp_dm_task_create (task)))
464                 return 0;
465
466         if (!dm_task_set_name (dmt, mpp->alias))
467                 goto addout;
468
469         if (!dm_task_add_target (dmt, 0, mpp->size, target, params))
470                 goto addout;
471
472         if (ro)
473                 dm_task_set_ro(dmt);
474
475         if (task == DM_DEVICE_CREATE) {
476                 if (asprintf(&prefixed_uuid, UUID_PREFIX "%s", mpp->wwid) < 0) {
477                         condlog(0, "cannot create prefixed uuid : %s",
478                                 strerror(errno));
479                         goto addout;
480                 }
481                 if (!dm_task_set_uuid(dmt, prefixed_uuid))
482                         goto freeout;
483                 dm_task_skip_lockfs(dmt);
484 #ifdef LIBDM_API_FLUSH
485                 dm_task_no_flush(dmt);
486 #endif
487         }
488
489         if (mpp->attribute_flags & (1 << ATTR_MODE) &&
490             !dm_task_set_mode(dmt, mpp->mode))
491                 goto freeout;
492         if (mpp->attribute_flags & (1 << ATTR_UID) &&
493             !dm_task_set_uid(dmt, mpp->uid))
494                 goto freeout;
495         if (mpp->attribute_flags & (1 << ATTR_GID) &&
496             !dm_task_set_gid(dmt, mpp->gid))
497                 goto freeout;
498         condlog(2, "%s: %s [0 %llu %s %s]", mpp->alias,
499                 task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size,
500                 target, params);
501
502         dm_task_no_open_count(dmt);
503
504         if (task == DM_DEVICE_CREATE &&
505             !dm_task_set_cookie(dmt, &cookie, udev_flags))
506                 goto freeout;
507
508         r = libmp_dm_task_run (dmt);
509         if (!r)
510                 dm_log_error(2, task, dmt);
511
512         if (task == DM_DEVICE_CREATE)
513                         libmp_udev_wait(cookie);
514 freeout:
515         if (prefixed_uuid)
516                 free(prefixed_uuid);
517
518 addout:
519         dm_task_destroy (dmt);
520
521         if (r)
522                 mpp->need_reload = false;
523         return r;
524 }
525
526 static uint16_t build_udev_flags(const struct multipath *mpp, int reload)
527 {
528         /* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */
529         return  (mpp->skip_kpartx == SKIP_KPARTX_ON ?
530                  MPATH_UDEV_NO_KPARTX_FLAG : 0) |
531                 ((count_active_pending_paths(mpp) == 0 ||
532                   mpp->ghost_delay_tick > 0) ?
533                  MPATH_UDEV_NO_PATHS_FLAG : 0) |
534                 (reload && !mpp->force_udev_reload ?
535                  MPATH_UDEV_RELOAD_FLAG : 0);
536 }
537
538 int dm_addmap_create (struct multipath *mpp, char * params)
539 {
540         int ro;
541         uint16_t udev_flags = build_udev_flags(mpp, 0);
542
543         for (ro = 0; ro <= 1; ro++) {
544                 int err;
545
546                 if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro,
547                               udev_flags)) {
548                         if (unmark_failed_wwid(mpp->wwid) ==
549                             WWID_FAILED_CHANGED)
550                                 mpp->needs_paths_uevent = 1;
551                         return 1;
552                 }
553                 /*
554                  * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
555                  * Failing the second part leaves an empty map. Clean it up.
556                  */
557                 err = errno;
558                 if (dm_map_present(mpp->alias)) {
559                         condlog(3, "%s: failed to load map (a path might be in use)", mpp->alias);
560                         dm_flush_map_nosync(mpp->alias);
561                 }
562                 if (err != EROFS) {
563                         condlog(3, "%s: failed to load map, error %d",
564                                 mpp->alias, err);
565                         break;
566                 }
567         }
568         if (mark_failed_wwid(mpp->wwid) == WWID_FAILED_CHANGED)
569                 mpp->needs_paths_uevent = 1;
570         return 0;
571 }
572
573 #define ADDMAP_RW 0
574 #define ADDMAP_RO 1
575
576 int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
577 {
578         int r = 0;
579         uint16_t udev_flags = build_udev_flags(mpp, 1);
580
581         /*
582          * DM_DEVICE_RELOAD cannot wait on a cookie, as
583          * the cookie will only ever be released after an
584          * DM_DEVICE_RESUME. So call DM_DEVICE_RESUME
585          * after each successful call to DM_DEVICE_RELOAD.
586          */
587         if (!mpp->force_readonly)
588                 r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params,
589                               ADDMAP_RW, 0);
590         if (!r) {
591                 if (!mpp->force_readonly && errno != EROFS)
592                         return 0;
593                 r = dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp,
594                               params, ADDMAP_RO, 0);
595         }
596         if (r)
597                 r = dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush,
598                                  1, udev_flags, 0);
599         if (r)
600                 return r;
601
602         /* If the resume failed, dm will leave the device suspended, and
603          * drop the new table, so doing a second resume will try using
604          * the original table */
605         if (dm_is_suspended(mpp->alias))
606                 dm_simplecmd(DM_DEVICE_RESUME, mpp->alias, !flush, 1,
607                              udev_flags, 0);
608         return 0;
609 }
610
611 bool
612 has_dm_info(const struct multipath *mpp)
613 {
614         return (mpp && mpp->dmi.exists != 0);
615 }
616
617 int
618 dm_get_info(const char *name, struct dm_info *info)
619 {
620         int r = -1;
621         struct dm_task *dmt;
622
623         if (!name || !info)
624                 return r;
625
626         if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
627                 return r;
628
629         if (!dm_task_set_name(dmt, name))
630                 goto out;
631
632         dm_task_no_open_count(dmt);
633
634         if (!libmp_dm_task_run(dmt)) {
635                 dm_log_error(3, DM_DEVICE_INFO, dmt);
636                 goto out;
637         }
638
639         if (!dm_task_get_info(dmt, info))
640                 goto out;
641
642         if (!info->exists)
643                 goto out;
644
645         r = 0;
646 out:
647         dm_task_destroy(dmt);
648         return r;
649 }
650
651 int dm_map_present(const char * str)
652 {
653         struct dm_info info;
654
655         return (dm_get_info(str, &info) == 0);
656 }
657
658 int dm_get_map(const char *name, unsigned long long *size, char **outparams)
659 {
660         int r = DMP_ERR;
661         struct dm_task *dmt;
662         uint64_t start, length;
663         char *target_type = NULL;
664         char *params = NULL;
665
666         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
667                 return r;
668
669         if (!dm_task_set_name(dmt, name))
670                 goto out;
671
672         dm_task_no_open_count(dmt);
673
674         errno = 0;
675         if (!libmp_dm_task_run(dmt)) {
676                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
677                 if (dm_task_get_errno(dmt) == ENXIO)
678                         r = DMP_NOT_FOUND;
679                 goto out;
680         }
681
682         r = DMP_NOT_FOUND;
683         /* Fetch 1st target */
684         if (dm_get_next_target(dmt, NULL, &start, &length,
685                                &target_type, &params) != NULL)
686                 /* more than one target */
687                 goto out;
688
689         if (size)
690                 *size = length;
691
692         if (!outparams)
693                 r = DMP_OK;
694         else {
695                 *outparams = strdup(params);
696                 r = *outparams ? DMP_OK : DMP_ERR;
697         }
698
699 out:
700         dm_task_destroy(dmt);
701         return r;
702 }
703
704 static int
705 dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
706 {
707         struct dm_task *dmt;
708         const char *uuidtmp;
709         int r = 1;
710
711         dmt = libmp_dm_task_create(DM_DEVICE_INFO);
712         if (!dmt)
713                 return 1;
714
715         if (!dm_task_set_name (dmt, name))
716                 goto uuidout;
717
718         if (!libmp_dm_task_run(dmt)) {
719                 dm_log_error(3, DM_DEVICE_INFO, dmt);
720                 goto uuidout;
721         }
722
723         uuidtmp = dm_task_get_uuid(dmt);
724         if (uuidtmp)
725                 strlcpy(uuid, uuidtmp, uuid_len);
726         else
727                 uuid[0] = '\0';
728
729         r = 0;
730 uuidout:
731         dm_task_destroy(dmt);
732         return r;
733 }
734
735 int dm_get_uuid(const char *name, char *uuid, int uuid_len)
736 {
737         char tmp[DM_UUID_LEN];
738
739         if (dm_get_prefixed_uuid(name, tmp, sizeof(tmp)))
740                 return 1;
741
742         if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
743                 strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
744         else
745                 uuid[0] = '\0';
746
747         return 0;
748 }
749
750 static int
751 is_mpath_part(const char *part_name, const char *map_name)
752 {
753         char *p;
754         char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
755
756         if (dm_get_prefixed_uuid(part_name, part_uuid, sizeof(part_uuid)))
757                 return 0;
758
759         if (dm_get_prefixed_uuid(map_name, map_uuid, sizeof(map_uuid)))
760                 return 0;
761
762         if (strncmp(part_uuid, "part", 4) != 0)
763                 return 0;
764
765         p = strstr(part_uuid, UUID_PREFIX);
766         if (p && !strcmp(p, map_uuid))
767                 return 1;
768
769         return 0;
770 }
771
772 int dm_get_status(const char *name, char **outstatus)
773 {
774         int r = DMP_ERR;
775         struct dm_task *dmt;
776         uint64_t start, length;
777         char *target_type = NULL;
778         char *status = NULL;
779
780         if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
781                 return r;
782
783         if (!dm_task_set_name(dmt, name))
784                 goto out;
785
786         dm_task_no_open_count(dmt);
787
788         errno = 0;
789         if (!libmp_dm_task_run(dmt)) {
790                 dm_log_error(3, DM_DEVICE_STATUS, dmt);
791                 if (dm_task_get_errno(dmt) == ENXIO)
792                         r = DMP_NOT_FOUND;
793                 goto out;
794         }
795
796         r = DMP_NOT_FOUND;
797         /* Fetch 1st target */
798         if (dm_get_next_target(dmt, NULL, &start, &length,
799                                &target_type, &status) != NULL)
800                 goto out;
801
802         if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
803                 goto out;
804
805         if (!status) {
806                 condlog(2, "get null status.");
807                 goto out;
808         }
809
810         if (!outstatus)
811                 r = DMP_OK;
812         else {
813                 *outstatus = strdup(status);
814                 r = *outstatus ? DMP_OK : DMP_ERR;
815         }
816 out:
817         if (r != DMP_OK)
818                 condlog(0, "%s: error getting map status string", name);
819
820         dm_task_destroy(dmt);
821         return r;
822 }
823
824 /*
825  * returns:
826  *    1 : match
827  *    0 : no match
828  *   -1 : empty map, or more than 1 target
829  */
830 int dm_type(const char *name, char *type)
831 {
832         int r = 0;
833         struct dm_task *dmt;
834         uint64_t start, length;
835         char *target_type = NULL;
836         char *params;
837
838         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
839                 return 0;
840
841         if (!dm_task_set_name(dmt, name))
842                 goto out;
843
844         dm_task_no_open_count(dmt);
845
846         if (!libmp_dm_task_run(dmt)) {
847                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
848                 goto out;
849         }
850
851         /* Fetch 1st target */
852         if (dm_get_next_target(dmt, NULL, &start, &length,
853                                &target_type, &params) != NULL)
854                 /* multiple targets */
855                 r = -1;
856         else if (!target_type)
857                 r = -1;
858         else if (!strcmp(target_type, type))
859                 r = 1;
860
861 out:
862         dm_task_destroy(dmt);
863         return r;
864 }
865
866 /*
867  * returns:
868  * 1  : is multipath device
869  * 0  : is not multipath device
870  * -1 : error
871  */
872 int dm_is_mpath(const char *name)
873 {
874         int r = -1;
875         struct dm_task *dmt;
876         struct dm_info info;
877         uint64_t start, length;
878         char *target_type = NULL;
879         char *params;
880         const char *uuid;
881
882         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
883                 goto out;
884
885         if (!dm_task_set_name(dmt, name))
886                 goto out_task;
887
888         dm_task_no_open_count(dmt);
889
890         if (!libmp_dm_task_run(dmt)) {
891                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
892                 goto out_task;
893         }
894
895         if (!dm_task_get_info(dmt, &info))
896                 goto out_task;
897
898         r = 0;
899
900         if (!info.exists)
901                 goto out_task;
902
903         uuid = dm_task_get_uuid(dmt);
904
905         if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
906                 goto out_task;
907
908         /* Fetch 1st target */
909         if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
910                                &params) != NULL)
911                 /* multiple targets */
912                 goto out_task;
913
914         if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
915                 goto out_task;
916
917         r = 1;
918 out_task:
919         dm_task_destroy(dmt);
920 out:
921         if (r < 0)
922                 condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
923         return r;
924 }
925
926 /*
927  * Return
928  *   1 : map with uuid exists
929  *   0 : map with uuid doesn't exist
930  *  -1 : error
931  */
932 int
933 dm_map_present_by_uuid(const char *uuid)
934 {
935         struct dm_task *dmt;
936         struct dm_info info;
937         char prefixed_uuid[WWID_SIZE + UUID_PREFIX_LEN];
938         int r = -1;
939
940         if (!uuid || uuid[0] == '\0')
941                 return 0;
942
943         if (safe_sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid))
944                 goto out;
945
946         if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
947                 goto out;
948
949         dm_task_no_open_count(dmt);
950
951         if (!dm_task_set_uuid(dmt, prefixed_uuid))
952                 goto out_task;
953
954         if (!libmp_dm_task_run(dmt)) {
955                 dm_log_error(3, DM_DEVICE_INFO, dmt);
956                 goto out_task;
957         }
958
959         if (!dm_task_get_info(dmt, &info))
960                 goto out_task;
961
962         r = !!info.exists;
963
964 out_task:
965         dm_task_destroy(dmt);
966 out:
967         if (r < 0)
968                 condlog(3, "%s: dm command failed in %s: %s", uuid,
969                         __FUNCTION__, strerror(errno));
970         return r;
971 }
972
973 static int
974 dm_dev_t (const char * mapname, char * dev_t, int len)
975 {
976         struct dm_info info;
977
978         if (dm_get_info(mapname, &info) != 0)
979                 return 1;
980
981         if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
982                 return 1;
983
984         return 0;
985 }
986
987 int
988 dm_get_opencount (const char * mapname)
989 {
990         int r = -1;
991         struct dm_task *dmt;
992         struct dm_info info;
993
994         if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
995                 return 0;
996
997         if (!dm_task_set_name(dmt, mapname))
998                 goto out;
999
1000         if (!libmp_dm_task_run(dmt)) {
1001                 dm_log_error(3, DM_DEVICE_INFO, dmt);
1002                 goto out;
1003         }
1004
1005         if (!dm_task_get_info(dmt, &info))
1006                 goto out;
1007
1008         if (!info.exists)
1009                 goto out;
1010
1011         r = info.open_count;
1012 out:
1013         dm_task_destroy(dmt);
1014         return r;
1015 }
1016
1017 int
1018 dm_get_major_minor(const char *name, int *major, int *minor)
1019 {
1020         struct dm_info info;
1021
1022         if (dm_get_info(name, &info) != 0)
1023                 return -1;
1024
1025         *major = info.major;
1026         *minor = info.minor;
1027         return 0;
1028 }
1029
1030 static int
1031 has_partmap(const char *name __attribute__((unused)),
1032             void *data __attribute__((unused)))
1033 {
1034         return 1;
1035 }
1036
1037 static int
1038 partmap_in_use(const char *name, void *data)
1039 {
1040         int part_count, *ret_count = (int *)data;
1041         int open_count = dm_get_opencount(name);
1042
1043         if (ret_count)
1044                 (*ret_count)++;
1045         part_count = 0;
1046         if (open_count) {
1047                 if (do_foreach_partmaps(name, partmap_in_use, &part_count))
1048                         return 1;
1049                 if (open_count != part_count) {
1050                         condlog(2, "%s: map in use", name);
1051                         return 1;
1052                 }
1053         }
1054         return 0;
1055 }
1056
1057 int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
1058                    int need_suspend, int retries)
1059 {
1060         int r;
1061         int queue_if_no_path = 0;
1062         int udev_flags = 0;
1063         unsigned long long mapsize;
1064         char *params = NULL;
1065
1066         if (dm_is_mpath(mapname) != 1)
1067                 return 0; /* nothing to do */
1068
1069         /* if the device currently has no partitions, do not
1070            run kpartx on it if you fail to delete it */
1071         if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0)
1072                 udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG;
1073
1074         /* If you aren't doing a deferred remove, make sure that no
1075          * devices are in use */
1076         if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL))
1077                         return 1;
1078
1079         if (need_suspend &&
1080             dm_get_map(mapname, &mapsize, &params) == DMP_OK &&
1081             strstr(params, "queue_if_no_path")) {
1082                 if (!dm_queue_if_no_path(mapname, 0))
1083                         queue_if_no_path = 1;
1084                 else
1085                         /* Leave queue_if_no_path alone if unset failed */
1086                         queue_if_no_path = -1;
1087         }
1088         free(params);
1089         params = NULL;
1090
1091         if (dm_remove_partmaps(mapname, need_sync, deferred_remove))
1092                 return 1;
1093
1094         if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) {
1095                 condlog(2, "%s: map in use", mapname);
1096                 return 1;
1097         }
1098
1099         do {
1100                 if (need_suspend && queue_if_no_path != -1)
1101                         dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0);
1102
1103                 r = dm_device_remove(mapname, need_sync, deferred_remove);
1104
1105                 if (r) {
1106                         if (do_deferred(deferred_remove)
1107                             && dm_map_present(mapname)) {
1108                                 condlog(4, "multipath map %s remove deferred",
1109                                         mapname);
1110                                 return 2;
1111                         }
1112                         condlog(4, "multipath map %s removed", mapname);
1113                         return 0;
1114                 } else {
1115                         condlog(2, "failed to remove multipath map %s",
1116                                 mapname);
1117                         if (need_suspend && queue_if_no_path != -1) {
1118                                 dm_simplecmd_noflush(DM_DEVICE_RESUME,
1119                                                      mapname, udev_flags);
1120                         }
1121                 }
1122                 if (retries)
1123                         sleep(1);
1124         } while (retries-- > 0);
1125
1126         if (queue_if_no_path == 1)
1127                 dm_queue_if_no_path(mapname, 1);
1128
1129         return 1;
1130 }
1131
1132 #ifdef LIBDM_API_DEFERRED
1133
1134 int
1135 dm_flush_map_nopaths(const char * mapname, int deferred_remove)
1136 {
1137         return _dm_flush_map(mapname, 1, deferred_remove, 0, 0);
1138 }
1139
1140 #else
1141
1142 int
1143 dm_flush_map_nopaths(const char * mapname,
1144                      int deferred_remove __attribute__((unused)))
1145 {
1146         return _dm_flush_map(mapname, 1, 0, 0, 0);
1147 }
1148
1149 #endif
1150
1151 int dm_flush_maps (int need_suspend, int retries)
1152 {
1153         int r = 1;
1154         struct dm_task *dmt;
1155         struct dm_names *names;
1156         unsigned next = 0;
1157
1158         if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))
1159                 return r;
1160
1161         dm_task_no_open_count(dmt);
1162
1163         if (!libmp_dm_task_run (dmt)) {
1164                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1165                 goto out;
1166         }
1167
1168         if (!(names = dm_task_get_names (dmt)))
1169                 goto out;
1170
1171         r = 0;
1172         if (!names->dev)
1173                 goto out;
1174
1175         do {
1176                 if (need_suspend)
1177                         r |= dm_suspend_and_flush_map(names->name, retries);
1178                 else
1179                         r |= dm_flush_map(names->name);
1180                 next = names->next;
1181                 names = (void *) names + next;
1182         } while (next);
1183
1184 out:
1185         dm_task_destroy (dmt);
1186         return r;
1187 }
1188
1189 int
1190 dm_message(const char * mapname, char * message)
1191 {
1192         int r = 1;
1193         struct dm_task *dmt;
1194
1195         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TARGET_MSG)))
1196                 return 1;
1197
1198         if (!dm_task_set_name(dmt, mapname))
1199                 goto out;
1200
1201         if (!dm_task_set_sector(dmt, 0))
1202                 goto out;
1203
1204         if (!dm_task_set_message(dmt, message))
1205                 goto out;
1206
1207         dm_task_no_open_count(dmt);
1208
1209         if (!libmp_dm_task_run(dmt)) {
1210                 dm_log_error(2, DM_DEVICE_TARGET_MSG, dmt);
1211                 goto out;
1212         }
1213
1214         r = 0;
1215 out:
1216         if (r)
1217                 condlog(0, "DM message failed [%s]", message);
1218
1219         dm_task_destroy(dmt);
1220         return r;
1221 }
1222
1223 int
1224 dm_fail_path(const char * mapname, char * path)
1225 {
1226         char message[32];
1227
1228         if (snprintf(message, 32, "fail_path %s", path) > 32)
1229                 return 1;
1230
1231         return dm_message(mapname, message);
1232 }
1233
1234 int
1235 dm_reinstate_path(const char * mapname, char * path)
1236 {
1237         char message[32];
1238
1239         if (snprintf(message, 32, "reinstate_path %s", path) > 32)
1240                 return 1;
1241
1242         return dm_message(mapname, message);
1243 }
1244
1245 int
1246 dm_queue_if_no_path(const char *mapname, int enable)
1247 {
1248         char *message;
1249
1250         if (enable)
1251                 message = "queue_if_no_path";
1252         else
1253                 message = "fail_if_no_path";
1254
1255         return dm_message(mapname, message);
1256 }
1257
1258 static int
1259 dm_groupmsg (const char * msg, const char * mapname, int index)
1260 {
1261         char message[32];
1262
1263         if (snprintf(message, 32, "%s_group %i", msg, index) > 32)
1264                 return 1;
1265
1266         return dm_message(mapname, message);
1267 }
1268
1269 int
1270 dm_switchgroup(const char * mapname, int index)
1271 {
1272         return dm_groupmsg("switch", mapname, index);
1273 }
1274
1275 int
1276 dm_enablegroup(const char * mapname, int index)
1277 {
1278         return dm_groupmsg("enable", mapname, index);
1279 }
1280
1281 int
1282 dm_disablegroup(const char * mapname, int index)
1283 {
1284         return dm_groupmsg("disable", mapname, index);
1285 }
1286
1287 struct multipath *dm_get_multipath(const char *name)
1288 {
1289         struct multipath *mpp = NULL;
1290
1291         mpp = alloc_multipath();
1292         if (!mpp)
1293                 return NULL;
1294
1295         mpp->alias = strdup(name);
1296
1297         if (!mpp->alias)
1298                 goto out;
1299
1300         if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
1301                 goto out;
1302
1303         if (dm_get_uuid(name, mpp->wwid, WWID_SIZE) != 0)
1304                 condlog(2, "%s: failed to get uuid for %s", __func__, name);
1305         if (dm_get_info(name, &mpp->dmi) != 0)
1306                 condlog(2, "%s: failed to get info for %s", __func__, name);
1307
1308         return mpp;
1309 out:
1310         free_multipath(mpp, KEEP_PATHS);
1311         return NULL;
1312 }
1313
1314 int
1315 dm_get_maps (vector mp)
1316 {
1317         struct multipath * mpp;
1318         int r = 1;
1319         struct dm_task *dmt;
1320         struct dm_names *names;
1321         unsigned next = 0;
1322
1323         if (!mp)
1324                 return 1;
1325
1326         if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
1327                 return 1;
1328
1329         dm_task_no_open_count(dmt);
1330
1331         if (!libmp_dm_task_run(dmt)) {
1332                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1333                 goto out;
1334         }
1335
1336         if (!(names = dm_task_get_names(dmt)))
1337                 goto out;
1338
1339         if (!names->dev) {
1340                 r = 0; /* this is perfectly valid */
1341                 goto out;
1342         }
1343
1344         do {
1345                 if (dm_is_mpath(names->name) != 1)
1346                         goto next;
1347
1348                 mpp = dm_get_multipath(names->name);
1349                 if (!mpp)
1350                         goto out;
1351
1352                 if (!vector_alloc_slot(mp)) {
1353                         free_multipath(mpp, KEEP_PATHS);
1354                         goto out;
1355                 }
1356
1357                 vector_set_slot(mp, mpp);
1358                 mpp = NULL;
1359 next:
1360                 next = names->next;
1361                 names = (void *) names + next;
1362         } while (next);
1363
1364         r = 0;
1365         goto out;
1366 out:
1367         dm_task_destroy (dmt);
1368         return r;
1369 }
1370
1371 int
1372 dm_geteventnr (const char *name)
1373 {
1374         struct dm_info info;
1375
1376         if (dm_get_info(name, &info) != 0)
1377                 return -1;
1378
1379         return info.event_nr;
1380 }
1381
1382 int
1383 dm_is_suspended(const char *name)
1384 {
1385         struct dm_info info;
1386
1387         if (dm_get_info(name, &info) != 0)
1388                 return -1;
1389
1390         return info.suspended;
1391 }
1392
1393 char *
1394 dm_mapname(int major, int minor)
1395 {
1396         char * response = NULL;
1397         const char *map;
1398         struct dm_task *dmt;
1399         int r;
1400
1401         if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
1402                 return NULL;
1403
1404         if (!dm_task_set_major(dmt, major) ||
1405             !dm_task_set_minor(dmt, minor))
1406                 goto bad;
1407
1408         dm_task_no_open_count(dmt);
1409         r = libmp_dm_task_run(dmt);
1410         if (!r) {
1411                 dm_log_error(2, DM_DEVICE_STATUS, dmt);
1412                 goto bad;
1413         }
1414
1415         map = dm_task_get_name(dmt);
1416         if (map && strlen(map))
1417                 response = strdup((const char *)map);
1418
1419         dm_task_destroy(dmt);
1420         return response;
1421 bad:
1422         dm_task_destroy(dmt);
1423         condlog(0, "%i:%i: error fetching map name", major, minor);
1424         return NULL;
1425 }
1426
1427 static int
1428 do_foreach_partmaps (const char * mapname,
1429                      int (*partmap_func)(const char *, void *),
1430                      void *data)
1431 {
1432         struct dm_task *dmt;
1433         struct dm_names *names;
1434         unsigned next = 0;
1435         char *params = NULL;
1436         unsigned long long size;
1437         char dev_t[32];
1438         int r = 1;
1439         char *p;
1440
1441         if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
1442                 return 1;
1443
1444         dm_task_no_open_count(dmt);
1445
1446         if (!libmp_dm_task_run(dmt)) {
1447                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1448                 goto out;
1449         }
1450
1451         if (!(names = dm_task_get_names(dmt)))
1452                 goto out;
1453
1454         if (!names->dev) {
1455                 r = 0; /* this is perfectly valid */
1456                 goto out;
1457         }
1458
1459         if (dm_dev_t(mapname, &dev_t[0], 32))
1460                 goto out;
1461
1462         do {
1463                 if (
1464                     /*
1465                      * if there is only a single "linear" target
1466                      */
1467                     (dm_type(names->name, TGT_PART) == 1) &&
1468
1469                     /*
1470                      * and the uuid of the target is a partition of the
1471                      * uuid of the multipath device
1472                      */
1473                     is_mpath_part(names->name, mapname) &&
1474
1475                     /*
1476                      * and we can fetch the map table from the kernel
1477                      */
1478                     dm_get_map(names->name, &size, &params) == DMP_OK &&
1479
1480                     /*
1481                      * and the table maps over the multipath map
1482                      */
1483                     (p = strstr(params, dev_t)) &&
1484                     !isdigit(*(p + strlen(dev_t)))
1485                    ) {
1486                         if (partmap_func(names->name, data) != 0)
1487                                 goto out;
1488                 }
1489
1490                 free(params);
1491                 params = NULL;
1492                 next = names->next;
1493                 names = (void *) names + next;
1494         } while (next);
1495
1496         r = 0;
1497 out:
1498         free(params);
1499         dm_task_destroy (dmt);
1500         return r;
1501 }
1502
1503 struct remove_data {
1504         int need_sync;
1505         int deferred_remove;
1506 };
1507
1508 static int
1509 remove_partmap(const char *name, void *data)
1510 {
1511         struct remove_data *rd = (struct remove_data *)data;
1512
1513         if (dm_get_opencount(name)) {
1514                 dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove);
1515                 if (!do_deferred(rd->deferred_remove) &&
1516                     dm_get_opencount(name)) {
1517                         condlog(2, "%s: map in use", name);
1518                         return 1;
1519                 }
1520         }
1521         condlog(4, "partition map %s removed", name);
1522         dm_device_remove(name, rd->need_sync, rd->deferred_remove);
1523         return 0;
1524 }
1525
1526 int
1527 dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove)
1528 {
1529         struct remove_data rd = { need_sync, deferred_remove };
1530         return do_foreach_partmaps(mapname, remove_partmap, &rd);
1531 }
1532
1533 #ifdef LIBDM_API_DEFERRED
1534
1535 static int
1536 cancel_remove_partmap (const char *name, void *unused __attribute__((unused)))
1537 {
1538         if (dm_get_opencount(name))
1539                 dm_cancel_remove_partmaps(name);
1540         if (dm_message(name, "@cancel_deferred_remove") != 0)
1541                 condlog(0, "%s: can't cancel deferred remove: %s", name,
1542                         strerror(errno));
1543         return 0;
1544 }
1545
1546 static int
1547 dm_get_deferred_remove (const char * mapname)
1548 {
1549         struct dm_info info;
1550
1551         if (dm_get_info(mapname, &info) != 0)
1552                 return -1;
1553
1554         return info.deferred_remove;
1555 }
1556
1557 static int
1558 dm_cancel_remove_partmaps(const char * mapname) {
1559         return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
1560 }
1561
1562 int
1563 dm_cancel_deferred_remove (struct multipath *mpp)
1564 {
1565         int r = 0;
1566
1567         if (!dm_get_deferred_remove(mpp->alias))
1568                 return 0;
1569         if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS)
1570                 mpp->deferred_remove = DEFERRED_REMOVE_ON;
1571
1572         dm_cancel_remove_partmaps(mpp->alias);
1573         r = dm_message(mpp->alias, "@cancel_deferred_remove");
1574         if (r)
1575                 condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias,
1576                                 strerror(errno));
1577         else
1578                 condlog(2, "%s: canceled deferred remove", mpp->alias);
1579         return r;
1580 }
1581
1582 #else
1583
1584 int
1585 dm_cancel_deferred_remove (struct multipath *mpp __attribute__((unused)))
1586 {
1587         return 0;
1588 }
1589
1590 #endif
1591
1592 struct rename_data {
1593         const char *old;
1594         char *new;
1595         char *delim;
1596 };
1597
1598 static int
1599 rename_partmap (const char *name, void *data)
1600 {
1601         char *buff = NULL;
1602         int offset;
1603         struct rename_data *rd = (struct rename_data *)data;
1604
1605         if (strncmp(name, rd->old, strlen(rd->old)) != 0)
1606                 return 0;
1607         for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */
1608         if (asprintf(&buff, "%s%s%s", rd->new, rd->delim, name + offset) >= 0) {
1609                 dm_rename(name, buff, rd->delim, SKIP_KPARTX_OFF);
1610                 free(buff);
1611                 condlog(4, "partition map %s renamed", name);
1612         } else
1613                 condlog(1, "failed to rename partition map %s", name);
1614         return 0;
1615 }
1616
1617 int
1618 dm_rename_partmaps (const char * old, char * new, char *delim)
1619 {
1620         struct rename_data rd;
1621
1622         rd.old = old;
1623         rd.new = new;
1624
1625         if (delim)
1626                 rd.delim = delim;
1627         else {
1628                 if (isdigit(new[strlen(new)-1]))
1629                         rd.delim = "p";
1630                 else
1631                         rd.delim = "";
1632         }
1633         return do_foreach_partmaps(old, rename_partmap, &rd);
1634 }
1635
1636 int
1637 dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
1638 {
1639         int r = 0;
1640         struct dm_task *dmt;
1641         uint32_t cookie = 0;
1642         uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
1643
1644         if (dm_rename_partmaps(old, new, delim))
1645                 return r;
1646
1647         if (!(dmt = libmp_dm_task_create(DM_DEVICE_RENAME)))
1648                 return r;
1649
1650         if (!dm_task_set_name(dmt, old))
1651                 goto out;
1652
1653         if (!dm_task_set_newname(dmt, new))
1654                 goto out;
1655
1656         dm_task_no_open_count(dmt);
1657
1658         if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
1659                 goto out;
1660         r = libmp_dm_task_run(dmt);
1661         if (!r)
1662                 dm_log_error(2, DM_DEVICE_RENAME, dmt);
1663
1664         libmp_udev_wait(cookie);
1665
1666 out:
1667         dm_task_destroy(dmt);
1668
1669         return r;
1670 }
1671
1672 void dm_reassign_deps(char *table, const char *dep, const char *newdep)
1673 {
1674         char *n, *newtable;
1675         const char *p;
1676
1677         newtable = strdup(table);
1678         if (!newtable)
1679                 return;
1680         p = strstr(newtable, dep);
1681         n = table + (p - newtable);
1682         strcpy(n, newdep);
1683         n += strlen(newdep);
1684         p += strlen(dep);
1685         strcat(n, p);
1686         free(newtable);
1687 }
1688
1689 int dm_reassign_table(const char *name, char *old, char *new)
1690 {
1691         int r = 0, modified = 0;
1692         uint64_t start, length;
1693         struct dm_task *dmt, *reload_dmt;
1694         char *target, *params = NULL;
1695         char *buff;
1696         void *next = NULL;
1697
1698         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
1699                 return 0;
1700
1701         if (!dm_task_set_name(dmt, name))
1702                 goto out;
1703
1704         dm_task_no_open_count(dmt);
1705
1706         if (!libmp_dm_task_run(dmt)) {
1707                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
1708                 goto out;
1709         }
1710         if (!(reload_dmt = libmp_dm_task_create(DM_DEVICE_RELOAD)))
1711                 goto out;
1712         if (!dm_task_set_name(reload_dmt, name))
1713                 goto out_reload;
1714
1715         do {
1716                 next = dm_get_next_target(dmt, next, &start, &length,
1717                                           &target, &params);
1718                 buff = strdup(params);
1719                 if (!buff) {
1720                         condlog(3, "%s: failed to replace target %s, "
1721                                 "out of memory", name, target);
1722                         goto out_reload;
1723                 }
1724                 if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
1725                         condlog(3, "%s: replace target %s %s",
1726                                 name, target, buff);
1727                         dm_reassign_deps(buff, old, new);
1728                         condlog(3, "%s: with target %s %s",
1729                                 name, target, buff);
1730                         modified++;
1731                 }
1732                 dm_task_add_target(reload_dmt, start, length, target, buff);
1733                 free(buff);
1734         } while (next);
1735
1736         if (modified) {
1737                 dm_task_no_open_count(reload_dmt);
1738
1739                 if (!libmp_dm_task_run(reload_dmt)) {
1740                         dm_log_error(3, DM_DEVICE_RELOAD, reload_dmt);
1741                         condlog(3, "%s: failed to reassign targets", name);
1742                         goto out_reload;
1743                 }
1744                 dm_simplecmd_noflush(DM_DEVICE_RESUME, name,
1745                                      MPATH_UDEV_RELOAD_FLAG);
1746         }
1747         r = 1;
1748
1749 out_reload:
1750         dm_task_destroy(reload_dmt);
1751 out:
1752         dm_task_destroy(dmt);
1753         return r;
1754 }
1755
1756
1757 /*
1758  * Reassign existing device-mapper table(s) to not use
1759  * the block devices but point to the multipathed
1760  * device instead
1761  */
1762 int dm_reassign(const char *mapname)
1763 {
1764         struct dm_deps *deps;
1765         struct dm_task *dmt;
1766         struct dm_info info;
1767         char dev_t[32], dm_dep[32];
1768         int r = 0;
1769         unsigned int i;
1770
1771         if (dm_dev_t(mapname, &dev_t[0], 32)) {
1772                 condlog(3, "%s: failed to get device number", mapname);
1773                 return 1;
1774         }
1775
1776         if (!(dmt = libmp_dm_task_create(DM_DEVICE_DEPS))) {
1777                 condlog(3, "%s: couldn't make dm task", mapname);
1778                 return 0;
1779         }
1780
1781         if (!dm_task_set_name(dmt, mapname))
1782                 goto out;
1783
1784         dm_task_no_open_count(dmt);
1785
1786         if (!libmp_dm_task_run(dmt)) {
1787                 dm_log_error(3, DM_DEVICE_DEPS, dmt);
1788                 goto out;
1789         }
1790
1791         if (!dm_task_get_info(dmt, &info))
1792                 goto out;
1793
1794         if (!(deps = dm_task_get_deps(dmt)))
1795                 goto out;
1796
1797         if (!info.exists)
1798                 goto out;
1799
1800         for (i = 0; i < deps->count; i++) {
1801                 sprintf(dm_dep, "%d:%d",
1802                         major(deps->device[i]),
1803                         minor(deps->device[i]));
1804                 sysfs_check_holders(dm_dep, dev_t);
1805         }
1806
1807         r = 1;
1808 out:
1809         dm_task_destroy (dmt);
1810         return r;
1811 }
1812
1813 int dm_setgeometry(struct multipath *mpp)
1814 {
1815         struct dm_task *dmt;
1816         struct path *pp;
1817         char heads[4], sectors[4];
1818         char cylinders[10], start[32];
1819         int r = 0;
1820
1821         if (!mpp)
1822                 return 1;
1823
1824         pp = first_path(mpp);
1825         if (!pp) {
1826                 condlog(3, "%s: no path for geometry", mpp->alias);
1827                 return 1;
1828         }
1829         if (pp->geom.cylinders == 0 ||
1830             pp->geom.heads == 0 ||
1831             pp->geom.sectors == 0) {
1832                 condlog(3, "%s: invalid geometry on %s", mpp->alias, pp->dev);
1833                 return 1;
1834         }
1835
1836         if (!(dmt = libmp_dm_task_create(DM_DEVICE_SET_GEOMETRY)))
1837                 return 0;
1838
1839         if (!dm_task_set_name(dmt, mpp->alias))
1840                 goto out;
1841
1842         dm_task_no_open_count(dmt);
1843
1844         /* What a sick interface ... */
1845         snprintf(heads, 4, "%u", pp->geom.heads);
1846         snprintf(sectors, 4, "%u", pp->geom.sectors);
1847         snprintf(cylinders, 10, "%u", pp->geom.cylinders);
1848         snprintf(start, 32, "%lu", pp->geom.start);
1849         if (!dm_task_set_geometry(dmt, cylinders, heads, sectors, start)) {
1850                 condlog(3, "%s: Failed to set geometry", mpp->alias);
1851                 goto out;
1852         }
1853
1854         r = libmp_dm_task_run(dmt);
1855         if (!r)
1856                 dm_log_error(3, DM_DEVICE_SET_GEOMETRY, dmt);
1857 out:
1858         dm_task_destroy(dmt);
1859
1860         return r;
1861 }