1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-04-01 18:50:41 +03:00

Change create_instance to create PV-based as well as VG-based format instances.

Add supporting functions to work with the format instance and metadata area
structures stored within the format instance. Add support for simple indexing
of metadata areas using PV id and mda order (for on-disk PV only for now, we
can extend the indexing even for other mdas if needed - we only need to define
a proper key for the index).
This commit is contained in:
Peter Rajnoha 2011-02-21 12:05:49 +00:00
parent 37c5724db2
commit 3a760ad8cd
6 changed files with 257 additions and 95 deletions

View File

@ -522,9 +522,7 @@ static struct metadata_area_ops _metadata_format1_ops = {
};
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
const char *vgname __attribute__((unused)),
const char *vgid __attribute__((unused)),
void *private __attribute__((unused)))
const struct format_instance_ctx *fic)
{
struct format_instance *fid;
struct metadata_area *mda;
@ -533,6 +531,8 @@ static struct format_instance *_format1_create_instance(const struct format_type
return_NULL;
fid->fmt = fmt;
fid->type = fic->type;
dm_list_init(&fid->metadata_areas_in_use);
dm_list_init(&fid->metadata_areas_ignored);

View File

@ -249,9 +249,7 @@ static struct metadata_area_ops _metadata_format_pool_ops = {
/* *INDENT-ON* */
static struct format_instance *_pool_create_instance(const struct format_type *fmt,
const char *vgname __attribute__((unused)),
const char *vgid __attribute__((unused)),
void *private __attribute__((unused)))
const struct format_instance_ctx *fic)
{
struct format_instance *fid;
struct metadata_area *mda;
@ -263,6 +261,8 @@ static struct format_instance *_pool_create_instance(const struct format_type *f
}
fid->fmt = fmt;
fid->type = fic->type;
dm_list_init(&fid->metadata_areas_in_use);
dm_list_init(&fid->metadata_areas_ignored);

View File

@ -37,16 +37,18 @@
#include <dirent.h>
#include <ctype.h>
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
void *context);
static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
const struct format_instance_ctx *fic);
struct text_fid_context {
char *raw_metadata_buf;
uint32_t raw_metadata_buf_size;
};
struct text_fid_pv_context {
int64_t label_sector;
};
struct dir_list {
struct dm_list list;
char dir[0];
@ -1911,13 +1913,38 @@ static int _text_pv_setup(const struct format_type *fmt,
return 1;
}
/* NULL vgname means use only the supplied context e.g. an archive file */
static struct format_instance *_text_create_text_instance(const struct format_type
*fmt, const char *vgname,
const char *vgid,
void *context)
static int _create_pv_text_instance(struct format_instance *fid,
const struct format_instance_ctx *fic)
{
struct format_instance *fid;
struct text_fid_pv_context *fid_pv_tc;
struct lvmcache_info *info;
if (!(fid_pv_tc = (struct text_fid_pv_context *)
dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*fid_pv_tc)))) {
log_error("Couldn't allocate text_fid_pv_context.");
return 0;
}
fid_pv_tc->label_sector = -1;
fid->private = (void *) fid_pv_tc;
if (!(fid->metadata_areas_index.array = dm_pool_zalloc(fid->fmt->cmd->mem,
FMT_TEXT_MAX_MDAS_PER_PV *
sizeof(struct metadata_area *)))) {
log_error("Couldn't allocate format instance metadata index.");
return 0;
}
if (fic->type & FMT_INSTANCE_MDAS &&
(info = info_from_pvid(fic->context.pv_id, 0)))
fid_add_mdas(fid, &info->mdas, fic->context.pv_id, ID_LEN);
return 1;
}
static int _create_vg_text_instance(struct format_instance *fid,
const struct format_instance_ctx *fic)
{
uint32_t type = fic->type;
struct text_fid_context *fidtc;
struct metadata_area *mda;
struct mda_context *mdac;
@ -1927,86 +1954,120 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
char path[PATH_MAX];
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
const char *vg_name, *vg_id;
if (!(fidtc = (struct text_fid_context *)
dm_pool_zalloc(fid->fmt->cmd->mem,sizeof(*fidtc)))) {
log_error("Couldn't allocate text_fid_context.");
return 0;
}
fidtc->raw_metadata_buf = NULL;
fid->private = (void *) fidtc;
if (type & FMT_INSTANCE_PRIVATE_MDAS) {
if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
return_0;
mda->ops = &_metadata_text_file_backup_ops;
mda->metadata_locn = fic->context.private;
mda->status = 0;
fid->metadata_areas_index.hash = NULL;
fid_add_mda(fid, mda, NULL, 0, 0);
} else {
vg_name = fic->context.vg_ref.vg_name;
vg_id = fic->context.vg_ref.vg_id;
if (!(fid->metadata_areas_index.hash = dm_hash_create(128))) {
log_error("Couldn't create metadata index for format "
"instance of VG %s.", vg_name);
return 0;
}
if (type & FMT_INSTANCE_AUX_MDAS) {
dir_list = &((struct mda_lists *) fid->fmt->private)->dirs;
dm_list_iterate_items(dl, dir_list) {
if (dm_snprintf(path, PATH_MAX, "%s/%s", dl->dir, vg_name) < 0) {
log_error("Name too long %s/%s", dl->dir, vg_name);
return 0;
}
if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
return_0;
mda->ops = &_metadata_text_file_ops;
mda->metadata_locn = create_text_context(fid->fmt->cmd, path, NULL);
mda->status = 0;
fid_add_mda(fid, mda, NULL, 0, 0);
}
raw_list = &((struct mda_lists *) fid->fmt->private)->raws;
dm_list_iterate_items(rl, raw_list) {
/* FIXME Cache this; rescan below if some missing */
if (!_raw_holds_vgname(fid, &rl->dev_area, vg_name))
continue;
if (!(mda = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mda))))
return_0;
if (!(mdac = dm_pool_zalloc(fid->fmt->cmd->mem, sizeof(*mdac))))
return_0;
mda->metadata_locn = mdac;
/* FIXME Allow multiple dev_areas inside area */
memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
mda->ops = &_metadata_text_raw_ops;
mda->status = 0;
/* FIXME MISTAKE? mda->metadata_locn = context; */
fid_add_mda(fid, mda, NULL, 0, 0);
}
}
if (type & FMT_INSTANCE_MDAS) {
/* Scan PVs in VG for any further MDAs */
lvmcache_label_scan(fid->fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vg_name, vg_id)))
goto_out;
dm_list_iterate_items(info, &vginfo->infos) {
if (!fid_add_mdas(fid, &info->mdas, info->dev->pvid, ID_LEN))
return_0;
}
}
/* FIXME Check raw metadata area count - rescan if required */
}
out:
return 1;
}
/* NULL vgname means use only the supplied context e.g. an archive file */
static struct format_instance *_text_create_text_instance(const struct format_type *fmt,
const struct format_instance_ctx *fic)
{
struct format_instance *fid;
int r;
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object.");
return NULL;
}
if (!(fidtc = (struct text_fid_context *)
dm_pool_zalloc(fmt->cmd->mem,sizeof(*fidtc)))) {
log_error("Couldn't allocate text_fid_context.");
return NULL;
}
fidtc->raw_metadata_buf = NULL;
fid->private = (void *) fidtc;
fid->fmt = fmt;
fid->type = fic->type;
dm_list_init(&fid->metadata_areas_in_use);
dm_list_init(&fid->metadata_areas_ignored);
if (!vgname) {
if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
return_NULL;
mda->ops = &_metadata_text_file_backup_ops;
mda->metadata_locn = context;
mda->status = 0;
fid_add_mda(fid, mda);
} else {
dir_list = &((struct mda_lists *) fmt->private)->dirs;
if (fid->type & FMT_INSTANCE_VG)
r = _create_vg_text_instance(fid, fic);
else
r = _create_pv_text_instance(fid, fic);
dm_list_iterate_items(dl, dir_list) {
if (dm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) {
log_error("Name too long %s/%s", dl->dir,
vgname);
return NULL;
}
context = create_text_context(fmt->cmd, path, NULL);
if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
return_NULL;
mda->ops = &_metadata_text_file_ops;
mda->metadata_locn = context;
mda->status = 0;
fid_add_mda(fid, mda);
}
raw_list = &((struct mda_lists *) fmt->private)->raws;
dm_list_iterate_items(rl, raw_list) {
/* FIXME Cache this; rescan below if some missing */
if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
continue;
if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda))))
return_NULL;
if (!(mdac = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mdac))))
return_NULL;
mda->metadata_locn = mdac;
/* FIXME Allow multiple dev_areas inside area */
memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
mda->ops = &_metadata_text_raw_ops;
mda->status = 0;
/* FIXME MISTAKE? mda->metadata_locn = context; */
fid_add_mda(fid, mda);
}
/* Scan PVs in VG for any further MDAs */
lvmcache_label_scan(fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
goto_out;
dm_list_iterate_items(info, &vginfo->infos) {
if (!fid_add_mdas(fid, &info->mdas))
return_NULL;
}
/* FIXME Check raw metadata area count - rescan if required */
if (r)
return fid;
else {
dm_pool_free(fmt->cmd->mem, fid);
return NULL;
}
out:
return fid;
}
void *create_text_context(struct cmd_context *cmd, const char *path,

View File

@ -22,6 +22,7 @@
#define FMT_TEXT_NAME "lvm2"
#define FMT_TEXT_ALIAS "text"
#define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
#define FMT_TEXT_MAX_MDAS_PER_PV 2
/*
* Archives a vg config. 'retain_days' is the minimum number of

View File

@ -2887,7 +2887,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
break;
}
if (dm_list_size(&info->mdas)) {
if (!fid_add_mdas(fid, &info->mdas))
if (!fid_add_mdas(fid, &info->mdas,
info->dev->pvid, ID_LEN))
return_NULL;
log_debug("Empty mda found for VG %s.", vgname);
@ -3918,22 +3919,117 @@ uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
return FAILED_EXIST;
}
void fid_add_mda(struct format_instance *fid, struct metadata_area *mda)
static int _convert_key_to_string(const char *key, size_t key_len,
unsigned sub_key, char *buf, size_t buf_len)
{
dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
&fid->metadata_areas_in_use, &mda->list);
memcpy(buf, key, key_len);
buf += key_len;
buf_len -= key_len;
if ((dm_snprintf(buf, buf_len, "_%u", sub_key) == -1))
return_0;
return 1;
}
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas)
int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
const char *key, size_t key_len, const unsigned sub_key)
{
char full_key[PATH_MAX];
dm_list_add(mda_is_ignored(mda) ? &fid->metadata_areas_ignored :
&fid->metadata_areas_in_use, &mda->list);
/* Return if the mda is not supposed to be indexed. */
if (!key)
return 1;
/* Add metadata area to index. */
if (fid->type & FMT_INSTANCE_VG) {
if (!_convert_key_to_string(key, key_len, sub_key,
full_key, PATH_MAX))
return_0;
dm_hash_insert(fid->metadata_areas_index.hash,
full_key, mda);
}
else
fid->metadata_areas_index.array[sub_key] = mda;
return 1;
}
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
const char *key, size_t key_len)
{
struct metadata_area *mda, *mda_new;
unsigned mda_index = 0;
dm_list_iterate_items(mda, mdas) {
mda_new = mda_copy(fid->fmt->cmd->mem, mda);
if (!mda_new)
return_0;
fid_add_mda(fid, mda_new);
fid_add_mda(fid, mda_new, key, key_len, mda_index);
mda_index++;
}
return 1;
}
struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
const char *key, size_t key_len,
const unsigned sub_key)
{
char full_key[PATH_MAX];
struct metadata_area *mda = NULL;
if (fid->type & FMT_INSTANCE_VG) {
if (!_convert_key_to_string(key, key_len, sub_key,
full_key, PATH_MAX))
return_NULL;
mda = (struct metadata_area *) dm_hash_lookup(fid->metadata_areas_index.hash,
full_key);
}
else
mda = fid->metadata_areas_index.array[sub_key];
return mda;
}
int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
const char *key, size_t key_len, const unsigned sub_key)
{
struct metadata_area *mda_indexed = NULL;
char full_key[PATH_MAX];
/* At least one of mda or key must be specified. */
if (!mda && !key)
return 1;
if (key) {
/*
* If both mda and key specified, check given mda
* with what we find using the index and return
* immediately if these two do not match.
*/
if (!(mda_indexed = fid_get_mda_indexed(fid, key, key_len, sub_key)) ||
(mda && mda != mda_indexed))
return 1;
mda = mda_indexed;
if (fid->type & FMT_INSTANCE_VG) {
if (!_convert_key_to_string(key, key_len, sub_key,
full_key, PATH_MAX))
return_0;
dm_hash_remove(fid->metadata_areas_index.hash, full_key);
} else
fid->metadata_areas_index.array[sub_key] = NULL;
}
dm_list_del(&mda->list);
return 1;
}

View File

@ -190,8 +190,14 @@ struct metadata_area *mda_copy(struct dm_pool *mem,
unsigned mda_is_ignored(struct metadata_area *mda);
void mda_set_ignored(struct metadata_area *mda, unsigned ignored);
unsigned mda_locns_match(struct metadata_area *mda1, struct metadata_area *mda2);
void fid_add_mda(struct format_instance *fid, struct metadata_area *mda);
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas);
int fid_add_mda(struct format_instance *fid, struct metadata_area *mda,
const char *key, size_t key_len, const unsigned sub_key);
int fid_add_mdas(struct format_instance *fid, struct dm_list *mdas,
const char *key, size_t key_len);
int fid_remove_mda(struct format_instance *fid, struct metadata_area *mda,
const char *key, size_t key_len, const unsigned sub_key);
struct metadata_area *fid_get_mda_indexed(struct format_instance *fid,
const char *key, size_t key_len, const unsigned sub_key);
int mdas_empty_or_ignored(struct dm_list *mdas);
#define seg_pvseg(seg, s) (seg)->areas[(s)].u.pv.pvseg
@ -290,10 +296,8 @@ struct format_handler {
/*
* Create format instance with a particular metadata area
*/
struct format_instance *(*create_instance) (const struct format_type *
fmt, const char *vgname,
const char *vgid,
void *context);
struct format_instance *(*create_instance) (const struct format_type *fmt,
const struct format_instance_ctx *fic);
/*
* Destructor for format instance