4 #include <libdevmapper.h>
6 #include <linux/kdev_t.h>
13 #include "devmapper.h"
16 #define LOOPS_PER_SEC 5
19 dm_prereq (char * str, int x, int y, int z)
23 struct dm_versions *target;
24 struct dm_versions *last_target;
26 if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
29 dm_task_no_open_count(dmt);
31 if (!dm_task_run(dmt)) {
32 condlog(0, "Can not communicate with kernel DM");
36 target = dm_task_get_versions(dmt);
41 if (!strncmp(str, target->name, strlen(str))) {
44 if (target->version[0] >= x &&
45 target->version[1] >= y &&
46 target->version[2] >= z)
52 target = (void *) target + target->next;
53 } while (last_target != target);
56 condlog(0, "DM multipath kernel driver not loaded");
58 condlog(0, "DM multipath kernel driver version too old");
66 dm_simplecmd (int task, const char *name) {
70 if (!(dmt = dm_task_create (task)))
73 if (!dm_task_set_name (dmt, name))
76 dm_task_no_open_count(dmt);
78 r = dm_task_run (dmt);
81 dm_task_destroy (dmt);
86 dm_addmap (int task, const char *name, const char *target,
87 const char *params, unsigned long long size) {
91 if (!(dmt = dm_task_create (task)))
94 if (!dm_task_set_name (dmt, name))
97 if (!dm_task_add_target (dmt, 0, size, target, params))
100 dm_task_no_open_count(dmt);
102 r = dm_task_run (dmt);
105 dm_task_destroy (dmt);
110 dm_map_present (char * str)
116 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
119 if (!dm_task_set_name(dmt, str))
122 dm_task_no_open_count(dmt);
124 if (!dm_task_run(dmt))
127 if (!dm_task_get_info(dmt, &info))
133 dm_task_destroy(dmt);
138 dm_get_map(char * name, unsigned long long * size, char * outparams)
143 uint64_t start, length;
144 char *target_type = NULL;
147 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
150 if (!dm_task_set_name(dmt, name))
153 dm_task_no_open_count(dmt);
155 if (!dm_task_run(dmt))
158 /* Fetch 1st target */
159 next = dm_get_next_target(dmt, next, &start, &length,
160 &target_type, ¶ms);
165 if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
168 dm_task_destroy(dmt);
173 dm_get_status(char * name, char * outstatus)
178 uint64_t start, length;
182 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
185 if (!dm_task_set_name(dmt, name))
188 dm_task_no_open_count(dmt);
190 if (!dm_task_run(dmt))
193 /* Fetch 1st target */
194 next = dm_get_next_target(dmt, next, &start, &length,
195 &target_type, &status);
197 if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
201 condlog(0, "%s: error getting map status string", name);
203 dm_task_destroy(dmt);
208 dm_type(char * name, char * type)
213 uint64_t start, length;
214 char *target_type = NULL;
217 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
220 if (!dm_task_set_name(dmt, name))
223 dm_task_no_open_count(dmt);
225 if (!dm_task_run(dmt))
228 /* Fetch 1st target */
229 next = dm_get_next_target(dmt, next, &start, &length,
230 &target_type, ¶ms);
232 if (0 == strcmp(target_type, type))
236 dm_task_destroy(dmt);
241 dm_dev_t (char * mapname, char * dev_t, int len)
247 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
250 if (!dm_task_set_name(dmt, mapname))
253 if (!dm_task_run(dmt))
256 if (!dm_task_get_info(dmt, &info))
260 if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
265 dm_task_destroy(dmt);
270 dm_get_opencount (char * mapname)
276 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
279 if (!dm_task_set_name(dmt, mapname))
282 if (!dm_task_run(dmt))
285 if (!dm_task_get_info(dmt, &info))
290 dm_task_destroy(dmt);
295 dm_get_minor (char * mapname)
301 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
304 if (!dm_task_set_name(dmt, mapname))
307 if (!dm_task_run(dmt))
310 if (!dm_task_get_info(dmt, &info))
315 dm_task_destroy(dmt);
320 dm_flush_map (char * mapname, char * type)
324 if (!dm_map_present(mapname))
327 if (!dm_type(mapname, type))
330 if (dm_remove_partmaps(mapname))
333 if (dm_get_opencount(mapname))
336 r = dm_simplecmd(DM_DEVICE_REMOVE, mapname);
339 condlog(4, "multipath map %s removed", mapname);
346 dm_flush_maps (char * type)
350 struct dm_names *names;
353 if (!(dmt = dm_task_create (DM_DEVICE_LIST)))
356 dm_task_no_open_count(dmt);
358 if (!dm_task_run (dmt))
361 if (!(names = dm_task_get_names (dmt)))
368 r += dm_flush_map(names->name, type);
370 names = (void *) names + next;
374 dm_task_destroy (dmt);
379 dm_fail_path(char * mapname, char * path)
385 if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
388 if (!dm_task_set_name(dmt, mapname))
391 if (!dm_task_set_sector(dmt, 0))
394 if (snprintf(str, 32, "fail_path %s\n", path) > 32)
397 if (!dm_task_set_message(dmt, str))
400 dm_task_no_open_count(dmt);
402 if (!dm_task_run(dmt))
407 dm_task_destroy(dmt);
412 dm_reinstate(char * mapname, char * path)
418 if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
421 if (!dm_task_set_name(dmt, mapname))
424 if (!dm_task_set_sector(dmt, 0))
427 if (snprintf(str, 32, "reinstate_path %s\n", path) > 32)
430 if (!dm_task_set_message(dmt, str))
433 dm_task_no_open_count(dmt);
435 if (!dm_task_run(dmt))
440 dm_task_destroy(dmt);
445 dm_groupmsg (char * msg, char * mapname, int index)
451 if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
454 if (!dm_task_set_name(dmt, mapname))
457 if (!dm_task_set_sector(dmt, 0))
460 snprintf(str, 24, "%s_group %i\n", msg, index);
462 if (!dm_task_set_message(dmt, str))
465 dm_task_no_open_count(dmt);
467 if (!dm_task_run(dmt))
470 condlog(3, "message %s 0 %s", mapname, str);
475 condlog(3, "message %s 0 %s failed", mapname, str);
477 dm_task_destroy(dmt);
483 dm_switchgroup(char * mapname, int index)
485 return dm_groupmsg("switch", mapname,index);
489 dm_enablegroup(char * mapname, int index)
491 return dm_groupmsg("enable", mapname,index);
495 dm_disablegroup(char * mapname, int index)
497 return dm_groupmsg("disable", mapname,index);
501 dm_get_maps (vector mp, char * type)
503 struct multipath * mpp;
506 struct dm_names *names;
512 if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
515 dm_task_no_open_count(dmt);
517 if (!dm_task_run(dmt))
520 if (!(names = dm_task_get_names(dmt)))
524 r = 0; /* this is perfectly valid */
529 if (dm_type(names->name, type)) {
530 mpp = alloc_multipath();
535 if (dm_get_map(names->name, &mpp->size, mpp->params))
538 if (dm_get_status(names->name, mpp->status))
541 mpp->alias = MALLOC(strlen(names->name) + 1);
546 strncat(mpp->alias, names->name, strlen(names->name));
548 if (!vector_alloc_slot(mp))
551 vector_set_slot(mp, mpp);
555 names = (void *) names + next;
561 free_multipath(mpp, KEEP_PATHS);
563 dm_task_destroy (dmt);
568 dm_geteventnr (char *name)
573 if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
576 if (!dm_task_set_name(dmt, name))
579 dm_task_no_open_count(dmt);
581 if (!dm_task_run(dmt))
584 if (!dm_task_get_info(dmt, &info)) {
595 dm_task_destroy(dmt);
597 return info.event_nr;
601 dm_mapname(int major, int minor)
606 int loop = MAX_WAIT * LOOPS_PER_SEC;
608 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
611 if (!dm_task_set_major(dmt, major) ||
612 !dm_task_set_minor(dmt, minor))
615 dm_task_no_open_count(dmt);
618 * device map might not be ready when we get here from
622 r = dm_task_run(dmt);
627 usleep(1000 * 1000 / LOOPS_PER_SEC);
631 condlog(0, "%i:%i: timeout fetching map name", major, minor);
635 response = STRDUP((char *)dm_task_get_name(dmt));
636 dm_task_destroy(dmt);
639 dm_task_destroy(dmt);
640 condlog(0, "%i:%i: error fetching map name", major, minor);
645 dm_remove_partmaps (char * mapname)
648 struct dm_names *names;
650 char params[PARAMS_SIZE];
651 unsigned long long size;
655 if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
658 dm_task_no_open_count(dmt);
660 if (!dm_task_run(dmt))
663 if (!(names = dm_task_get_names(dmt)))
667 r = 0; /* this is perfectly valid */
671 if (dm_dev_t(mapname, &dev_t[0], 32))
677 * if devmap target is "linear"
679 dm_type(names->name, "linear") &&
682 * and the multipath mapname and the part mapname start
685 !strncmp(names->name, mapname, strlen(mapname)) &&
688 * and the opencount is 0 for us to allow removal
690 !dm_get_opencount(names->name) &&
693 * and we can fetch the map table from the kernel
695 !dm_get_map(names->name, &size, ¶ms[0]) &&
698 * and the table maps over the multipath map
700 strstr(params, dev_t)
703 * then it's a kpartx generated partition.
706 condlog(4, "partition map %s removed",
708 dm_simplecmd(DM_DEVICE_REMOVE, names->name);
712 names = (void *) names + next;
717 dm_task_destroy (dmt);
723 dm_rename (char * old, char * new)
728 if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
731 if (!dm_task_set_name(dmt, old))
734 if (!dm_task_set_newname(dmt, new))
737 dm_task_no_open_count(dmt);
739 if (!dm_task_run(dmt))
744 dm_task_destroy(dmt);