/* Create a task, set its name and run it. */ static int run_task(struct lib_context *lc, struct raid_set *rs, char *table, int type, char *name) { /* * DM_UUID_LEN is defined in dm-ioctl.h as 129 characters; * though not all 129 must be used (md uses just 16 from * a quick review of md.c. * We will be using: (len vol grp name) */ char uuid[DM_UUID_LEN]; int ret; struct dm_task *dmt; _init_dm(); ret = (dmt = dm_task_create(type)) && dm_task_set_name(dmt, name); if (ret && table) ret = parse_table(lc, dmt, table); if (ret) { if (DM_DEVICE_CREATE == type) { ret = dmraid_uuid(lc, rs, uuid, DM_UUID_LEN, name) && dm_task_set_uuid(dmt, uuid) && dm_task_run(dmt); } else ret = dm_task_run(dmt); } _exit_dm(dmt); return ret; }
int dm_mount_aspect(substrate_t *substrate, u64 header_offset, u8 *header_key, char *name) { char *params; struct dm_task *task; task = dm_task_create(DM_DEVICE_CREATE); if(!task) { die("dm_task_create"); } if(!dm_task_set_name(task, name)) { die("dm_task_set_name"); } if(!dm_task_set_uuid(task, name)) { die("dm_task_set_uuid"); } params = steg_malloc(strlen(substrate->filename) + 4096); sprintf(params, "%s %zu ", substrate->filename, header_offset); sprint_hex(params + strlen(params), header_key, KEY_BYTES); if(!dm_task_add_target(task, 0, substrate->bytes, "steg", params)) { die("dm_task_add_target"); } if(!dm_task_run(task)) { die("dm_task_run"); } dm_task_destroy(task); steg_free(params); return 0; }
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; }
/* Get uuid of a device */ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh) { struct dm_task *dmt; struct dm_info info; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) { log_error("_get_device_info: dm_task creation for info failed"); return NULL; } if (dmevh->uuid) dm_task_set_uuid(dmt, dmevh->uuid); else if (dmevh->dev_name) dm_task_set_name(dmt, dmevh->dev_name); else if (dmevh->major && dmevh->minor) { dm_task_set_major(dmt, dmevh->major); dm_task_set_minor(dmt, dmevh->minor); } /* FIXME Add name or uuid or devno to messages */ if (!dm_task_run(dmt)) { log_error("_get_device_info: dm_task_run() failed"); goto failed; } if (!dm_task_get_info(dmt, &info)) { log_error("_get_device_info: failed to get info for device"); goto failed; } if (!info.exists) { log_error("_get_device_info: device not found"); goto failed; } return dmt; failed: dm_task_destroy(dmt); return NULL; }
/* * Low level device-layer operations. */ static struct dm_task *_setup_task(const char *name, const char *uuid, uint32_t *event_nr, int task, uint32_t major, uint32_t minor) { struct dm_task *dmt; if (!(dmt = dm_task_create(task))) return_NULL; if (name) dm_task_set_name(dmt, name); if (uuid && *uuid) dm_task_set_uuid(dmt, uuid); if (event_nr) dm_task_set_event_nr(dmt, *event_nr); if (major) dm_task_set_major_minor(dmt, major, minor, 1); return dmt; }
/* Check, if a device exists. */ static int _fill_device_data(struct thread_status *ts) { struct dm_task *dmt; struct dm_info dmi; if (!ts->device.uuid) return 0; ts->device.name = NULL; ts->device.major = ts->device.minor = 0; dmt = dm_task_create(DM_DEVICE_INFO); if (!dmt) return 0; dm_task_set_uuid(dmt, ts->device.uuid); if (!dm_task_run(dmt)) goto fail; ts->device.name = dm_strdup(dm_task_get_name(dmt)); if (!ts->device.name) goto fail; if (!dm_task_get_info(dmt, &dmi)) goto fail; ts->device.major = dmi.major; ts->device.minor = dmi.minor; dm_task_destroy(dmt); return 1; fail: dm_task_destroy(dmt); dm_free(ts->device.name); return 0; }
static int _create_and_load_v4(struct dm_task *dmt) { struct dm_task *task; int r; uint32_t cookie; /* Use new task struct to create the device */ if (!(task = dm_task_create(DM_DEVICE_CREATE))) { log_error("Failed to create device-mapper task struct"); _udev_complete(dmt); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); _udev_complete(dmt); return 0; } if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { dm_task_destroy(task); _udev_complete(dmt); return 0; } task->major = dmt->major; task->minor = dmt->minor; task->uid = dmt->uid; task->gid = dmt->gid; task->mode = dmt->mode; /* FIXME: Just for udev_check in dm_task_run. Can we avoid this? */ task->event_nr = dmt->event_nr & DM_UDEV_FLAGS_MASK; task->cookie_set = dmt->cookie_set; r = dm_task_run(task); dm_task_destroy(task); if (!r) { _udev_complete(dmt); return 0; } /* Next load the table */ if (!(task = dm_task_create(DM_DEVICE_RELOAD))) { log_error("Failed to create device-mapper task struct"); _udev_complete(dmt); r = 0; goto revert; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); _udev_complete(dmt); r = 0; goto revert; } task->read_only = dmt->read_only; task->head = dmt->head; task->tail = dmt->tail; r = dm_task_run(task); task->head = NULL; task->tail = NULL; dm_task_destroy(task); if (!r) { _udev_complete(dmt); goto revert; } /* Use the original structure last so the info will be correct */ dmt->type = DM_DEVICE_RESUME; dm_free(dmt->uuid); dmt->uuid = NULL; r = dm_task_run(dmt); if (r) return r; revert: dmt->type = DM_DEVICE_REMOVE; dm_free(dmt->uuid); dmt->uuid = NULL; /* * Also udev-synchronize "remove" dm task that is a part of this revert! * But only if the original dm task was supposed to be synchronized. */ if (dmt->cookie_set) { cookie = (dmt->event_nr & ~DM_UDEV_FLAGS_MASK) | (DM_COOKIE_MAGIC << DM_UDEV_FLAGS_SHIFT); dm_task_set_cookie(dmt, &cookie, (dmt->event_nr & DM_UDEV_FLAGS_MASK) >> DM_UDEV_FLAGS_SHIFT); }
static int _first_status(int task, const char *name, const char *uuid, uint64_t *start, uint64_t *length, size_t target_size, char *target_ptr, size_t params_size, char *params_ptr) { uint64_t a, b; struct dm_task *dmt; struct dm_info dmi; char *tgt, *prm; int rc = -1; if (!(dmt = dm_task_create(task))) return -1; if (name && !dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, uuid)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &dmi)) goto out; if (!dmi.exists) { error(0, "target %s does not exists", name ? name : (uuid ? uuid : "<NULL>")); goto out; } (void)dm_get_next_target(dmt, NULL, &a, &b, &tgt, &prm); if (start) *start = a; if (length) *length = b; if (target_size > 0 && target_ptr) { if (strlen(tgt) >= target_size) { error(0, "too long target name"); goto out; } strcpy(target_ptr, tgt); } if (params_size > 0 && params_ptr) { if (strlen(prm) >= params_size) { error(0, "too long target params"); goto out; } strcpy(params_ptr, prm); } rc = 0; out: dm_task_destroy(dmt); return rc; }
int era_dm_info(const char *name, const char *uuid, struct era_dm_info *info, size_t name_size, char *name_ptr, size_t uuid_size, char *uuid_ptr) { struct dm_task *dmt; struct dm_info dmi; int rc = -1; if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return -1; if (name && !dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, uuid)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &dmi)) goto out; if (info) { 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; } if (dmi.exists && name_size > 0 && name_ptr) { const char *dm_name; size_t dm_name_len; dm_name = dm_task_get_name(dmt); if (!dm_name) goto out; dm_name_len = strlen(dm_name); if (dm_name_len >= name_size) { rc = dm_name_len + 1; goto out; } strcpy(name_ptr, dm_name); } if (dmi.exists && uuid_size > 0 && uuid_ptr) { const char *dm_uuid; size_t dm_uuid_len; dm_uuid = dm_task_get_uuid(dmt); if (!dm_uuid) goto out; dm_uuid_len = strlen(dm_uuid); if (dm_uuid_len >= uuid_size) { dm_task_destroy(dmt); return dm_uuid_len + 1; } strcpy(uuid_ptr, dm_uuid); } rc = 0; out: dm_task_destroy(dmt); return rc; }
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; }
static int _reload_with_suppression_v4(struct dm_task *dmt) { struct dm_task *task; struct target *t1, *t2; int r; /* New task to get existing table information */ if (!(task = dm_task_create(DM_DEVICE_TABLE))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { dm_task_destroy(task); return 0; } task->major = dmt->major; task->minor = dmt->minor; r = dm_task_run(task); if (!r) { dm_task_destroy(task); return r; } /* Store existing table size */ t2 = task->head; while (t2 && t2->next) t2 = t2->next; dmt->existing_table_size = t2 ? t2->start + t2->length : 0; if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only) goto no_match; t1 = dmt->head; t2 = task->head; while (t1 && t2) { while (t2->params[strlen(t2->params) - 1] == ' ') t2->params[strlen(t2->params) - 1] = '\0'; if ((t1->start != t2->start) || (t1->length != t2->length) || (strcmp(t1->type, t2->type)) || (strcmp(t1->params, t2->params))) goto no_match; t1 = t1->next; t2 = t2->next; } if (!t1 && !t2) { dmt->dmi.v4 = task->dmi.v4; task->dmi.v4 = NULL; dm_task_destroy(task); return 1; } no_match: dm_task_destroy(task); /* Now do the original reload */ dmt->suppress_identical_reload = 0; r = dm_task_run(dmt); return r; }
/* Create new device and load table to it. */ static int _create_and_load_v4(struct dm_task *dmt) { struct dm_task *task; int r; log_verbose("create and load called"); /* Use new task struct to create the device */ if (!(task = dm_task_create(DM_DEVICE_CREATE))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { dm_task_destroy(task); return 0; } task->major = dmt->major; task->minor = dmt->minor; task->uid = dmt->uid; task->gid = dmt->gid; task->mode = dmt->mode; r = dm_task_run(task); dm_task_destroy(task); if (!r) return r; /* Next load the table */ if (!(task = dm_task_create(DM_DEVICE_RELOAD))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } task->read_only = dmt->read_only; task->head = dmt->head; task->tail = dmt->tail; r = dm_task_run(task); task->head = NULL; task->tail = NULL; dm_task_destroy(task); if (!r) goto revert; /* Use the original structure last so the info will be correct */ dmt->type = DM_DEVICE_RESUME; dm_free(dmt->uuid); dmt->uuid = NULL; r = dm_task_run(dmt); if (r) return r; revert: dmt->type = DM_DEVICE_REMOVE; dm_free(dmt->uuid); dmt->uuid = NULL; if (!dm_task_run(dmt)) log_error("Failed to revert device creation."); 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; }