Fix error
[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 = mpp->force_readonly ? 1 : 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 || !params)
686                 /* more than one target or not found 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         struct dm_info info;
710         int r = 1;
711
712         dmt = libmp_dm_task_create(DM_DEVICE_INFO);
713         if (!dmt)
714                 return 1;
715
716         if (uuid_len > 0)
717                 uuid[0] = '\0';
718
719         if (!dm_task_set_name (dmt, name))
720                 goto uuidout;
721
722         if (!libmp_dm_task_run(dmt)) {
723                 dm_log_error(3, DM_DEVICE_INFO, dmt);
724                 goto uuidout;
725         }
726
727         if (!dm_task_get_info(dmt, &info) ||
728             !info.exists)
729                 goto uuidout;
730
731         uuidtmp = dm_task_get_uuid(dmt);
732         if (uuidtmp)
733                 strlcpy(uuid, uuidtmp, uuid_len);
734
735         r = 0;
736 uuidout:
737         dm_task_destroy(dmt);
738         return r;
739 }
740
741 int dm_get_uuid(const char *name, char *uuid, int uuid_len)
742 {
743         char tmp[DM_UUID_LEN];
744
745         if (dm_get_prefixed_uuid(name, tmp, sizeof(tmp)))
746                 return 1;
747
748         if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
749                 strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
750         else
751                 uuid[0] = '\0';
752
753         return 0;
754 }
755
756 static int
757 is_mpath_part(const char *part_name, const char *map_name)
758 {
759         char *p;
760         char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
761
762         if (dm_get_prefixed_uuid(part_name, part_uuid, sizeof(part_uuid)))
763                 return 0;
764
765         if (dm_get_prefixed_uuid(map_name, map_uuid, sizeof(map_uuid)))
766                 return 0;
767
768         if (strncmp(part_uuid, "part", 4) != 0)
769                 return 0;
770
771         p = strstr(part_uuid, UUID_PREFIX);
772         if (p && !strcmp(p, map_uuid))
773                 return 1;
774
775         return 0;
776 }
777
778 int dm_get_status(const char *name, char **outstatus)
779 {
780         int r = DMP_ERR;
781         struct dm_task *dmt;
782         uint64_t start, length;
783         char *target_type = NULL;
784         char *status = NULL;
785
786         if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
787                 return r;
788
789         if (!dm_task_set_name(dmt, name))
790                 goto out;
791
792         dm_task_no_open_count(dmt);
793
794         errno = 0;
795         if (!libmp_dm_task_run(dmt)) {
796                 dm_log_error(3, DM_DEVICE_STATUS, dmt);
797                 if (dm_task_get_errno(dmt) == ENXIO)
798                         r = DMP_NOT_FOUND;
799                 goto out;
800         }
801
802         r = DMP_NOT_FOUND;
803         /* Fetch 1st target */
804         if (dm_get_next_target(dmt, NULL, &start, &length,
805                                &target_type, &status) != NULL)
806                 goto out;
807
808         if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
809                 goto out;
810
811         if (!status) {
812                 condlog(2, "get null status.");
813                 goto out;
814         }
815
816         if (!outstatus)
817                 r = DMP_OK;
818         else {
819                 *outstatus = strdup(status);
820                 r = *outstatus ? DMP_OK : DMP_ERR;
821         }
822 out:
823         if (r != DMP_OK)
824                 condlog(0, "%s: error getting map status string", name);
825
826         dm_task_destroy(dmt);
827         return r;
828 }
829
830 /*
831  * returns:
832  *    1 : match
833  *    0 : no match
834  *   -1 : empty map, or more than 1 target
835  */
836 int dm_type(const char *name, char *type)
837 {
838         int r = 0;
839         struct dm_task *dmt;
840         uint64_t start, length;
841         char *target_type = NULL;
842         char *params;
843
844         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
845                 return 0;
846
847         if (!dm_task_set_name(dmt, name))
848                 goto out;
849
850         dm_task_no_open_count(dmt);
851
852         if (!libmp_dm_task_run(dmt)) {
853                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
854                 goto out;
855         }
856
857         /* Fetch 1st target */
858         if (dm_get_next_target(dmt, NULL, &start, &length,
859                                &target_type, &params) != NULL)
860                 /* multiple targets */
861                 r = -1;
862         else if (!target_type)
863                 r = -1;
864         else if (!strcmp(target_type, type))
865                 r = 1;
866
867 out:
868         dm_task_destroy(dmt);
869         return r;
870 }
871
872 /*
873  * returns:
874  * 1  : is multipath device
875  * 0  : is not multipath device
876  * -1 : error
877  */
878 int dm_is_mpath(const char *name)
879 {
880         int r = -1;
881         struct dm_task *dmt;
882         struct dm_info info;
883         uint64_t start, length;
884         char *target_type = NULL;
885         char *params;
886         const char *uuid;
887
888         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
889                 goto out;
890
891         if (!dm_task_set_name(dmt, name))
892                 goto out_task;
893
894         dm_task_no_open_count(dmt);
895
896         if (!libmp_dm_task_run(dmt)) {
897                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
898                 goto out_task;
899         }
900
901         if (!dm_task_get_info(dmt, &info))
902                 goto out_task;
903
904         r = 0;
905
906         if (!info.exists)
907                 goto out_task;
908
909         uuid = dm_task_get_uuid(dmt);
910
911         if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
912                 goto out_task;
913
914         /* Fetch 1st target */
915         if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
916                                &params) != NULL)
917                 /* multiple targets */
918                 goto out_task;
919
920         if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
921                 goto out_task;
922
923         r = 1;
924 out_task:
925         dm_task_destroy(dmt);
926 out:
927         if (r < 0)
928                 condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
929         return r;
930 }
931
932 /*
933  * Return
934  *   1 : map with uuid exists
935  *   0 : map with uuid doesn't exist
936  *  -1 : error
937  */
938 int
939 dm_map_present_by_uuid(const char *uuid)
940 {
941         struct dm_task *dmt;
942         struct dm_info info;
943         char prefixed_uuid[WWID_SIZE + UUID_PREFIX_LEN];
944         int r = -1;
945
946         if (!uuid || uuid[0] == '\0')
947                 return 0;
948
949         if (safe_sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid))
950                 goto out;
951
952         if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
953                 goto out;
954
955         dm_task_no_open_count(dmt);
956
957         if (!dm_task_set_uuid(dmt, prefixed_uuid))
958                 goto out_task;
959
960         if (!libmp_dm_task_run(dmt)) {
961                 dm_log_error(3, DM_DEVICE_INFO, dmt);
962                 goto out_task;
963         }
964
965         if (!dm_task_get_info(dmt, &info))
966                 goto out_task;
967
968         r = !!info.exists;
969
970 out_task:
971         dm_task_destroy(dmt);
972 out:
973         if (r < 0)
974                 condlog(3, "%s: dm command failed in %s: %s", uuid,
975                         __FUNCTION__, strerror(errno));
976         return r;
977 }
978
979 static int
980 dm_dev_t (const char * mapname, char * dev_t, int len)
981 {
982         struct dm_info info;
983
984         if (dm_get_info(mapname, &info) != 0)
985                 return 1;
986
987         if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
988                 return 1;
989
990         return 0;
991 }
992
993 int
994 dm_get_opencount (const char * mapname)
995 {
996         int r = -1;
997         struct dm_task *dmt;
998         struct dm_info info;
999
1000         if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
1001                 return 0;
1002
1003         if (!dm_task_set_name(dmt, mapname))
1004                 goto out;
1005
1006         if (!libmp_dm_task_run(dmt)) {
1007                 dm_log_error(3, DM_DEVICE_INFO, dmt);
1008                 goto out;
1009         }
1010
1011         if (!dm_task_get_info(dmt, &info))
1012                 goto out;
1013
1014         if (!info.exists)
1015                 goto out;
1016
1017         r = info.open_count;
1018 out:
1019         dm_task_destroy(dmt);
1020         return r;
1021 }
1022
1023 int
1024 dm_get_major_minor(const char *name, int *major, int *minor)
1025 {
1026         struct dm_info info;
1027
1028         if (dm_get_info(name, &info) != 0)
1029                 return -1;
1030
1031         *major = info.major;
1032         *minor = info.minor;
1033         return 0;
1034 }
1035
1036 static int
1037 has_partmap(const char *name __attribute__((unused)),
1038             void *data __attribute__((unused)))
1039 {
1040         return 1;
1041 }
1042
1043 static int
1044 partmap_in_use(const char *name, void *data)
1045 {
1046         int part_count, *ret_count = (int *)data;
1047         int open_count = dm_get_opencount(name);
1048
1049         if (ret_count)
1050                 (*ret_count)++;
1051         part_count = 0;
1052         if (open_count) {
1053                 if (do_foreach_partmaps(name, partmap_in_use, &part_count))
1054                         return 1;
1055                 if (open_count != part_count) {
1056                         condlog(2, "%s: map in use", name);
1057                         return 1;
1058                 }
1059         }
1060         return 0;
1061 }
1062
1063 int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
1064                    int need_suspend, int retries)
1065 {
1066         int r;
1067         int queue_if_no_path = 0;
1068         int udev_flags = 0;
1069         unsigned long long mapsize;
1070         char *params = NULL;
1071
1072         if (dm_is_mpath(mapname) != 1)
1073                 return 0; /* nothing to do */
1074
1075         /* if the device currently has no partitions, do not
1076            run kpartx on it if you fail to delete it */
1077         if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0)
1078                 udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG;
1079
1080         /* If you aren't doing a deferred remove, make sure that no
1081          * devices are in use */
1082         if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL))
1083                         return 1;
1084
1085         if (need_suspend &&
1086             dm_get_map(mapname, &mapsize, &params) == DMP_OK &&
1087             strstr(params, "queue_if_no_path")) {
1088                 if (!dm_queue_if_no_path(mapname, 0))
1089                         queue_if_no_path = 1;
1090                 else
1091                         /* Leave queue_if_no_path alone if unset failed */
1092                         queue_if_no_path = -1;
1093         }
1094         free(params);
1095         params = NULL;
1096
1097         if (dm_remove_partmaps(mapname, need_sync, deferred_remove))
1098                 return 1;
1099
1100         if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) {
1101                 condlog(2, "%s: map in use", mapname);
1102                 return 1;
1103         }
1104
1105         do {
1106                 if (need_suspend && queue_if_no_path != -1)
1107                         dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0);
1108
1109                 r = dm_device_remove(mapname, need_sync, deferred_remove);
1110
1111                 if (r) {
1112                         if (do_deferred(deferred_remove)
1113                             && dm_map_present(mapname)) {
1114                                 condlog(4, "multipath map %s remove deferred",
1115                                         mapname);
1116                                 return 2;
1117                         }
1118                         condlog(4, "multipath map %s removed", mapname);
1119                         return 0;
1120                 } else if (dm_is_mpath(mapname) != 1) {
1121                         condlog(4, "multipath map %s removed externally",
1122                                 mapname);
1123                         return 0; /*we raced with someone else removing it */
1124                 } else {
1125                         condlog(2, "failed to remove multipath map %s",
1126                                 mapname);
1127                         if (need_suspend && queue_if_no_path != -1) {
1128                                 dm_simplecmd_noflush(DM_DEVICE_RESUME,
1129                                                      mapname, udev_flags);
1130                         }
1131                 }
1132                 if (retries)
1133                         sleep(1);
1134         } while (retries-- > 0);
1135
1136         if (queue_if_no_path == 1)
1137                 dm_queue_if_no_path(mapname, 1);
1138
1139         return 1;
1140 }
1141
1142 #ifdef LIBDM_API_DEFERRED
1143
1144 int
1145 dm_flush_map_nopaths(const char * mapname, int deferred_remove)
1146 {
1147         return _dm_flush_map(mapname, 1, deferred_remove, 0, 0);
1148 }
1149
1150 #else
1151
1152 int
1153 dm_flush_map_nopaths(const char * mapname,
1154                      int deferred_remove __attribute__((unused)))
1155 {
1156         return _dm_flush_map(mapname, 1, 0, 0, 0);
1157 }
1158
1159 #endif
1160
1161 int dm_flush_maps (int need_suspend, int retries)
1162 {
1163         int r = 1;
1164         struct dm_task *dmt;
1165         struct dm_names *names;
1166         unsigned next = 0;
1167
1168         if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))
1169                 return r;
1170
1171         dm_task_no_open_count(dmt);
1172
1173         if (!libmp_dm_task_run (dmt)) {
1174                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1175                 goto out;
1176         }
1177
1178         if (!(names = dm_task_get_names (dmt)))
1179                 goto out;
1180
1181         r = 0;
1182         if (!names->dev)
1183                 goto out;
1184
1185         do {
1186                 if (need_suspend)
1187                         r |= dm_suspend_and_flush_map(names->name, retries);
1188                 else
1189                         r |= dm_flush_map(names->name);
1190                 next = names->next;
1191                 names = (void *) names + next;
1192         } while (next);
1193
1194 out:
1195         dm_task_destroy (dmt);
1196         return r;
1197 }
1198
1199 int
1200 dm_message(const char * mapname, char * message)
1201 {
1202         int r = 1;
1203         struct dm_task *dmt;
1204
1205         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TARGET_MSG)))
1206                 return 1;
1207
1208         if (!dm_task_set_name(dmt, mapname))
1209                 goto out;
1210
1211         if (!dm_task_set_sector(dmt, 0))
1212                 goto out;
1213
1214         if (!dm_task_set_message(dmt, message))
1215                 goto out;
1216
1217         dm_task_no_open_count(dmt);
1218
1219         if (!libmp_dm_task_run(dmt)) {
1220                 dm_log_error(2, DM_DEVICE_TARGET_MSG, dmt);
1221                 goto out;
1222         }
1223
1224         r = 0;
1225 out:
1226         if (r)
1227                 condlog(0, "DM message failed [%s]", message);
1228
1229         dm_task_destroy(dmt);
1230         return r;
1231 }
1232
1233 int
1234 dm_fail_path(const char * mapname, char * path)
1235 {
1236         char message[32];
1237
1238         if (snprintf(message, 32, "fail_path %s", path) > 32)
1239                 return 1;
1240
1241         return dm_message(mapname, message);
1242 }
1243
1244 int
1245 dm_reinstate_path(const char * mapname, char * path)
1246 {
1247         char message[32];
1248
1249         if (snprintf(message, 32, "reinstate_path %s", path) > 32)
1250                 return 1;
1251
1252         return dm_message(mapname, message);
1253 }
1254
1255 int
1256 dm_queue_if_no_path(const char *mapname, int enable)
1257 {
1258         char *message;
1259
1260         if (enable)
1261                 message = "queue_if_no_path";
1262         else
1263                 message = "fail_if_no_path";
1264
1265         return dm_message(mapname, message);
1266 }
1267
1268 static int
1269 dm_groupmsg (const char * msg, const char * mapname, int index)
1270 {
1271         char message[32];
1272
1273         if (snprintf(message, 32, "%s_group %i", msg, index) > 32)
1274                 return 1;
1275
1276         return dm_message(mapname, message);
1277 }
1278
1279 int
1280 dm_switchgroup(const char * mapname, int index)
1281 {
1282         return dm_groupmsg("switch", mapname, index);
1283 }
1284
1285 int
1286 dm_enablegroup(const char * mapname, int index)
1287 {
1288         return dm_groupmsg("enable", mapname, index);
1289 }
1290
1291 int
1292 dm_disablegroup(const char * mapname, int index)
1293 {
1294         return dm_groupmsg("disable", mapname, index);
1295 }
1296
1297 struct multipath *dm_get_multipath(const char *name)
1298 {
1299         struct multipath *mpp = NULL;
1300
1301         mpp = alloc_multipath();
1302         if (!mpp)
1303                 return NULL;
1304
1305         mpp->alias = strdup(name);
1306
1307         if (!mpp->alias)
1308                 goto out;
1309
1310         if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
1311                 goto out;
1312
1313         if (dm_get_uuid(name, mpp->wwid, WWID_SIZE) != 0)
1314                 condlog(2, "%s: failed to get uuid for %s", __func__, name);
1315         if (dm_get_info(name, &mpp->dmi) != 0)
1316                 condlog(2, "%s: failed to get info for %s", __func__, name);
1317
1318         return mpp;
1319 out:
1320         free_multipath(mpp, KEEP_PATHS);
1321         return NULL;
1322 }
1323
1324 int
1325 dm_get_maps (vector mp)
1326 {
1327         struct multipath * mpp;
1328         int r = 1;
1329         struct dm_task *dmt;
1330         struct dm_names *names;
1331         unsigned next = 0;
1332
1333         if (!mp)
1334                 return 1;
1335
1336         if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
1337                 return 1;
1338
1339         dm_task_no_open_count(dmt);
1340
1341         if (!libmp_dm_task_run(dmt)) {
1342                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1343                 goto out;
1344         }
1345
1346         if (!(names = dm_task_get_names(dmt)))
1347                 goto out;
1348
1349         if (!names->dev) {
1350                 r = 0; /* this is perfectly valid */
1351                 goto out;
1352         }
1353
1354         do {
1355                 if (dm_is_mpath(names->name) != 1)
1356                         goto next;
1357
1358                 mpp = dm_get_multipath(names->name);
1359                 if (!mpp)
1360                         goto out;
1361
1362                 if (!vector_alloc_slot(mp)) {
1363                         free_multipath(mpp, KEEP_PATHS);
1364                         goto out;
1365                 }
1366
1367                 vector_set_slot(mp, mpp);
1368 next:
1369                 next = names->next;
1370                 names = (void *) names + next;
1371         } while (next);
1372
1373         r = 0;
1374         goto out;
1375 out:
1376         dm_task_destroy (dmt);
1377         return r;
1378 }
1379
1380 int
1381 dm_geteventnr (const char *name)
1382 {
1383         struct dm_info info;
1384
1385         if (dm_get_info(name, &info) != 0)
1386                 return -1;
1387
1388         return info.event_nr;
1389 }
1390
1391 int
1392 dm_is_suspended(const char *name)
1393 {
1394         struct dm_info info;
1395
1396         if (dm_get_info(name, &info) != 0)
1397                 return -1;
1398
1399         return info.suspended;
1400 }
1401
1402 char *
1403 dm_mapname(int major, int minor)
1404 {
1405         char * response = NULL;
1406         const char *map;
1407         struct dm_task *dmt;
1408         int r;
1409
1410         if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
1411                 return NULL;
1412
1413         if (!dm_task_set_major(dmt, major) ||
1414             !dm_task_set_minor(dmt, minor))
1415                 goto bad;
1416
1417         dm_task_no_open_count(dmt);
1418         r = libmp_dm_task_run(dmt);
1419         if (!r) {
1420                 dm_log_error(2, DM_DEVICE_STATUS, dmt);
1421                 goto bad;
1422         }
1423
1424         map = dm_task_get_name(dmt);
1425         if (map && strlen(map))
1426                 response = strdup((const char *)map);
1427
1428         dm_task_destroy(dmt);
1429         return response;
1430 bad:
1431         dm_task_destroy(dmt);
1432         condlog(0, "%i:%i: error fetching map name", major, minor);
1433         return NULL;
1434 }
1435
1436 static int
1437 do_foreach_partmaps (const char * mapname,
1438                      int (*partmap_func)(const char *, void *),
1439                      void *data)
1440 {
1441         struct dm_task *dmt;
1442         struct dm_names *names;
1443         unsigned next = 0;
1444         char *params = NULL;
1445         unsigned long long size;
1446         char dev_t[32];
1447         int r = 1;
1448         char *p;
1449
1450         if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
1451                 return 1;
1452
1453         dm_task_no_open_count(dmt);
1454
1455         if (!libmp_dm_task_run(dmt)) {
1456                 dm_log_error(3, DM_DEVICE_LIST, dmt);
1457                 goto out;
1458         }
1459
1460         if (!(names = dm_task_get_names(dmt)))
1461                 goto out;
1462
1463         if (!names->dev) {
1464                 r = 0; /* this is perfectly valid */
1465                 goto out;
1466         }
1467
1468         if (dm_dev_t(mapname, &dev_t[0], 32))
1469                 goto out;
1470
1471         do {
1472                 if (
1473                     /*
1474                      * if there is only a single "linear" target
1475                      */
1476                     (dm_type(names->name, TGT_PART) == 1) &&
1477
1478                     /*
1479                      * and the uuid of the target is a partition of the
1480                      * uuid of the multipath device
1481                      */
1482                     is_mpath_part(names->name, mapname) &&
1483
1484                     /*
1485                      * and we can fetch the map table from the kernel
1486                      */
1487                     dm_get_map(names->name, &size, &params) == DMP_OK &&
1488
1489                     /*
1490                      * and the table maps over the multipath map
1491                      */
1492                     (p = strstr(params, dev_t)) &&
1493                     !isdigit(*(p + strlen(dev_t)))
1494                    ) {
1495                         if (partmap_func(names->name, data) != 0)
1496                                 goto out;
1497                 }
1498
1499                 free(params);
1500                 params = NULL;
1501                 next = names->next;
1502                 names = (void *) names + next;
1503         } while (next);
1504
1505         r = 0;
1506 out:
1507         free(params);
1508         dm_task_destroy (dmt);
1509         return r;
1510 }
1511
1512 struct remove_data {
1513         int need_sync;
1514         int deferred_remove;
1515 };
1516
1517 static int
1518 remove_partmap(const char *name, void *data)
1519 {
1520         struct remove_data *rd = (struct remove_data *)data;
1521
1522         if (dm_get_opencount(name)) {
1523                 dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove);
1524                 if (!do_deferred(rd->deferred_remove) &&
1525                     dm_get_opencount(name)) {
1526                         condlog(2, "%s: map in use", name);
1527                         return 1;
1528                 }
1529         }
1530         condlog(4, "partition map %s removed", name);
1531         dm_device_remove(name, rd->need_sync, rd->deferred_remove);
1532         return 0;
1533 }
1534
1535 int
1536 dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove)
1537 {
1538         struct remove_data rd = { need_sync, deferred_remove };
1539         return do_foreach_partmaps(mapname, remove_partmap, &rd);
1540 }
1541
1542 #ifdef LIBDM_API_DEFERRED
1543
1544 static int
1545 cancel_remove_partmap (const char *name, void *unused __attribute__((unused)))
1546 {
1547         if (dm_get_opencount(name))
1548                 dm_cancel_remove_partmaps(name);
1549         if (dm_message(name, "@cancel_deferred_remove") != 0)
1550                 condlog(0, "%s: can't cancel deferred remove: %s", name,
1551                         strerror(errno));
1552         return 0;
1553 }
1554
1555 static int
1556 dm_get_deferred_remove (const char * mapname)
1557 {
1558         struct dm_info info;
1559
1560         if (dm_get_info(mapname, &info) != 0)
1561                 return -1;
1562
1563         return info.deferred_remove;
1564 }
1565
1566 static int
1567 dm_cancel_remove_partmaps(const char * mapname) {
1568         return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL);
1569 }
1570
1571 int
1572 dm_cancel_deferred_remove (struct multipath *mpp)
1573 {
1574         int r = 0;
1575
1576         if (!dm_get_deferred_remove(mpp->alias))
1577                 return 0;
1578         if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS)
1579                 mpp->deferred_remove = DEFERRED_REMOVE_ON;
1580
1581         dm_cancel_remove_partmaps(mpp->alias);
1582         r = dm_message(mpp->alias, "@cancel_deferred_remove");
1583         if (r)
1584                 condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias,
1585                                 strerror(errno));
1586         else
1587                 condlog(2, "%s: canceled deferred remove", mpp->alias);
1588         return r;
1589 }
1590
1591 #else
1592
1593 int
1594 dm_cancel_deferred_remove (struct multipath *mpp __attribute__((unused)))
1595 {
1596         return 0;
1597 }
1598
1599 #endif
1600
1601 struct rename_data {
1602         const char *old;
1603         char *new;
1604         char *delim;
1605 };
1606
1607 static int
1608 rename_partmap (const char *name, void *data)
1609 {
1610         char *buff = NULL;
1611         int offset;
1612         struct rename_data *rd = (struct rename_data *)data;
1613
1614         if (strncmp(name, rd->old, strlen(rd->old)) != 0)
1615                 return 0;
1616         for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */
1617         if (asprintf(&buff, "%s%s%s", rd->new, rd->delim, name + offset) >= 0) {
1618                 dm_rename(name, buff, rd->delim, SKIP_KPARTX_OFF);
1619                 free(buff);
1620                 condlog(4, "partition map %s renamed", name);
1621         } else
1622                 condlog(1, "failed to rename partition map %s", name);
1623         return 0;
1624 }
1625
1626 int
1627 dm_rename_partmaps (const char * old, char * new, char *delim)
1628 {
1629         struct rename_data rd;
1630
1631         rd.old = old;
1632         rd.new = new;
1633
1634         if (delim)
1635                 rd.delim = delim;
1636         else {
1637                 if (isdigit(new[strlen(new)-1]))
1638                         rd.delim = "p";
1639                 else
1640                         rd.delim = "";
1641         }
1642         return do_foreach_partmaps(old, rename_partmap, &rd);
1643 }
1644
1645 int
1646 dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
1647 {
1648         int r = 0;
1649         struct dm_task *dmt;
1650         uint32_t cookie = 0;
1651         uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
1652
1653         if (dm_rename_partmaps(old, new, delim))
1654                 return r;
1655
1656         if (!(dmt = libmp_dm_task_create(DM_DEVICE_RENAME)))
1657                 return r;
1658
1659         if (!dm_task_set_name(dmt, old))
1660                 goto out;
1661
1662         if (!dm_task_set_newname(dmt, new))
1663                 goto out;
1664
1665         dm_task_no_open_count(dmt);
1666
1667         if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
1668                 goto out;
1669         r = libmp_dm_task_run(dmt);
1670         if (!r)
1671                 dm_log_error(2, DM_DEVICE_RENAME, dmt);
1672
1673         libmp_udev_wait(cookie);
1674
1675 out:
1676         dm_task_destroy(dmt);
1677
1678         return r;
1679 }
1680
1681 void dm_reassign_deps(char *table, const char *dep, const char *newdep)
1682 {
1683         char *n, *newtable;
1684         const char *p;
1685
1686         newtable = strdup(table);
1687         if (!newtable)
1688                 return;
1689         p = strstr(newtable, dep);
1690         n = table + (p - newtable);
1691         strcpy(n, newdep);
1692         n += strlen(newdep);
1693         p += strlen(dep);
1694         strcat(n, p);
1695         free(newtable);
1696 }
1697
1698 int dm_reassign_table(const char *name, char *old, char *new)
1699 {
1700         int r = 0, modified = 0;
1701         uint64_t start, length;
1702         struct dm_task *dmt, *reload_dmt;
1703         char *target, *params = NULL;
1704         char *buff;
1705         void *next = NULL;
1706
1707         if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
1708                 return 0;
1709
1710         if (!dm_task_set_name(dmt, name))
1711                 goto out;
1712
1713         dm_task_no_open_count(dmt);
1714
1715         if (!libmp_dm_task_run(dmt)) {
1716                 dm_log_error(3, DM_DEVICE_TABLE, dmt);
1717                 goto out;
1718         }
1719         if (!(reload_dmt = libmp_dm_task_create(DM_DEVICE_RELOAD)))
1720                 goto out;
1721         if (!dm_task_set_name(reload_dmt, name))
1722                 goto out_reload;
1723
1724         do {
1725                 next = dm_get_next_target(dmt, next, &start, &length,
1726                                           &target, &params);
1727                 if (!target || !params) {
1728                         /*
1729                          * We can't call dm_task_add_target() with
1730                          * invalid parameters. But simply dropping this
1731                          * target feels wrong, too. Abort and warn.
1732                          */
1733                         condlog(1, "%s: invalid target found in map %s",
1734                                 __func__, name);
1735                         goto out_reload;
1736                 }
1737                 buff = strdup(params);
1738                 if (!buff) {
1739                         condlog(3, "%s: failed to replace target %s, "
1740                                 "out of memory", name, target);
1741                         goto out_reload;
1742                 }
1743                 if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
1744                         condlog(3, "%s: replace target %s %s",
1745                                 name, target, buff);
1746                         dm_reassign_deps(buff, old, new);
1747                         condlog(3, "%s: with target %s %s",
1748                                 name, target, buff);
1749                         modified++;
1750                 }
1751                 dm_task_add_target(reload_dmt, start, length, target, buff);
1752                 free(buff);
1753         } while (next);
1754
1755         if (modified) {
1756                 dm_task_no_open_count(reload_dmt);
1757
1758                 if (!libmp_dm_task_run(reload_dmt)) {
1759                         dm_log_error(3, DM_DEVICE_RELOAD, reload_dmt);
1760                         condlog(3, "%s: failed to reassign targets", name);
1761                         goto out_reload;
1762                 }
1763                 dm_simplecmd_noflush(DM_DEVICE_RESUME, name,
1764                                      MPATH_UDEV_RELOAD_FLAG);
1765         }
1766         r = 1;
1767
1768 out_reload:
1769         dm_task_destroy(reload_dmt);
1770 out:
1771         dm_task_destroy(dmt);
1772         return r;
1773 }
1774
1775
1776 /*
1777  * Reassign existing device-mapper table(s) to not use
1778  * the block devices but point to the multipathed
1779  * device instead
1780  */
1781 int dm_reassign(const char *mapname)
1782 {
1783         struct dm_deps *deps;
1784         struct dm_task *dmt;
1785         struct dm_info info;
1786         char dev_t[32], dm_dep[32];
1787         int r = 0;
1788         unsigned int i;
1789
1790         if (dm_dev_t(mapname, &dev_t[0], 32)) {
1791                 condlog(3, "%s: failed to get device number", mapname);
1792                 return 1;
1793         }
1794
1795         if (!(dmt = libmp_dm_task_create(DM_DEVICE_DEPS))) {
1796                 condlog(3, "%s: couldn't make dm task", mapname);
1797                 return 0;
1798         }
1799
1800         if (!dm_task_set_name(dmt, mapname))
1801                 goto out;
1802
1803         dm_task_no_open_count(dmt);
1804
1805         if (!libmp_dm_task_run(dmt)) {
1806                 dm_log_error(3, DM_DEVICE_DEPS, dmt);
1807                 goto out;
1808         }
1809
1810         if (!dm_task_get_info(dmt, &info))
1811                 goto out;
1812
1813         if (!(deps = dm_task_get_deps(dmt)))
1814                 goto out;
1815
1816         if (!info.exists)
1817                 goto out;
1818
1819         for (i = 0; i < deps->count; i++) {
1820                 sprintf(dm_dep, "%d:%d",
1821                         major(deps->device[i]),
1822                         minor(deps->device[i]));
1823                 sysfs_check_holders(dm_dep, dev_t);
1824         }
1825
1826         r = 1;
1827 out:
1828         dm_task_destroy (dmt);
1829         return r;
1830 }
1831
1832 int dm_setgeometry(struct multipath *mpp)
1833 {
1834         struct dm_task *dmt;
1835         struct path *pp;
1836         char heads[4], sectors[4];
1837         char cylinders[10], start[32];
1838         int r = 0;
1839
1840         if (!mpp)
1841                 return 1;
1842
1843         pp = first_path(mpp);
1844         if (!pp) {
1845                 condlog(3, "%s: no path for geometry", mpp->alias);
1846                 return 1;
1847         }
1848         if (pp->geom.cylinders == 0 ||
1849             pp->geom.heads == 0 ||
1850             pp->geom.sectors == 0) {
1851                 condlog(3, "%s: invalid geometry on %s", mpp->alias, pp->dev);
1852                 return 1;
1853         }
1854
1855         if (!(dmt = libmp_dm_task_create(DM_DEVICE_SET_GEOMETRY)))
1856                 return 0;
1857
1858         if (!dm_task_set_name(dmt, mpp->alias))
1859                 goto out;
1860
1861         dm_task_no_open_count(dmt);
1862
1863         /* What a sick interface ... */
1864         snprintf(heads, 4, "%u", pp->geom.heads);
1865         snprintf(sectors, 4, "%u", pp->geom.sectors);
1866         snprintf(cylinders, 10, "%u", pp->geom.cylinders);
1867         snprintf(start, 32, "%lu", pp->geom.start);
1868         if (!dm_task_set_geometry(dmt, cylinders, heads, sectors, start)) {
1869                 condlog(3, "%s: Failed to set geometry", mpp->alias);
1870                 goto out;
1871         }
1872
1873         r = libmp_dm_task_run(dmt);
1874         if (!r)
1875                 dm_log_error(3, DM_DEVICE_SET_GEOMETRY, dmt);
1876 out:
1877         dm_task_destroy(dmt);
1878
1879         return r;
1880 }