diff --git a/lib/activate/activate.c b/lib/activate/activate.c index c9a0efd9a..65296f464 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -49,7 +49,7 @@ int driver_version(char *version, size_t size) r = 1; - out: + out: dm_task_destroy(dmt); return r; @@ -151,52 +151,6 @@ static int _lv_suspend(struct logical_volume *lv) return r; } -static int _lv_rename(const char *old_name, struct logical_volume *lv) -{ -#if 0 - int r = 0; - char new_name[PATH_MAX]; - struct dm_task *dmt; - - if (test_mode()) { - _skip("Rename '%s' to '%s'.", old_name, lv->name); - return 0; - } - - if (!(dmt = setup_dm_task(old_name, DM_DEVICE_RENAME))) { - stack; - return 0; - } - - if (!build_dm_name(new_name, sizeof(new_name), "", - lv->vg->name, lv->name)) { - stack; - return 0; - } - - if (!dm_task_set_newname(dmt, new_name)) { - stack; - r = 0; - goto end; - } - - if (!dm_task_run(dmt)) { - stack; - r = 0; - goto end; - } - - fs_rename_lv(old_name, lv); - - end: - dm_task_destroy(dmt); - return r; -#else - log_err("lv_rename not implemented yet."); - return 1; -#endif -} - /* * These two functions return the number of LVs in the state, * or -1 on error. @@ -278,10 +232,10 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) return 0; } - if (!lv_info(lv, &info)) { - stack; - return 0; - } + if (!lv_info(lv, &info)) { + stack; + return 0; + } if (info.exists && !info.suspended) _lv_suspend(lv); @@ -289,7 +243,6 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) return 1; } - int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) { struct logical_volume *lv; @@ -303,10 +256,10 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) return 0; } - if (!lv_info(lv, &info)) { - stack; - return 0; - } + if (!lv_info(lv, &info)) { + stack; + return 0; + } if (info.exists && info.suspended) _lv_activate(lv); @@ -327,10 +280,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) return 0; } - if (!lv_info(lv, &info)) { - stack; - return 0; - } + if (!lv_info(lv, &info)) { + stack; + return 0; + } if (info.exists) _lv_deactivate(lv); @@ -351,14 +304,13 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s) return 0; } - if (!lv_info(lv, &info)) { - stack; - return 0; - } + if (!lv_info(lv, &info)) { + stack; + return 0; + } if (!info.exists || info.suspended) _lv_activate(lv); return 1; } - diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 01b4f62bf..da847feca 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -77,9 +77,13 @@ struct dev_layer { /* * Setup the dm_task. */ - int (*populate)(struct dev_manager * dm, - struct dm_task * dmt, struct dev_layer * dl); + int (*populate) (struct dev_manager * dm, + struct dm_task * dmt, struct dev_layer * dl); struct dm_info info; + + /* lvid plus layer */ + char *dlid; + struct logical_volume *lv; /* @@ -183,7 +187,7 @@ static char *_build_name(struct pool *mem, const char *vg, _count_hyphens(vg, &len, &hyphens); _count_hyphens(lv, &len, &hyphens); - if (layer) + if (layer && *layer) _count_hyphens(layer, &len, &hyphens); len += hyphens + 2; @@ -198,7 +202,7 @@ static char *_build_name(struct pool *mem, const char *vg, *out++ = '-'; _quote_hyphens(&out, lv); - if (layer) { + if (layer && *layer) { *out++ = '-'; _quote_hyphens(&out, layer); } @@ -207,6 +211,44 @@ static char *_build_name(struct pool *mem, const char *vg, return r; } +/* Find start of LV component in hyphenated name */ +static char *_find_lv_name(char *vg) +{ + char *c = vg; + + while (*c && *(c + 1)) { + if (*c == '-') { + if (*(c + 1) == '-') + c++; + else + return (c + 1); + } + c++; + } + + return NULL; +} + +static char *_build_dlid(struct pool *mem, const char *lvid, const char *layer) +{ + char *dlid; + int len; + + if (!layer) + layer = ""; + + len = strlen(lvid) + strlen(layer) + 2; + + if (!(dlid = pool_alloc(mem, len))) { + stack; + return NULL; + } + + sprintf(dlid, "%s%s%s", lvid, (*layer) ? "-" : "", layer); + + return dlid; +} + /* * Low level device-layer operations. */ @@ -223,10 +265,12 @@ static struct dm_task *_setup_task(const char *name, int task) return dmt; } -static int _info(const char *name, struct dm_info *info) +static int _info(const char *name, const char *uuid, struct dm_info *info, + struct pool *mem, char **uuid_out) { int r = 0; struct dm_task *dmt; + const char *u; log_debug("Getting device info for %s", name); if (!(dmt = _setup_task(name, DM_DEVICE_INFO))) { @@ -234,6 +278,9 @@ static int _info(const char *name, struct dm_info *info) return 0; } + if (uuid) + dm_task_set_uuid(dmt, uuid); + if (!dm_task_run(dmt)) { stack; goto out; @@ -243,6 +290,14 @@ static int _info(const char *name, struct dm_info *info) stack; goto out; } + + if (info->exists && uuid_out) { + if (!(u = dm_task_get_uuid(dmt))) { + stack; + goto out; + } + *uuid_out = pool_strdup(mem, u); + } r = 1; out: @@ -250,9 +305,40 @@ static int _info(const char *name, struct dm_info *info) return r; } +static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname) +{ + int r = 1; + struct dm_task *dmt; + + log_verbose("Renaming %s to %s", dl->name, newname); + + if (!(dmt = _setup_task(dl->name, DM_DEVICE_RENAME))) { + stack; + return 0; + } + + if (!dm_task_set_newname(dmt, newname)) { + stack; + r = 0; + goto out; + } + + if (!(r = dm_task_run(dmt))) + log_error("Couldn't rename device '%s'.", dl->name); + + if (r && _get_flag(dl, VISIBLE)) + fs_rename_lv(dl->lv, newname, _find_lv_name(dl->name)); + + dl->name = newname; + + out: + dm_task_destroy(dmt); + return r; +} + static int _load(struct dev_manager *dm, struct dev_layer *dl, int task) { - int r; + int r = 1; struct dm_task *dmt; log_verbose("Loading %s", dl->name); @@ -266,28 +352,28 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task) */ if (!dl->populate(dm, dmt, dl)) { log_error("Couldn't populate device '%s'.", dl->name); - return 0; + r = 0; + goto out; } - if (_get_flag(dl, VISIBLE)) { - dm_task_set_uuid(dmt, dl->lv->lvid.s); - } + dm_task_set_uuid(dmt, dl->dlid); if (!(r = dm_task_run(dmt))) log_error("Couldn't load device '%s'.", dl->name); if (!dm_task_get_info(dmt, &dl->info)) { stack; - return 0; + r = 0; + goto out; } - dm_task_destroy(dmt); - if (r && _get_flag(dl, VISIBLE)) fs_add_lv(dl->lv, dl->name); _clear_flag(dl, DIRTY); + out: + dm_task_destroy(dmt); return r; } @@ -480,7 +566,7 @@ static int _populate_origin(struct dev_manager *dm, if (lvm_snprintf(params, sizeof(params), "%s/%s", dm_dir(), real) == -1) { log_error("Couldn't create origin device parameters for '%s'.", - dl->name); + real); return 0; } @@ -503,7 +589,7 @@ static int _populate_snapshot(struct dev_manager *dm, struct snapshot *s; if (!(s = find_cow(dl->lv))) { - log_error("Couldn't find snapshot for '%s'.", dl->name); + log_error("Couldn't find snapshot for '%s'.", dl->lv->name); return 0; } @@ -597,7 +683,7 @@ int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv, /* * Try and get some info on this device. */ - if (!_info(name, info)) { + if (!_info(name, lv->lvid.s, info, NULL, NULL)) { stack; return 0; } @@ -617,6 +703,7 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv) return 0; } + /* FIXME Recurse */ if (!_suspend_or_resume(name, SUSPEND)) { stack; return 0; @@ -625,9 +712,11 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv) return 1; } -static struct dev_layer *_create_dev(struct dev_manager *dm, char *name) +static struct dev_layer *_create_dev(struct dev_manager *dm, char *name, + char *dlid) { struct dev_layer *dl; + char *uuid; if (!(dl = pool_zalloc(dm->mem, sizeof(*dl)))) { stack; @@ -636,15 +725,20 @@ static struct dev_layer *_create_dev(struct dev_manager *dm, char *name) dl->name = name; - if (!_info(dl->name, &dl->info)) { + if (!_info(dl->name, dlid, &dl->info, dm->mem, &uuid)) { stack; return NULL; } + if (dl->info.exists) + dl->dlid = uuid; + else + dl->dlid = dlid; + list_init(&dl->pre_create); list_init(&dl->pre_active); - if (!hash_insert(dm->layers, dl->name, dl)) { + if (!hash_insert(dm->layers, dl->dlid, dl)) { stack; return NULL; } @@ -656,7 +750,7 @@ static struct dev_layer *_create_layer(struct dev_manager *dm, const char *layer, struct logical_volume *lv) { - char *name; + char *name, *dlid; struct dev_layer *dl; if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, layer))) { @@ -664,8 +758,13 @@ static struct dev_layer *_create_layer(struct dev_manager *dm, return NULL; } - if (!(dl = hash_lookup(dm->layers, name)) && - !(dl = _create_dev(dm, name))) { + if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, layer))) { + stack; + return NULL; + } + + if (!(dl = hash_lookup(dm->layers, dlid)) && + !(dl = _create_dev(dm, name, dlid))) { stack; return NULL; } @@ -679,18 +778,18 @@ static struct dev_layer *_create_layer(struct dev_manager *dm, * Finds the specified layer. */ static struct dev_layer *_lookup(struct dev_manager *dm, - const char *lv, const char *layer) + const char *lvid, const char *layer) { - char *name; + char *dlid; struct dev_layer *dl; - if (!(name = _build_name(dm->mem, dm->vg_name, lv, layer))) { + if (!(dlid = _build_dlid(dm->mem, lvid, layer))) { stack; return NULL; } - dl = hash_lookup(dm->layers, name); - pool_free(dm->mem, name); + dl = hash_lookup(dm->layers, dlid); + pool_free(dm->mem, dlid); return dl; } @@ -715,7 +814,7 @@ static int _expand_origin_real(struct dev_manager *dm, struct logical_volume *lv) { struct dev_layer *dl; - char *real_name; + char *real_dlid; struct str_list *sl; if (!(dl = _create_layer(dm, "real", lv))) { @@ -725,7 +824,7 @@ static int _expand_origin_real(struct dev_manager *dm, dl->populate = _populate_vanilla; _clear_flag(dl, VISIBLE); - real_name = dl->name; + real_dlid = dl->dlid; if (!(dl = _create_layer(dm, NULL, lv))) { stack; @@ -740,7 +839,7 @@ static int _expand_origin_real(struct dev_manager *dm, return 0; } - if (!(sl->str = pool_strdup(dm->mem, real_name))) { + if (!(sl->str = pool_strdup(dm->mem, real_dlid))) { stack; return 0; } @@ -777,7 +876,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv, * cow */ struct dev_layer *dl; - char *cow_name; + char *cow_dlid; struct str_list *sl; if (!(dl = _create_layer(dm, "cow", lv))) { @@ -787,7 +886,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv, dl->populate = _populate_vanilla; _clear_flag(dl, VISIBLE); - cow_name = dl->name; + cow_dlid = dl->dlid; if (!(dl = _create_layer(dm, NULL, lv))) { stack; @@ -802,7 +901,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv, return 0; } - if (!(sl->str = pool_strdup(dm->mem, cow_name))) { + if (!(sl->str = pool_strdup(dm->mem, cow_dlid))) { stack; return 0; } @@ -815,8 +914,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv, return 0; } - if (!(sl->str = _build_name(dm->mem, dm->vg_name, - s->origin->name, "real"))) { + if (!(sl->str = _build_dlid(dm->mem, s->origin->lvid.s, "real"))) { stack; return 0; } @@ -866,14 +964,14 @@ static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl, int flag) { struct list *sh; - char *name; + char *dlid; struct dev_layer *dep; list_iterate(sh, &dl->pre_create) { - name = list_item(sh, struct str_list)->str; + dlid = list_item(sh, struct str_list)->str; - if (!(dep = hash_lookup(dm->layers, name))) { - log_error("Couldn't find device layer '%s'.", name); + if (!(dep = hash_lookup(dm->layers, dlid))) { + log_error("Couldn't find device layer '%s'.", dlid); return 0; } @@ -923,7 +1021,7 @@ static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag) list_iterate(lvh, lvs) { lv = list_item(lvh, struct lv_list)->lv; - if (!(dl = _lookup(dm, lv->name, NULL))) { + if (!(dl = _lookup(dm, lv->lvid.s, NULL))) { stack; return 0; } @@ -947,14 +1045,15 @@ int _create_rec(struct dev_manager *dm, struct dev_layer *dl) { struct list *sh; struct dev_layer *dep; - char *name; + char *dlid, *newname, *suffix; + int len; int suspended = 0; list_iterate(sh, &dl->pre_create) { - name = list_item(sh, struct str_list)->str; + dlid = list_item(sh, struct str_list)->str; - if (!(dep = hash_lookup(dm->layers, name))) { - log_error("Couldn't find device layer '%s'.", name); + if (!(dep = hash_lookup(dm->layers, dlid))) { + log_error("Couldn't find device layer '%s'.", dlid); return 0; } @@ -964,12 +1063,33 @@ int _create_rec(struct dev_manager *dm, struct dev_layer *dl) } suspended = 1; + if (!strcmp(dep->dlid, dl->dlid)) { + log_error("BUG: pre-create loop detected (%s)", dlid); + return 0; + } + if (!_create_rec(dm, dep)) { stack; return 0; } } + /* Rename? */ + if (dl->info.exists) { + newname = _build_name(dm->mem, dm->vg_name, dl->lv->name, NULL); + len = strlen(newname); + if (strncmp(newname, dl->name, len)) { + if ((suffix = rindex(dl->dlid, '-'))) + suffix++; + newname = _build_name(dm->mem, dm->vg_name, + dl->lv->name, suffix); + if (!_rename(dm, dl, newname)) { + stack; + return 0; + } + } + } + /* Create? */ if (!dl->info.exists) { if (!_load(dm, dl, DM_DEVICE_CREATE)) { @@ -1159,7 +1279,7 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name) return 0; } - if (!(dl = _create_dev(dm, copy))) { + if (!(dl = _create_dev(dm, copy, ""))) { stack; return 0; } @@ -1270,21 +1390,20 @@ static void _remove_lvs(struct list *head, struct logical_volume *origin) static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg) { int found; - char *name; + char *dlid; struct list *lvh; struct logical_volume *lv; list_iterate(lvh, &vg->lvs) { lv = list_item(lvh, struct lv_list)->lv; - name = _build_name(dm->mem, dm->vg_name, lv->name, NULL); - if (!name) { + if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) { stack; return 0; } - found = hash_lookup(dm->layers, name) ? 1 : 0; - pool_free(dm->mem, name); + found = hash_lookup(dm->layers, dlid) ? 1 : 0; + pool_free(dm->mem, dlid); if (found) { log_debug("Found active lv %s", lv->name); @@ -1299,7 +1418,7 @@ static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg) return 1; } -static int _activate(struct dev_manager *dm, struct logical_volume *lv, +static int _activate(struct dev_manager *dm, struct logical_volume *lv, activate_t activate) { if (!_scan_existing_devices(dm)) { @@ -1341,4 +1460,3 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv) { return _activate(dm, lv, DEACTIVATE); } - diff --git a/lib/activate/fs.c b/lib/activate/fs.c index f23d78499..c981c2098 100644 --- a/lib/activate/fs.c +++ b/lib/activate/fs.c @@ -130,8 +130,7 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name) int fs_add_lv(struct logical_volume *lv, const char *dev) { - if (!_mk_dir(lv->vg) || - !_mk_link(lv, dev)) { + if (!_mk_dir(lv->vg) || !_mk_link(lv, dev)) { stack; return 0; } @@ -141,8 +140,7 @@ int fs_add_lv(struct logical_volume *lv, const char *dev) int fs_del_lv(struct logical_volume *lv) { - if (!_rm_link(lv, lv->name) || - !_rm_dir(lv->vg)) { + if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) { stack; return 0; } @@ -150,10 +148,11 @@ int fs_del_lv(struct logical_volume *lv) return 1; } +/* FIXME Use rename() */ int fs_rename_lv(struct logical_volume *lv, const char *dev, const char *old_name) { - if (!_rm_link(lv, old_name)) + if (old_name && !_rm_link(lv, old_name)) stack; if (!_mk_link(lv, dev))