static void _cb_set_destroy(struct cb_set *cbs) { // We know this is always called after a wait_all. So there should // never be in flight IO. if (!dm_list_empty(&cbs->allocated)) { // bail out log_error("async io still in flight"); return; } free(cbs->vec); free(cbs); }
static struct control_block *_cb_alloc(struct cb_set *cbs, void *context) { struct control_block *cb; if (dm_list_empty(&cbs->free)) return NULL; cb = dm_list_item(_list_pop(&cbs->free), struct control_block); cb->context = context; dm_list_add(&cbs->allocated, &cb->list); return cb; }
/* * lv_cache_create * @pool * @origin * * Given a cache_pool and an origin, link the two and create a * cached LV. * * Returns: cache LV on success, NULL on failure */ struct logical_volume *lv_cache_create(struct logical_volume *pool, struct logical_volume *origin) { const struct segment_type *segtype; struct cmd_context *cmd = pool->vg->cmd; struct logical_volume *cache_lv; struct lv_segment *seg; if (!lv_is_cache_pool(pool)) { log_error(INTERNAL_ERROR "%s is not a cache_pool LV", pool->name); return NULL; } if (!dm_list_empty(&pool->segs_using_this_lv)) { seg = get_only_segment_using_this_lv(pool); log_error("%s is already in use by %s", pool->name, seg ? seg->lv->name : "another LV"); return NULL; } if (lv_is_cache_type(origin)) { /* * FIXME: We can layer caches, insert_layer_for_lv() would * have to do a better job renaming the LVs in the stack * first so that there isn't a name collision with <name>_corig. * The origin under the origin would become *_corig_corig * before renaming the origin above to *_corig. */ log_error(INTERNAL_ERROR "The origin, %s, cannot be of cache type", origin->name); return NULL; } if (!(segtype = get_segtype_from_string(cmd, "cache"))) return_NULL; cache_lv = origin; if (!(origin = insert_layer_for_lv(cmd, cache_lv, CACHE, "_corig"))) return_NULL; seg = first_seg(cache_lv); seg->segtype = segtype; if (!attach_pool_lv(seg, pool, NULL, NULL)) return_NULL; return cache_lv; }
static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path, const char *new_vg_path) { char *dev_dir; struct id id; int match = 0; int found_id = 0; struct dm_list *vgids; struct str_list *sl; const char *vg_name_new; const char *vgid = NULL, *vg_name, *vg_name_old; char old_path[NAME_LEN], new_path[NAME_LEN]; struct volume_group *vg = NULL; int lock_vg_old_first = 1; vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL); vg_name_new = skip_dev_dir(cmd, new_vg_path, NULL); dev_dir = cmd->dev_dir; if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new)) return_0; log_verbose("Checking for existing volume group \"%s\"", vg_name_old); /* Avoid duplicates */ if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) { log_error("No complete volume groups found"); return 0; } dm_list_iterate_items(sl, vgids) { vgid = sl->str; if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid))) continue; if (!strcmp(vg_name, vg_name_old)) { if (match) { log_error("Found more than one VG called %s. " "Please supply VG uuid.", vg_name_old); return 0; } match = 1; } }
/* * Formats data LV for a use as a VDO pool LV. * * Calls tool 'vdoformat' on the already active volume. */ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv, const struct dm_vdo_target_params *vtp, uint64_t *logical_size) { char *dpath; const struct dm_config_node *cn; const struct dm_config_value *cv; struct pipe_data pdata; FILE *f; uint64_t lb; unsigned slabbits; int args = 1; char buf_args[5][128]; char buf[256]; /* buffer for short disk header (64B) */ const char *argv[19] = { /* Max supported args */ find_config_tree_str_allow_empty(data_lv->vg->cmd, global_vdo_format_executable_CFG, NULL) }; if (!(dpath = lv_path_dup(data_lv->vg->cmd->mem, data_lv))) { log_error("Failed to build device path for VDO formating of data volume %s.", display_lvname(data_lv)); return 0; } if (*logical_size) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--logical-size=" FMTu64 "K", (*logical_size / 2)) < 0) return_0; argv[args] = buf_args[args]; args++; } slabbits = 31 - clz(vtp->slab_size_mb / DM_VDO_BLOCK_SIZE * 512); log_debug("Slab size %s converted to %u bits.", display_size(data_lv->vg->cmd, vtp->slab_size_mb * UINT64_C(2 * 1024)), slabbits); if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--slab-bits=%u", slabbits) < 0) return_0; argv[args] = buf_args[args]; args++; if (vtp->check_point_frequency) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-checkpoint-frequency=%u", vtp->check_point_frequency) < 0) return_0; argv[args] = buf_args[args]; args++; } /* Convert size to GiB units or one of these strings: 0.25, 0.50, 0.75 */ if (vtp->index_memory_size_mb >= 1024) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-memory-size=%u", vtp->index_memory_size_mb / 1024) < 0) return_0; } else if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-memory-size=0.%u", (vtp->index_memory_size_mb < 512) ? 25 : (vtp->index_memory_size_mb < 768) ? 50 : 75) < 0) return_0; argv[args] = buf_args[args]; args++; if (vtp->use_sparse_index) { if (dm_snprintf(buf_args[args], sizeof(buf_args[0]), "--uds-sparse") < 0) return_0; argv[args] = buf_args[args]; args++; } /* Any other user opts add here */ if (!(cn = find_config_tree_array(data_lv->vg->cmd, global_vdo_format_options_CFG, NULL))) { log_error(INTERNAL_ERROR "Unable to find configuration for vdoformat command options."); return 0; } for (cv = cn->v; cv && args < 16; cv = cv->next) { if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/vdoformat_options."); return 0; } if (cv->v.str[0]) argv[++args] = cv->v.str; } /* Only unused VDO data LV could be activated and wiped */ if (!dm_list_empty(&data_lv->segs_using_this_lv)) { log_error(INTERNAL_ERROR "Failed to wipe logical VDO data for volume %s.", display_lvname(data_lv)); return 0; } argv[args] = dpath; if (!(f = pipe_open(data_lv->vg->cmd, argv, 0, &pdata))) { log_error("WARNING: Cannot read output from %s.", argv[0]); return 0; } if (!*logical_size) while (fgets(buf, sizeof(buf), f)) { /* TODO: Watch out for locales */ if (sscanf(buf, "Logical blocks defaulted to " FMTu64 " blocks", &lb) == 1) { *logical_size = lb * DM_VDO_BLOCK_SIZE; log_verbose("Available VDO logical blocks " FMTu64 " (%s).", lb, display_size(data_lv->vg->cmd, *logical_size)); break; } else log_warn("WARNING: Cannot parse output '%s' from %s.", buf, argv[0]); } if (!pipe_close(&pdata)) { log_error("Command %s failed.", argv[0]); return 0; } return 1; }
/* * Return last element of the list or NULL if empty */ struct dm_list *dm_list_last(const struct dm_list *head) { return (dm_list_empty(head) ? NULL : head->p); }
/* * Return first element of the list or NULL if empty */ struct dm_list *dm_list_first(const struct dm_list *head) { return (dm_list_empty(head) ? NULL : head->n); }