mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
o Split struct io_space into:
struct format_handler - format methods struct format_instance - links instance data, methods, and cmd struct cmd_context - dev_dir, memory allocator, device filter
This commit is contained in:
parent
3c02236767
commit
2107f48208
@ -27,6 +27,7 @@ static int _check_vgs(struct list *pvs)
|
||||
|
||||
if (!first)
|
||||
first = dl;
|
||||
|
||||
else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
|
||||
log_err("VG data differs between PVs %s and %s",
|
||||
dev_name(first->dev), dev_name(dl->dev));
|
||||
@ -86,7 +87,8 @@ static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct volume_group *_vg_read(struct io_space *is, const char *vg_name)
|
||||
static struct volume_group *_vg_read(struct format_instance *fi,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct list pvs;
|
||||
@ -99,15 +101,14 @@ static struct volume_group *_vg_read(struct io_space *is, const char *vg_name)
|
||||
}
|
||||
|
||||
/* Strip prefix if present */
|
||||
if (!strncmp(vg_name, is->prefix, strlen(is->prefix)))
|
||||
vg_name += strlen(is->prefix);
|
||||
vg_name = strip_dir(vg_name, fi->cmd->dev_dir);
|
||||
|
||||
if (!read_pvs_in_vg(vg_name, is->filter, mem, &pvs)) {
|
||||
if (!read_pvs_in_vg(vg_name, fi->cmd->filter, mem, &pvs)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(vg = _build_vg(is->mem, &pvs)))
|
||||
if (!(vg = _build_vg(fi->cmd->mem, &pvs)))
|
||||
stack;
|
||||
|
||||
pool_destroy(mem);
|
||||
@ -174,7 +175,7 @@ static int _flatten_vg(struct pool *mem, struct volume_group *vg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _vg_write(struct io_space *is, struct volume_group *vg)
|
||||
static int _vg_write(struct format_instance *fi, struct volume_group *vg)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct list pvs;
|
||||
@ -187,17 +188,17 @@ static int _vg_write(struct io_space *is, struct volume_group *vg)
|
||||
|
||||
list_init(&pvs);
|
||||
|
||||
r = (_flatten_vg(mem, vg, &pvs, is->prefix, is->filter) &&
|
||||
r = (_flatten_vg(mem, vg, &pvs, fi->cmd->dev_dir, fi->cmd->filter) &&
|
||||
write_pvds(&pvs));
|
||||
pool_destroy(mem);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct physical_volume *_pv_read(struct io_space *is,
|
||||
static struct physical_volume *_pv_read(struct format_instance *fi,
|
||||
const char *name)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct physical_volume *pv;
|
||||
struct physical_volume *pv = NULL;
|
||||
struct disk_list *dl;
|
||||
struct device *dev;
|
||||
|
||||
@ -208,35 +209,33 @@ static struct physical_volume *_pv_read(struct io_space *is,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dev = dev_cache_get(name, is->filter))) {
|
||||
if (!(dev = dev_cache_get(name, fi->cmd->filter))) {
|
||||
stack;
|
||||
goto bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(dl = read_disk(dev, mem, NULL))) {
|
||||
stack;
|
||||
goto bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(pv = pool_alloc(is->mem, sizeof(*pv)))) {
|
||||
if (!(pv = pool_alloc(fi->cmd->mem, sizeof(*pv)))) {
|
||||
stack;
|
||||
goto bad;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!import_pv(is->mem, dl->dev, pv, &dl->pvd)) {
|
||||
if (!import_pv(fi->cmd->mem, dl->dev, pv, &dl->pvd)) {
|
||||
stack;
|
||||
goto bad;
|
||||
pool_free(fi->cmd->mem, pv);
|
||||
pv = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
pool_destroy(mem);
|
||||
return pv;
|
||||
|
||||
bad:
|
||||
pool_destroy(mem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct list *_get_pvs(struct io_space *is)
|
||||
static struct list *_get_pvs(struct format_instance *fi)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct list pvs, *results;
|
||||
@ -247,7 +246,7 @@ static struct list *_get_pvs(struct io_space *is)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(results = pool_alloc(is->mem, sizeof(*results)))) {
|
||||
if (!(results = pool_alloc(fi->cmd->mem, sizeof(*results)))) {
|
||||
stack;
|
||||
pool_destroy(mem);
|
||||
return NULL;
|
||||
@ -256,12 +255,12 @@ static struct list *_get_pvs(struct io_space *is)
|
||||
list_init(&pvs);
|
||||
list_init(results);
|
||||
|
||||
if (!read_pvs_in_vg(NULL, is->filter, mem, &pvs)) {
|
||||
if (!read_pvs_in_vg(NULL, fi->cmd->filter, mem, &pvs)) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!import_pvs(is->mem, &pvs, results, &count)) {
|
||||
if (!import_pvs(fi->cmd->mem, &pvs, results, &count)) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -270,7 +269,7 @@ static struct list *_get_pvs(struct io_space *is)
|
||||
return results;
|
||||
|
||||
bad:
|
||||
pool_free(is->mem, results);
|
||||
pool_free(fi->cmd->mem, results);
|
||||
pool_destroy(mem);
|
||||
return NULL;
|
||||
}
|
||||
@ -289,10 +288,10 @@ static int _find_vg_name(struct list *names, const char *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct list *_get_vgs(struct io_space *is)
|
||||
static struct list *_get_vgs(struct format_instance *fi)
|
||||
{
|
||||
struct list *pvh;
|
||||
struct list *pvs, *names = pool_alloc(is->mem, sizeof(*names));
|
||||
struct list *pvs, *names = pool_alloc(fi->cmd->mem, sizeof(*names));
|
||||
struct name_list *nl;
|
||||
|
||||
if (!names) {
|
||||
@ -302,7 +301,7 @@ static struct list *_get_vgs(struct io_space *is)
|
||||
|
||||
list_init(names);
|
||||
|
||||
if (!(pvs = _get_pvs(is))) {
|
||||
if (!(pvs = _get_pvs(fi))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -314,12 +313,12 @@ static struct list *_get_vgs(struct io_space *is)
|
||||
_find_vg_name(names, pvl->pv.vg_name))
|
||||
continue;
|
||||
|
||||
if (!(nl = pool_alloc(is->mem, sizeof(*nl)))) {
|
||||
if (!(nl = pool_alloc(fi->cmd->mem, sizeof(*nl)))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(nl->name = pool_strdup(is->mem, pvl->pv.vg_name))) {
|
||||
if (!(nl->name = pool_strdup(fi->cmd->mem, pvl->pv.vg_name))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -333,11 +332,11 @@ static struct list *_get_vgs(struct io_space *is)
|
||||
return names;
|
||||
|
||||
bad:
|
||||
pool_free(is->mem, names);
|
||||
pool_free(fi->cmd->mem, names);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _pv_setup(struct io_space *is, struct physical_volume *pv,
|
||||
static int _pv_setup(struct format_instance *fi, struct physical_volume *pv,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
/*
|
||||
@ -351,7 +350,7 @@ static int _pv_setup(struct io_space *is, struct physical_volume *pv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pv_write(struct io_space *is, struct physical_volume *pv)
|
||||
static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
|
||||
{
|
||||
struct pool *mem;
|
||||
struct disk_list *dl;
|
||||
@ -401,7 +400,7 @@ static int _pv_write(struct io_space *is, struct physical_volume *pv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _vg_setup(struct io_space *is, struct volume_group *vg)
|
||||
int _vg_setup(struct format_instance *fi, struct volume_group *vg)
|
||||
{
|
||||
/* just check max_pv and max_lv */
|
||||
if (vg->max_lv >= MAX_LV)
|
||||
@ -439,44 +438,36 @@ int _vg_setup(struct io_space *is, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _destroy(struct io_space *ios)
|
||||
void _destroy(struct format_instance *fi)
|
||||
{
|
||||
dbg_free(ios->prefix);
|
||||
pool_destroy(ios->mem);
|
||||
dbg_free(ios);
|
||||
dbg_free(fi);
|
||||
}
|
||||
|
||||
struct io_space *create_lvm1_format(const char *prefix, struct pool *mem,
|
||||
struct dev_filter *filter)
|
||||
{
|
||||
struct io_space *ios = dbg_malloc(sizeof(*ios));
|
||||
|
||||
if (!ios) {
|
||||
static struct format_handler _format1_ops = {
|
||||
get_vgs: _get_vgs,
|
||||
get_pvs: _get_pvs,
|
||||
pv_read: _pv_read,
|
||||
pv_setup: _pv_setup,
|
||||
pv_write: _pv_write,
|
||||
vg_read: _vg_read,
|
||||
vg_setup: _vg_setup,
|
||||
vg_write: _vg_write,
|
||||
destroy: _destroy,
|
||||
};
|
||||
|
||||
struct format_instance *create_lvm1_format(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_instance *fi = dbg_malloc(sizeof(*fi));
|
||||
|
||||
if (!fi) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ios->get_vgs = _get_vgs;
|
||||
ios->get_pvs = _get_pvs;
|
||||
ios->pv_read = _pv_read;
|
||||
ios->pv_setup = _pv_setup;
|
||||
ios->pv_write = _pv_write;
|
||||
ios->vg_read = _vg_read;
|
||||
ios->vg_setup = _vg_setup;
|
||||
ios->vg_write = _vg_write;
|
||||
ios->destroy = _destroy;
|
||||
fi->cmd = cmd;
|
||||
fi->ops = &_format1_ops;
|
||||
fi->private = NULL;
|
||||
|
||||
ios->prefix = dbg_malloc(strlen(prefix) + 1);
|
||||
if (!ios->prefix) {
|
||||
stack;
|
||||
dbg_free(ios);
|
||||
return 0;
|
||||
}
|
||||
strcpy(ios->prefix, prefix);
|
||||
|
||||
ios->mem = mem;
|
||||
ios->filter = filter;
|
||||
ios->private = NULL;
|
||||
|
||||
return ios;
|
||||
return fi;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
struct io_space *create_lvm1_format(const char *prefix, struct pool *mem,
|
||||
struct dev_filter *filter);
|
||||
struct filter_instance *create_lvm1_format(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
@ -526,22 +526,6 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_lv_number(struct volume_group *vg, const char *name)
|
||||
{
|
||||
/* FIXME: inefficient */
|
||||
int r = 0;
|
||||
struct list *lvh;
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
struct lv_list *ll = list_item(lvh, struct lv_list);
|
||||
if (!strcmp(ll->lv.name, name))
|
||||
break;
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* This calculates the nasty pv_number and
|
||||
* lv_number fields used by LVM1. Very
|
||||
@ -549,9 +533,8 @@ static int _get_lv_number(struct volume_group *vg, const char *name)
|
||||
*/
|
||||
void export_numbers(struct list *pvs, struct volume_group *vg)
|
||||
{
|
||||
struct list *pvh, *lvh;
|
||||
struct list *pvh;
|
||||
struct disk_list *dl;
|
||||
struct lvd_list *ll;
|
||||
int pv_num = 1;
|
||||
|
||||
list_iterate(pvh, pvs) {
|
||||
|
@ -112,13 +112,11 @@ static int _alloc_simple(struct logical_volume *lv,
|
||||
allocated += _alloc_area(lv, allocated, pvm->pv, pva);
|
||||
|
||||
if (allocated == lv->le_count)
|
||||
break;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (allocated == lv->le_count) /* FIXME: yuck, repeated test */
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
if (allocated != lv->le_count) {
|
||||
log_error("Insufficient free logical extents to "
|
||||
"allocate logical volume %s: %u required",
|
||||
@ -165,13 +163,12 @@ static int _allocate(struct volume_group *vg, struct logical_volume *lv,
|
||||
vg->free_count -= lv->le_count - allocated;
|
||||
}
|
||||
|
||||
out:
|
||||
out:
|
||||
pool_destroy(scratch);
|
||||
return r;
|
||||
}
|
||||
|
||||
struct logical_volume *lv_create(struct io_space *ios,
|
||||
const char *name,
|
||||
struct logical_volume *lv_create(const char *name,
|
||||
uint32_t status,
|
||||
uint32_t stripes,
|
||||
uint32_t stripe_size,
|
||||
@ -179,6 +176,7 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
struct volume_group *vg,
|
||||
struct list *acceptable_pvs)
|
||||
{
|
||||
struct cmd_context *cmd = vg->cmd;
|
||||
struct lv_list *ll = NULL;
|
||||
struct logical_volume *lv;
|
||||
int i;
|
||||
@ -201,7 +199,7 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ll = pool_zalloc(ios->mem, sizeof(*ll)))) {
|
||||
if (!(ll = pool_zalloc(cmd->mem, sizeof(*ll)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@ -212,7 +210,7 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
|
||||
strcpy(lv->id.uuid, "");
|
||||
|
||||
if (!(lv->name = pool_strdup(ios->mem, name))) {
|
||||
if (!(lv->name = pool_strdup(cmd->mem, name))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -223,7 +221,8 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
lv->size = extents * vg->extent_size;
|
||||
lv->le_count = extents;
|
||||
|
||||
if (!(lv->map = pool_zalloc(ios->mem, sizeof(*lv->map) * extents))) {
|
||||
if (!(lv->map = pool_zalloc(cmd->mem,
|
||||
sizeof(*lv->map) * extents))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -233,9 +232,8 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (i = 0; i < lv->le_count; i++) {
|
||||
for (i = 0; i < lv->le_count; i++)
|
||||
lv->map[i].pv->pe_allocated++;
|
||||
}
|
||||
|
||||
vg->lv_count++;
|
||||
list_add(&vg->lvs, &ll->list);
|
||||
@ -243,15 +241,16 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
|
||||
return lv;
|
||||
|
||||
bad:
|
||||
bad:
|
||||
if (ll)
|
||||
pool_free(ios->mem, ll);
|
||||
pool_free(cmd->mem, ll);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lv_reduce(struct io_space *ios, struct logical_volume *lv, uint32_t extents)
|
||||
int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
{
|
||||
// FIXME: merge with Alasdair's version in tools
|
||||
if (extents % lv->stripes) {
|
||||
log_error("For a striped volume you must reduce by a "
|
||||
"multiple of the number of stripes");
|
||||
@ -269,15 +268,15 @@ int lv_reduce(struct io_space *ios, struct logical_volume *lv, uint32_t extents)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_extend(struct io_space *ios,
|
||||
struct logical_volume *lv, uint32_t extents,
|
||||
int lv_extend(struct logical_volume *lv, uint32_t extents,
|
||||
struct list *acceptable_pvs)
|
||||
{
|
||||
struct cmd_context *cmd = lv->vg->cmd;
|
||||
struct pe_specifier *new_map;
|
||||
struct logical_volume *new_lv;
|
||||
int i;
|
||||
|
||||
if (!(new_map = pool_zalloc(ios->mem, sizeof(*new_map) *
|
||||
if (!(new_map = pool_zalloc(cmd->mem, sizeof(*new_map) *
|
||||
(extents + lv->le_count)))) {
|
||||
stack;
|
||||
return 0;
|
||||
@ -285,8 +284,8 @@ int lv_extend(struct io_space *ios,
|
||||
|
||||
memcpy(new_map, lv->map, sizeof(*new_map) * lv->le_count);
|
||||
|
||||
if (!(new_lv = pool_alloc(ios->mem, sizeof(*new_lv)))) {
|
||||
pool_free(ios->mem, new_map);
|
||||
if (!(new_lv = pool_alloc(cmd->mem, sizeof(*new_lv)))) {
|
||||
pool_free(cmd->mem, new_map);
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@ -300,17 +299,20 @@ int lv_extend(struct io_space *ios,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (i = lv->le_count; i < new_lv->le_count; i++) {
|
||||
for (i = lv->le_count; i < new_lv->le_count; i++)
|
||||
new_lv->map[i].pv->pe_allocated++;
|
||||
}
|
||||
|
||||
memcpy(lv, new_lv, sizeof(*lv));
|
||||
|
||||
/* now you see why new_lv had to be allocated last */
|
||||
pool_free(ios->mem, new_lv);
|
||||
/*
|
||||
* new_lv had to be allocated last so we
|
||||
* could free it without touching the new
|
||||
* map
|
||||
*/
|
||||
pool_free(cmd->mem, new_lv);
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
pool_free(ios->mem, new_map);
|
||||
bad:
|
||||
pool_free(cmd->mem, new_map);
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,21 +12,22 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
int _add_pv_to_vg(struct format_instance *fi, struct volume_group *vg,
|
||||
const char *pv_name)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
struct pool *mem = fi->cmd->mem;
|
||||
|
||||
log_verbose("Adding physical volume '%s' to volume group '%s'",
|
||||
pv_name, vg->name);
|
||||
|
||||
if (!(pvl = pool_alloc(ios->mem, sizeof (*pvl)))) {
|
||||
if (!(pvl = pool_alloc(mem, sizeof (*pvl)))) {
|
||||
log_error("pv_list allocation for '%s' failed", pv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pv = ios->pv_read(ios, pv_name))) {
|
||||
if (!(pv = fi->ops->pv_read(fi, pv_name))) {
|
||||
log_error("Failed to read existing physical volume '%s'",
|
||||
pv_name);
|
||||
return 0;
|
||||
@ -44,7 +45,7 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
/* FIXME check this */
|
||||
pv->exported = NULL;
|
||||
|
||||
if (!(pv->vg_name = pool_strdup(ios->mem, vg->name))) {
|
||||
if (!(pv->vg_name = pool_strdup(mem, vg->name))) {
|
||||
log_error("vg->name allocation failed for '%s'", pv_name);
|
||||
return 0;
|
||||
}
|
||||
@ -63,14 +64,14 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
|
||||
/*
|
||||
* The next two fields should be corrected
|
||||
* by ios->pv_setup.
|
||||
* by fi->pv_setup.
|
||||
*/
|
||||
pv->pe_start = 0;
|
||||
pv->pe_count = pv->size / pv->pe_size;
|
||||
|
||||
pv->pe_allocated = 0;
|
||||
|
||||
if (!ios->pv_setup(ios, pv, vg)) {
|
||||
if (!fi->ops->pv_setup(fi, pv, vg)) {
|
||||
log_debug("Format-specific setup of physical volume '%s' "
|
||||
"failed.", pv_name);
|
||||
return 0;
|
||||
@ -89,7 +90,7 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pvl->pv, pv, sizeof (struct physical_volume));
|
||||
memcpy(&pvl->pv, pv, sizeof(*pv));
|
||||
|
||||
list_add(&vg->pvs, &pvl->list);
|
||||
vg->pv_count++;
|
||||
@ -99,14 +100,14 @@ int _add_pv_to_vg(struct io_space *ios, struct volume_group *vg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vg_extend(struct io_space *ios, struct volume_group *vg, int pv_count,
|
||||
char **pv_names)
|
||||
int vg_extend(struct format_instance *fi,
|
||||
struct volume_group *vg, int pv_count, char **pv_names)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* attach each pv */
|
||||
for (i = 0; i < pv_count; i++)
|
||||
if (!_add_pv_to_vg(ios, vg, pv_names[i])) {
|
||||
if (!_add_pv_to_vg(fi, vg, pv_names[i])) {
|
||||
log_error("Unable to add physical volume '%s' to "
|
||||
"volume group '%s'.", pv_names[i], vg->name);
|
||||
return 0;
|
||||
@ -115,33 +116,43 @@ int vg_extend(struct io_space *ios, struct volume_group *vg, int pv_count,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct volume_group *vg_create(struct io_space *ios, const char *vg_name,
|
||||
const char *strip_prefix(const char *vg_name, const char *dev_dir)
|
||||
{
|
||||
int len = strlen(dev_dir);
|
||||
if (!strncmp(vg_name, dev_dir, len))
|
||||
vg_name += len;
|
||||
|
||||
return vg_name;
|
||||
}
|
||||
|
||||
struct volume_group *vg_create(struct format_instance *fi, const char *vg_name,
|
||||
uint32_t extent_size, int max_pv, int max_lv,
|
||||
int pv_count, char **pv_names)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct pool *mem = fi->cmd->mem;
|
||||
|
||||
if (!(vg = pool_alloc(ios->mem, sizeof (*vg)))) {
|
||||
if (!(vg = pool_alloc(mem, sizeof (*vg)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* is this vg name already in use ? */
|
||||
if (ios->vg_read(ios, vg_name)) {
|
||||
if (fi->ops->vg_read(fi, vg_name)) {
|
||||
log_err("A volume group called '%s' already exists.", vg_name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!id_create(&vg->id)) {
|
||||
log_err("Couldn't create uuid for volume group '%s'.", vg_name);
|
||||
log_err("Couldn't create uuid for volume group '%s'.",
|
||||
vg_name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Strip prefix if present */
|
||||
if (!strncmp(vg_name, ios->prefix, strlen(ios->prefix)))
|
||||
vg_name += strlen(ios->prefix);
|
||||
vg_name = strip_dir(vg_name, fi->cmd->dev_dir);
|
||||
|
||||
if (!(vg->name = pool_strdup(ios->mem, vg_name))) {
|
||||
if (!(vg->name = pool_strdup(mem, vg_name))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -161,26 +172,27 @@ struct volume_group *vg_create(struct io_space *ios, const char *vg_name,
|
||||
vg->lv_count = 0;
|
||||
list_init(&vg->lvs);
|
||||
|
||||
if (!ios->vg_setup(ios, vg)) {
|
||||
if (!fi->ops->vg_setup(fi, vg)) {
|
||||
log_error("Format specific setup of volume group '%s' failed.",
|
||||
vg_name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* attach the pv's */
|
||||
if (!vg_extend(ios, vg, pv_count, pv_names))
|
||||
if (!vg_extend(fi, vg, pv_count, pv_names))
|
||||
goto bad;
|
||||
|
||||
return vg;
|
||||
|
||||
bad:
|
||||
pool_free(ios->mem, vg);
|
||||
bad:
|
||||
pool_free(mem, vg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct physical_volume *pv_create(struct io_space *ios, const char *name)
|
||||
struct physical_volume *pv_create(struct format_instance *fi, const char *name)
|
||||
{
|
||||
struct physical_volume *pv = pool_alloc(ios->mem, sizeof (*pv));
|
||||
struct pool *mem = fi->cmd->mem;
|
||||
struct physical_volume *pv = pool_alloc(mem, sizeof (*pv));
|
||||
|
||||
if (!pv) {
|
||||
stack;
|
||||
@ -188,12 +200,12 @@ struct physical_volume *pv_create(struct io_space *ios, const char *name)
|
||||
}
|
||||
|
||||
id_create(&pv->id);
|
||||
if (!(pv->dev = dev_cache_get(name, ios->filter))) {
|
||||
if (!(pv->dev = dev_cache_get(name, fi->cmd->filter))) {
|
||||
log_err("Couldn't find device '%s'", name);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(pv->vg_name = pool_alloc(ios->mem, NAME_LEN))) {
|
||||
if (!(pv->vg_name = pool_alloc(mem, NAME_LEN))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@ -214,7 +226,7 @@ struct physical_volume *pv_create(struct io_space *ios, const char *name)
|
||||
return pv;
|
||||
|
||||
bad:
|
||||
pool_free(ios->mem, pv);
|
||||
pool_free(mem, pv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,11 @@ struct pe_specifier {
|
||||
uint32_t pe;
|
||||
};
|
||||
|
||||
struct cmd_context;
|
||||
|
||||
struct volume_group {
|
||||
struct cmd_context *cmd;
|
||||
|
||||
struct id id;
|
||||
char *name;
|
||||
|
||||
@ -119,101 +123,114 @@ struct lv_list {
|
||||
struct logical_volume lv;
|
||||
};
|
||||
|
||||
struct cmd_context {
|
||||
/* format handler allocates all objects from here */
|
||||
struct pool *mem;
|
||||
|
||||
/* misc. vars needed by format handler */
|
||||
char *dev_dir;
|
||||
struct dev_filter *filter;
|
||||
};
|
||||
|
||||
struct format_instance {
|
||||
struct cmd_context *cmd;
|
||||
struct format_handler *ops;
|
||||
void *private;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Ownership of objects passes to caller.
|
||||
*/
|
||||
struct io_space {
|
||||
struct format_handler {
|
||||
/*
|
||||
* Returns a name_list of vg's.
|
||||
*/
|
||||
struct list *(*get_vgs)(struct io_space *is);
|
||||
struct list *(*get_vgs)(struct format_instance *fi);
|
||||
|
||||
/*
|
||||
* Returns pv_list of fully-populated pv structures.
|
||||
*/
|
||||
struct list *(*get_pvs)(struct io_space *is);
|
||||
struct list *(*get_pvs)(struct format_instance *fi);
|
||||
|
||||
/*
|
||||
* Return PV with given path.
|
||||
*/
|
||||
struct physical_volume *(*pv_read)(struct io_space *is,
|
||||
struct physical_volume *(*pv_read)(struct format_instance *fi,
|
||||
const char *pv_name);
|
||||
|
||||
/*
|
||||
* Tweak an already filled out a pv ready
|
||||
* for importing into a vg. eg. pe_count
|
||||
* is format specific.
|
||||
* Tweak an already filled out a pv ready for importing into a
|
||||
* vg. eg. pe_count is format specific.
|
||||
*/
|
||||
int (*pv_setup)(struct io_space *is, struct physical_volume *pv,
|
||||
int (*pv_setup)(struct format_instance *fi, struct physical_volume *pv,
|
||||
struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Write a PV structure to disk. Fails if
|
||||
* the PV is in a VG ie pv->vg_name must
|
||||
* be null.
|
||||
* Write a PV structure to disk. Fails if the PV is in a VG ie
|
||||
* pv->vg_name must be null.
|
||||
*/
|
||||
int (*pv_write)(struct io_space *is, struct physical_volume *pv);
|
||||
int (*pv_write)(struct format_instance *fi,
|
||||
struct physical_volume *pv);
|
||||
|
||||
/*
|
||||
* Tweak an already filled out vg. eg,
|
||||
* max_pv is format specific.
|
||||
* Tweak an already filled out vg. eg, max_pv is format
|
||||
* specific.
|
||||
*/
|
||||
int (*vg_setup)(struct io_space *is, struct volume_group *vg);
|
||||
int (*vg_setup)(struct format_instance *fi, struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* If vg_name doesn't contain any slash,
|
||||
* this function adds prefix.
|
||||
* The name may be prefixed with the dev_dir from the
|
||||
* job_context.
|
||||
*/
|
||||
struct volume_group *(*vg_read)(struct io_space *is,
|
||||
struct volume_group *(*vg_read)(struct format_instance *fi,
|
||||
const char *vg_name);
|
||||
|
||||
/*
|
||||
* Write out complete VG metadata. Ensure
|
||||
* *internal* consistency before writing
|
||||
* anything. eg. PEs can't refer to PVs
|
||||
* not part of the VG. Order write sequence
|
||||
* to aid recovery if process is aborted
|
||||
* (eg flush entire set of changes to each
|
||||
* disk in turn) It is the responsibility
|
||||
* of the caller to ensure external
|
||||
* consistency, eg by calling pv_write()
|
||||
* if removing PVs from a VG or calling
|
||||
* vg_write() a second time if splitting a
|
||||
* VG into two. vg_write() must not read
|
||||
* or write from any PVs not included in
|
||||
* the volume_group structure it is
|
||||
* handed.
|
||||
* Write out complete VG metadata. You must ensure internal
|
||||
* consistency before calling. eg. PEs can't refer to PVs not
|
||||
* part of the VG.
|
||||
*
|
||||
* It is also the responsibility of the caller to ensure external
|
||||
* consistency, eg by calling pv_write() if removing PVs from
|
||||
* a VG or calling vg_write() a second time if splitting a VG
|
||||
* into two.
|
||||
*
|
||||
* vg_write() must not read or write from any PVs not included
|
||||
* in the volume_group structure it is handed. Note: format1
|
||||
* does read all pv's currently.
|
||||
*/
|
||||
int (*vg_write)(struct io_space *is, struct volume_group *vg);
|
||||
int (*vg_write)(struct format_instance *fi, struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Destructor for this object.
|
||||
*/
|
||||
void (*destroy)(struct io_space *is);
|
||||
|
||||
/*
|
||||
* Current volume group prefix.
|
||||
*/
|
||||
char *prefix;
|
||||
struct pool *mem;
|
||||
struct dev_filter *filter;
|
||||
void *private;
|
||||
void (*destroy)(struct format_instance *fi);
|
||||
};
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
struct volume_group *vg_create(struct io_space *ios, const char *name,
|
||||
struct physical_volume *pv_create(struct format_instance *fi,
|
||||
const char *name);
|
||||
|
||||
struct volume_group *vg_create(struct format_instance *fi, const char *name,
|
||||
uint32_t extent_size, int max_pv, int max_lv,
|
||||
int pv_count, char **pv_names);
|
||||
struct physical_volume *pv_create(struct io_space *ios, const char *name);
|
||||
|
||||
/*
|
||||
* This needs the format instance to check the
|
||||
* pv's are orphaned.
|
||||
*/
|
||||
int vg_extend(struct format_instance *fi,
|
||||
struct volume_group *vg, int pv_count, char **pv_names);
|
||||
|
||||
|
||||
/*
|
||||
* Create a new LV within a given volume group.
|
||||
*
|
||||
*/
|
||||
struct logical_volume *lv_create(struct io_space *ios,
|
||||
const char *name,
|
||||
struct logical_volume *lv_create(const char *name,
|
||||
uint32_t status,
|
||||
uint32_t stripes,
|
||||
uint32_t stripe_size,
|
||||
@ -221,30 +238,15 @@ struct logical_volume *lv_create(struct io_space *ios,
|
||||
struct volume_group *vg,
|
||||
struct list *acceptable_pvs);
|
||||
|
||||
int lv_reduce(struct io_space *ios,
|
||||
struct logical_volume *lv,
|
||||
uint32_t extents);
|
||||
int lv_reduce(struct logical_volume *lv, uint32_t extents);
|
||||
|
||||
int lv_extend(struct io_space *ios, struct logical_volume *lv,
|
||||
int lv_extend(struct logical_volume *lv,
|
||||
uint32_t extents, struct list *allocatable_pvs);
|
||||
|
||||
|
||||
int vg_extend(struct io_space *ios, struct volume_group *vg, int pv_count,
|
||||
char **pv_names);
|
||||
|
||||
|
||||
|
||||
/* FIXME: Move to other files */
|
||||
struct io_space *create_text_format(struct dev_filter *filter,
|
||||
const char *text_file);
|
||||
|
||||
int id_eq(struct id *op1, struct id *op2);
|
||||
|
||||
/* Create consistent new empty structures, populated with defaults */
|
||||
struct volume_group *vg_create();
|
||||
|
||||
int vg_destroy(struct volume_group *vg);
|
||||
|
||||
/* Manipulate PV structures */
|
||||
int pv_add(struct volume_group *vg, struct physical_volume *pv);
|
||||
int pv_remove(struct volume_group *vg, struct physical_volume *pv);
|
||||
@ -269,5 +271,9 @@ struct volume_group *find_vg_with_lv(const char *lv_name);
|
||||
struct physical_volume *_find_pv(struct volume_group *vg, struct device *dev);
|
||||
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
|
||||
|
||||
/*
|
||||
* Remove a prefix directory if present.
|
||||
*/
|
||||
const char *strip_dir(const char *vg_name, const char *dir);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user