int dm_device_remove_all(uint64_t *dev) { struct bl_dm_tree *p; struct dm_tree_node *node; const char *uuid; int ret = 0; uint32_t major, minor; uint64_t bl_dev; memcpy(&major, dev, sizeof(uint32_t)); memcpy(&minor, (void *)dev + sizeof(uint32_t), sizeof(uint32_t)); bl_dev = MKDEV(major, minor); p = find_bl_dm_tree(bl_dev); if (!p) return ret; node = dm_tree_find_node(p->tree, MAJOR(bl_dev), MINOR(bl_dev)); if (!node) return ret; uuid = dm_tree_node_get_uuid(node); if (!uuid) return ret; dm_device_remove(bl_dev); ret = dm_tree_deactivate_children(node, uuid, strlen(uuid)); dm_task_update_nodes(); bl_dm_remove_tree(bl_dev); return ret; }
static int dm_device_remove(uint64_t dev) { struct dm_task *dmt; struct dm_names *dmnames; char *name = NULL; int ret = 0; /* Look for dev_name via dev, if dev_name could be transferred here, we could jump to DM_DEVICE_REMOVE directly */ dmt = dm_task_create(DM_DEVICE_LIST); if (!dmt) { BL_LOG_ERR("dm_task creation failed\n"); goto out; } ret = dm_task_run(dmt); if (!ret) { BL_LOG_ERR("dm_task_run failed\n"); goto out; } dmnames = dm_task_get_names(dmt); if (!dmnames || !dmnames->dev) { BL_LOG_ERR("dm_task_get_names failed\n"); goto out; } while (dmnames) { if (dmnames->dev == dev) { name = strdup(dmnames->name); break; } dmnames = (void *)dmnames + dmnames->next; } if (!name) { BL_LOG_ERR("Could not find device\n"); goto out; } dm_task_update_nodes(); out: if (dmt) dm_task_destroy(dmt); /* Start to remove device */ if (name) { ret = dm_device_remove_byname(name); free(name); } return ret; }
static int dm_device_remove_byname(const char *dev_name) { struct dm_task *dmt; int ret = 0; BL_LOG_INFO("%s: %s\n", __func__, dev_name); dmt = dm_task_create(DM_DEVICE_REMOVE); if (!dmt) return 0; ret = dm_task_set_name(dmt, dev_name) && dm_task_run(dmt); dm_task_update_nodes(); dm_task_destroy(dmt); return ret; }
/* * Create device via device mapper * return 0 when creation failed * return dev no for created device */ static uint64_t dm_device_create_mapped(const char *dev_name, struct bl_dm_table *p) { struct dm_task *dmt; struct dm_info dminfo; int ret = 0; dmt = dm_task_create(DM_DEVICE_CREATE); if (!dmt) { BL_LOG_ERR("Create dm_task for %s failed\n", dev_name); return 0; } ret = dm_task_set_name(dmt, dev_name); if (!ret) goto err_out; while (p) { ret = dm_task_add_target(dmt, p->offset, p->size, p->target_type, p->params); if (!ret) goto err_out; p = p->next; } ret = dm_task_run(dmt) && dm_task_get_info(dmt, &dminfo) && dminfo.exists; if (!ret) goto err_out; dm_task_update_nodes(); err_out: dm_task_destroy(dmt); if (!ret) { BL_LOG_ERR("Create device %s failed\n", dev_name); return 0; } return MKDEV(dminfo.major, dminfo.minor); }
int dm_remove_device(const char *name, int force, uint64_t size) { int r = -EINVAL; int retries = force ? RETRY_COUNT : 1; int error_target = 0; if (!name || (force && !size)) return -EINVAL; do { r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL; if (--retries && r) { log_dbg("WARNING: other process locked internal device %s, %s.", name, retries ? "retrying remove" : "giving up"); if (force && (crypt_get_debug_level() == CRYPT_LOG_DEBUG)) debug_processes_using_device(name); sleep(1); if (force && !error_target) { /* If force flag is set, replace device with error, read-only target. * it should stop processes from reading it and also removed underlying * device from mapping, so it is usable again. * Force flag should be used only for temporary devices, which are * intended to work inside cryptsetup only! * Anyway, if some process try to read temporary cryptsetup device, * it is bug - no other process should try touch it (e.g. udev). */ _error_device(name, size); error_target = 1; } } } while (r == -EINVAL && retries); dm_task_update_nodes(); 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; }