/* DM helpers */ static int _dm_simple(int task, const char *name, int udev_wait) { int r = 0; struct dm_task *dmt; uint32_t cookie = 0; if (!_dm_use_udev()) udev_wait = 0; if (!(dmt = dm_task_create(task))) return 0; if (name && !dm_task_set_name(dmt, name)) goto out; if (udev_wait && !dm_task_set_cookie(dmt, &cookie, 0)) goto out; r = dm_task_run(dmt); if (udev_wait) (void)dm_udev_wait(cookie); out: dm_task_destroy(dmt); return r; }
static int _dm_simple(int task, int wait, const char *name) { struct dm_task *dmt; uint32_t cookie = 0; int rc; if (!(dmt = dm_task_create(task))) return -1; if (!dm_task_set_name(dmt, name)) goto out; if (wait && !dm_task_set_cookie(dmt, &cookie, 0)) goto out; rc = dm_task_run(dmt); if (wait) (void) dm_udev_wait(cookie); dm_task_destroy(dmt); return rc ? 0 : -1; out: dm_task_destroy(dmt); return -1; }
int dm_addmap(int task, const char *name, const char *target, const char *params, uint64_t size, int ro, const char *uuid, int part, mode_t mode, uid_t uid, gid_t gid) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; #ifdef LIBDM_API_COOKIE uint32_t cookie = 0; uint16_t udev_flags = 0; #endif if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, name)) goto addout; if (!dm_task_add_target (dmt, 0, size, target, params)) goto addout; if (ro && !dm_task_set_ro (dmt)) goto addout; if (task == DM_DEVICE_CREATE && uuid) { prefixed_uuid = make_prefixed_uuid(part, uuid); if (prefixed_uuid == NULL) goto addout; if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto addout; } if (!dm_task_set_mode(dmt, mode)) goto addout; if (!dm_task_set_uid(dmt, uid)) goto addout; if (!dm_task_set_gid(dmt, gid)) goto addout; dm_task_no_open_count(dmt); #ifdef LIBDM_API_COOKIE if (!udev_sync) udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto addout; #endif r = dm_task_run (dmt); #ifdef LIBDM_API_COOKIE if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); #endif addout: dm_task_destroy (dmt); free(prefixed_uuid); return r; }
static int _dm_create(int task, int wait, const char *name, const char *uuid, uint64_t start, uint64_t length, const char *target, const char *table, struct era_dm_info *info) { struct dm_task *dmt; uint32_t cookie = 0; int rc; if (!(dmt = dm_task_create(task))) return -1; if (!dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, uuid)) goto out; if (target && !dm_task_add_target(dmt, start, length, target, table)) goto out; if (wait && !dm_task_set_cookie(dmt, &cookie, 0)) goto out; rc = dm_task_run(dmt); if (wait) (void) dm_udev_wait(cookie); if (rc && info) { struct dm_info dmi; if (!dm_task_get_info(dmt, &dmi)) goto out; info->target_count = dmi.target_count; info->open_count = dmi.open_count; info->suspended = dmi.suspended; info->exists = dmi.exists; info->major = dmi.major; info->minor = dmi.minor; } dm_task_destroy(dmt); return rc ? 0 : -1; out: dm_task_destroy(dmt); return -1; }
int dm_simplecmd(int task, const char *name, int no_flush, uint16_t udev_flags) { int r = 0; int udev_wait_flag = (task == DM_DEVICE_RESUME || task == DM_DEVICE_REMOVE); #ifdef LIBDM_API_COOKIE uint32_t cookie = 0; #endif struct dm_task *dmt; if (!(dmt = dm_task_create(task))) return 0; if (!dm_task_set_name(dmt, name)) goto out; dm_task_no_open_count(dmt); dm_task_skip_lockfs(dmt); if (no_flush) dm_task_no_flush(dmt); #ifdef LIBDM_API_COOKIE if (!udev_sync) udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK; if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out; #endif r = dm_task_run(dmt); #ifdef LIBDM_API_COOKIE if (udev_wait_flag) dm_udev_wait(cookie); #endif out: dm_task_destroy(dmt); return r; }
static int dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { int r = 0; int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || task == DM_DEVICE_REMOVE)); uint32_t cookie = 0; struct dm_task *dmt; if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, name)) goto out; dm_task_no_open_count(dmt); dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */ #ifdef LIBDM_API_FLUSH if (no_flush) dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ #endif #ifdef LIBDM_API_DEFERRED if (do_deferred(deferred_remove)) dm_task_deferred_remove(dmt); #endif if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags)) goto out; r = dm_task_run (dmt); if (udev_wait_flag) dm_udev_wait(cookie); out: dm_task_destroy (dmt); return r; }
static int dm_addmap (int task, const char *target, struct multipath *mpp, char * params, int ro) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; uint32_t cookie = 0; if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, mpp->alias)) goto addout; if (!dm_task_add_target (dmt, 0, mpp->size, target, params)) goto addout; if (ro) dm_task_set_ro(dmt); if (task == DM_DEVICE_CREATE) { if (strlen(mpp->wwid) > 0) { prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1); if (!prefixed_uuid) { condlog(0, "cannot create prefixed uuid : %s", strerror(errno)); goto addout; } sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid); if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto freeout; } dm_task_skip_lockfs(dmt); #ifdef LIBDM_API_FLUSH dm_task_no_flush(dmt); #endif } if (mpp->attribute_flags & (1 << ATTR_MODE) && !dm_task_set_mode(dmt, mpp->mode)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_UID) && !dm_task_set_uid(dmt, mpp->uid)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_GID) && !dm_task_set_gid(dmt, mpp->gid)) goto freeout; condlog(4, "%s: %s [0 %llu %s %s]", mpp->alias, task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size, target, params); dm_task_no_open_count(dmt); if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK)) goto freeout; r = dm_task_run (dmt); if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); freeout: if (prefixed_uuid) FREE(prefixed_uuid); addout: dm_task_destroy (dmt); return r; }
int dm_create_device(const char *name, const char *device, const char *cipher, const char *type, const char *uuid, uint64_t size, uint64_t skip, uint64_t offset, size_t key_size, const char *key, int read_only, int reload) { struct dm_task *dmt = NULL; struct dm_info dmi; char *params = NULL; char *error = NULL; char dev_uuid[DM_UUID_LEN] = {0}; int r = -EINVAL; uint32_t read_ahead = 0; uint32_t cookie = 0; uint16_t udev_flags = 0; params = get_params(device, skip, offset, cipher, key_size, key); if (!params) goto out_no_removal; if (type && !strncmp(type, "TEMP", 4)) udev_flags = CRYPT_TEMP_UDEV_FLAGS; /* All devices must have DM_UUID, only resize on old device is exception */ if (reload) { if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) goto out_no_removal; if (!dm_task_set_name(dmt, name)) goto out_no_removal; } else { dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid)); if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) goto out_no_removal; if (!dm_task_set_name(dmt, name)) goto out_no_removal; if (!dm_task_set_uuid(dmt, dev_uuid)) goto out_no_removal; if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out_no_removal; } if (read_only && !dm_task_set_ro(dmt)) goto out_no_removal; if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params)) goto out_no_removal; #ifdef DM_READ_AHEAD_MINIMUM_FLAG if (_dev_read_ahead(device, &read_ahead) && !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG)) goto out_no_removal; #endif if (!dm_task_run(dmt)) goto out_no_removal; if (reload) { dm_task_destroy(dmt); if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) goto out; if (!dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, dev_uuid)) goto out; if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out; if (!dm_task_run(dmt)) goto out; } if (!dm_task_get_info(dmt, &dmi)) goto out; r = 0; out: if (_dm_use_udev()) { (void)dm_udev_wait(cookie); cookie = 0; } if (r < 0 && !reload) { if (get_error()) error = strdup(get_error()); dm_remove_device(name, 0, 0); if (error) { set_error(error); free(error); } } out_no_removal: if (cookie && _dm_use_udev()) (void)dm_udev_wait(cookie); if (params) safe_free(params); if (dmt) dm_task_destroy(dmt); dm_task_update_nodes(); return r; }
int main(int argc, char **argv){ int fd, i, j, m, n, op, off, arg, c, d; struct slice all; struct pt *ptp; enum action what = LIST; char *type, *diskdevice, *device, *progname; int verbose = 0; char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16]; char * loopdev = NULL; char * delim = NULL; char *uuid = NULL; char *mapname = NULL; int loopro = 0; int hotplug = 0; int loopcreated = 0; int sync = 0; struct stat buf; uint32_t cookie = 0; initpts(); init_crc32(); type = device = diskdevice = NULL; memset(&all, 0, sizeof(all)); memset(&partname, 0, sizeof(partname)); /* Check whether hotplug mode. */ progname = strrchr(argv[0], '/'); if (!progname) progname = argv[0]; else progname++; if (!strcmp(progname, "kpartx.dev")) { /* Hotplug mode */ hotplug = 1; /* Setup for original kpartx variables */ if (!(device = get_hotplug_device())) exit(1); diskdevice = device; what = ADD; } else if (argc < 2) { usage(); exit(1); } while ((arg = getopt(argc, argv, short_opts)) != EOF) switch(arg) { case 'g': force_gpt=1; break; case 't': type = optarg; break; case 'v': verbose = 1; break; case 'p': delim = optarg; break; case 'l': what = LIST; break; case 'a': what = ADD; break; case 'd': what = DELETE; break; case 's': sync = 1; break; default: usage(); exit(1); } if (!sync) dm_udev_set_sync_support(0); if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) { fprintf(stderr, "device mapper prerequisites not met\n"); exit(1); } if (hotplug) { /* already got [disk]device */ } else if (optind == argc-2) { device = argv[optind]; diskdevice = argv[optind+1]; } else if (optind == argc-1) { diskdevice = device = argv[optind]; } else { usage(); exit(1); } if (stat(device, &buf)) { printf("failed to stat() %s\n", device); exit (1); } if (S_ISREG (buf.st_mode)) { /* already looped file ? */ loopdev = find_loop_by_file(device); if (!loopdev && what == DELETE) exit (0); if (!loopdev) { loopdev = find_unused_loop_device(); if (set_loop(loopdev, device, 0, &loopro)) { fprintf(stderr, "can't set up loop\n"); exit (1); } loopcreated = 1; } device = loopdev; } if (delim == NULL) { delim = malloc(DELIM_SIZE); memset(delim, 0, DELIM_SIZE); set_delimiter(device, delim); } off = find_devname_offset(device); if (!loopdev) { uuid = dm_mapuuid((unsigned int)MAJOR(buf.st_rdev), (unsigned int)MINOR(buf.st_rdev)); mapname = dm_mapname((unsigned int)MAJOR(buf.st_rdev), (unsigned int)MINOR(buf.st_rdev)); } if (!uuid) uuid = device + off; if (!mapname) mapname = device + off; fd = open(device, O_RDONLY); if (fd == -1) { perror(device); exit(1); } /* add/remove partitions to the kernel devmapper tables */ int r = 0; for (i = 0; i < ptct; i++) { ptp = &pts[i]; if (type && strcmp(type, ptp->type)) continue; /* here we get partitions */ n = ptp->fn(fd, all, slices, SIZE(slices)); #ifdef DEBUG if (n >= 0) printf("%s: %d slices\n", ptp->type, n); #endif if (n > 0) close(fd); else continue; switch(what) { case LIST: for (j = 0, c = 0, m = 0; j < n; j++) { if (slices[j].size == 0) continue; if (slices[j].container > 0) { c++; continue; } slices[j].minor = m++; printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", mapname, delim, j+1, slices[j].size, device, slices[j].start); } /* Loop to resolve contained slices */ d = c; while (c) { for (j = 0; j < n; j++) { uint64_t start; int k = slices[j].container - 1; if (slices[j].size == 0) continue; if (slices[j].minor > 0) continue; if (slices[j].container == 0) continue; slices[j].minor = m++; start = slices[j].start - slices[k].start; printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", mapname, delim, j+1, slices[j].size, slices[k].minor, start); c--; } /* Terminate loop if nothing more to resolve */ if (d == c) break; } if (loopcreated && S_ISREG (buf.st_mode)) { if (del_loop(device)) { if (verbose) printf("can't del loop : %s\n", device); exit(1); } printf("loop deleted : %s\n", device); } break; case DELETE: for (j = n-1; j >= 0; j--) { if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); if (!slices[j].size || !dm_map_present(partname)) continue; if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, 0, &cookie)) { r++; continue; } if (verbose) printf("del devmap : %s\n", partname); } if (S_ISREG (buf.st_mode)) { if (del_loop(device)) { if (verbose) printf("can't del loop : %s\n", device); exit(1); } printf("loop deleted : %s\n", device); } break; case ADD: for (j = 0, c = 0; j < n; j++) { if (slices[j].size == 0) continue; /* Skip all contained slices */ if (slices[j].container > 0) { c++; continue; } if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); if (safe_sprintf(params, "%s %" PRIu64 , device, slices[j].start)) { fprintf(stderr, "params too small\n"); exit(1); } op = (dm_map_present(partname) ? DM_DEVICE_RELOAD : DM_DEVICE_CREATE); if (!dm_addmap(op, partname, DM_TARGET, params, slices[j].size, uuid, j+1, buf.st_mode & 0777, buf.st_uid, buf.st_gid, &cookie)) { fprintf(stderr, "create/reload failed on %s\n", partname); r++; } if (op == DM_DEVICE_RELOAD && !dm_simplecmd(DM_DEVICE_RESUME, partname, 1, &cookie)) { fprintf(stderr, "resume failed on %s\n", partname); r++; } dm_devn(partname, &slices[j].major, &slices[j].minor); if (verbose) printf("add map %s (%d:%d): 0 %" PRIu64 " %s %s\n", partname, slices[j].major, slices[j].minor, slices[j].size, DM_TARGET, params); } /* Loop to resolve contained slices */ d = c; while (c) { for (j = 0; j < n; j++) { uint64_t start; int k = slices[j].container - 1; if (slices[j].size == 0) continue; /* Skip all existing slices */ if (slices[j].minor > 0) continue; /* Skip all simple slices */ if (slices[j].container == 0) continue; /* Check container slice */ if (slices[k].size == 0) fprintf(stderr, "Invalid slice %d\n", k); if (safe_sprintf(partname, "%s%s%d", mapname, delim, j+1)) { fprintf(stderr, "partname too small\n"); exit(1); } strip_slash(partname); start = slices[j].start - slices[k].start; if (safe_sprintf(params, "%d:%d %" PRIu64, slices[k].major, slices[k].minor, start)) { fprintf(stderr, "params too small\n"); exit(1); } op = (dm_map_present(partname) ? DM_DEVICE_RELOAD : DM_DEVICE_CREATE); dm_addmap(op, partname, DM_TARGET, params, slices[j].size, uuid, j+1, buf.st_mode & 0777, buf.st_uid, buf.st_gid, &cookie); if (op == DM_DEVICE_RELOAD) dm_simplecmd(DM_DEVICE_RESUME, partname, 1, &cookie); dm_devn(partname, &slices[j].major, &slices[j].minor); if (verbose) printf("add map %s : 0 %" PRIu64 " %s %s\n", partname, slices[j].size, DM_TARGET, params); c--; } /* Terminate loop */ if (d == c) break; } break; default: break; } if (n > 0) break; } dm_udev_wait(cookie); dm_lib_release(); dm_lib_exit(); return r; }