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