1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

o First pass at format1 snapshot support.

This commit is contained in:
Joe Thornber 2002-02-13 11:43:29 +00:00
parent 7d68b08028
commit 0a9f8bcf97
9 changed files with 146 additions and 33 deletions

View File

@ -230,6 +230,9 @@ int import_lvs(struct pool *mem, struct volume_group *vg,
int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir);
int import_snapshots(struct pool *mem, struct volume_group *vg,
struct list *pvds);
int export_uuids(struct disk_list *dl, struct volume_group *vg);
void export_numbers(struct list *pvds, struct volume_group *vg);

View File

@ -82,8 +82,10 @@ static int _check_vgs(struct list *pvs, int *partial)
return 1;
}
static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
static struct volume_group *_build_vg(struct cmd_context *cmd,
struct list *pvs)
{
struct pool *mem = cmd->mem;
struct volume_group *vg = pool_alloc(mem, sizeof(*vg));
struct disk_list *dl;
int partial;
@ -96,8 +98,10 @@ static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
memset(vg, 0, sizeof(*vg));
vg->cmd = cmd;
list_init(&vg->pvs);
list_init(&vg->lvs);
list_init(&vg->snapshots);
if (!_check_vgs(pvs, &partial))
goto bad;
@ -116,6 +120,9 @@ static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
if (!import_extents(mem, vg, pvs))
goto bad;
if (!import_snapshots(mem, vg, pvs))
goto bad;
return vg;
bad:
@ -145,13 +152,11 @@ static struct volume_group *_vg_read(struct format_instance *fi,
goto bad;
}
if (!(vg = _build_vg(fi->cmd->mem, &pvs))) {
if (!(vg = _build_vg(fi->cmd, &pvs))) {
stack;
goto bad;
}
vg->cmd = fi->cmd;
bad:
pool_destroy(mem);
return vg;

View File

@ -293,12 +293,6 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
if (lvd->lv_access & LV_WRITE)
lv->status |= LVM_WRITE;
if (lvd->lv_access & LV_SNAPSHOT)
lv->status |= SNAPSHOT;
if (lvd->lv_access & LV_SNAPSHOT_ORG)
lv->status |= SNAPSHOT_ORG;
if (lvd->lv_badblock)
lv->status |= BADBLOCK_ON;
@ -336,12 +330,6 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
if (lv->status & LVM_WRITE)
lvd->lv_access |= LV_WRITE;
if (lv->status & SNAPSHOT)
lvd->lv_access |= LV_SNAPSHOT;
if (lv->status & SNAPSHOT_ORG)
lvd->lv_access |= LV_SNAPSHOT_ORG;
if (lv->status & SPINDOWN_LV)
lvd->lv_status |= LV_SPINDOWN;
@ -478,13 +466,21 @@ int import_lvs(struct pool *mem, struct volume_group *vg,
return 1;
}
/* FIXME: tidy */
int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir)
{
struct list *lvh;
int r = 0;
struct list *lvh, *sh;
struct lv_list *ll;
struct lvd_list *lvdl;
int lv_num = 0, len;
struct hash_table *lvd_hash;
if (!(lvd_hash = hash_create(32))) {
stack;
return 0;
}
/*
* setup the pv's extents array
@ -492,32 +488,146 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
if (!(dl->extents = pool_alloc(dl->mem, len))) {
stack;
return 0;
goto out;
}
memset(dl->extents, 0, len);
list_iterate(lvh, &vg->lvs) {
list_iterate (lvh, &vg->lvs) {
ll = list_item(lvh, struct lv_list);
if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) {
stack;
return 0;
goto out;
}
export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
/* this isn't a real dev, more of an index for
* snapshots to refer to, *HACK* */
lvdl->lvd.lv_dev = MKDEV(0, lv_num);
lvdl->lvd.lv_number = lv_num;
if (!hash_insert(lvd_hash, lvdl->lvd.lv_name, &lvdl->lvd)) {
stack;
goto out;
}
if (!export_extents(dl, lv_num + 1, ll->lv, pv)) {
stack;
return 0;
goto out;
}
list_add(&dl->lvds, &lvdl->list);
dl->pvd.lv_cur++;
lv_num++;
}
/*
* Now we need to run through the snapshots, exporting
* the SNAPSHOT_ORG flags etc.
*/
list_iterate (sh, &vg->snapshots) {
struct lv_disk *org, *cow;
struct snapshot *s = list_item(sh,
struct snapshot_list)->snapshot;
if (!(org = hash_lookup(lvd_hash, s->origin->name))) {
stack;
goto out;
}
if (!(cow = hash_lookup(lvd_hash, s->cow->name))) {
stack;
goto out;
}
org->lv_access |= LV_SNAPSHOT_ORG;
cow->lv_access |= LV_SNAPSHOT;
cow->lv_snapshot_minor = MINOR(org->lv_dev);
}
r = 1;
out:
hash_destroy(lvd_hash);
return r;
}
/*
* FIXME: More inefficient code.
*/
int import_snapshots(struct pool *mem, struct volume_group *vg,
struct list *pvds)
{
struct logical_volume *lvs[MAX_LV];
struct list *pvdh, *lvdh;
struct disk_list *dl;
struct lv_disk *lvd;
int minor;
struct logical_volume *org, *cow;
/* build an array of minor->lv* */
memset(lvs, 0, sizeof(lvs));
list_iterate (pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate (lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
minor = MINOR(lvd->lv_dev);
if (minor > MAX_LV) {
log_err("Logical volume minor number "
"out of bounds.");
return 0;
}
if (!lvs[minor] &&
!(lvs[minor] = find_lv(vg, lvd->lv_name))) {
log_err("Couldn't find logical volume '%s'.",
lvd->lv_name);
return 0;
}
}
}
/*
* Now iterate through yet again adding the snapshots.
*/
list_iterate (pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate (lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
if (!(lvd->lv_status & LV_SNAPSHOT))
continue;
minor = MINOR(lvd->lv_dev);
cow = lvs[minor];
if (!(org = lvs[lvd->lv_snapshot_minor])) {
log_err("Couldn't find origin logical volume "
"for snapshot '%s'.", lvd->lv_name);
return 0;
}
/* we may have already added this snapshot */
if (lv_is_cow(vg, cow))
continue;
/* insert the snapshot */
if (!vg_add_snapshot(vg, org, cow, 1,
lvd->lv_chunk_size)) {
log_err("Couldn't add snapshot.");
return 0;
}
}
}
return 1;
}
int export_uuids(struct disk_list *dl, struct volume_group *vg)
{
struct uuid_list *ul;

View File

@ -41,8 +41,6 @@ static struct flag _lv_flags[] = {
{ALLOC_SIMPLE, "ALLOC_SIMPLE"},
{ALLOC_STRICT, "ALLOC_STRICT"},
{ALLOC_CONTIGUOUS, "ALLOC_CONTIGUOUS"},
{SNAPSHOT, "SNASHOT"},
{SNAPSHOT_ORG, "SNAPSHOT_ORIGIN"},
{FIXED_MINOR, "FIXED_MINOR"},
{0, NULL}
};

View File

@ -50,9 +50,6 @@
#define ALLOC_STRICT 0x00002000 /* LV */
#define ALLOC_CONTIGUOUS 0x00004000 /* LV */
#define SNAPSHOT 0x00010000 /* LV */
#define SNAPSHOT_ORG 0x00020000 /* LV */
struct physical_volume {
struct id id;

View File

@ -91,6 +91,6 @@ int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow)
}
/* fail */
log_err("Asked to remove an unknow snapshot.");
log_err("Asked to remove an unknown snapshot.");
return 0;
}

View File

@ -67,13 +67,13 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv)
return EINVALID_CMD_LINE;
}
if (lv->status & SNAPSHOT_ORG) {
if (lv_is_origin(lv->vg, lv)) {
log_error("Can't change logical volume \"%s\" under snapshot",
lv->name);
return ECMD_FAILED;
}
if (lv->status & SNAPSHOT) {
if (lv_is_cow(lv->vg, lv)) {
log_error("Can't change snapshot logical volume \"%s\"",
lv->name);
return ECMD_FAILED;

View File

@ -44,7 +44,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
return ECMD_FAILED;
}
if (lv->status & SNAPSHOT_ORG) {
if (lv_is_origin(lv->vg, lv)) {
log_error("Can't remove logical volume \"%s\" under snapshot",
lv->name);
return ECMD_FAILED;

View File

@ -70,9 +70,9 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv)
} else
active_str = "inactive ";
if (lv->status & SNAPSHOT_ORG)
if (lv_is_origin(lv->vg, lv))
snapshot_str = "Original";
else if (lv->status & SNAPSHOT)
else if (lv_is_cow(lv->vg, lv))
snapshot_str = "Snapshot";
else
snapshot_str = " ";