1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +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, int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir); 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); int export_uuids(struct disk_list *dl, struct volume_group *vg);
void export_numbers(struct list *pvds, 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; 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 volume_group *vg = pool_alloc(mem, sizeof(*vg));
struct disk_list *dl; struct disk_list *dl;
int partial; int partial;
@ -96,8 +98,10 @@ static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
memset(vg, 0, sizeof(*vg)); memset(vg, 0, sizeof(*vg));
vg->cmd = cmd;
list_init(&vg->pvs); list_init(&vg->pvs);
list_init(&vg->lvs); list_init(&vg->lvs);
list_init(&vg->snapshots);
if (!_check_vgs(pvs, &partial)) if (!_check_vgs(pvs, &partial))
goto bad; goto bad;
@ -116,6 +120,9 @@ static struct volume_group *_build_vg(struct pool *mem, struct list *pvs)
if (!import_extents(mem, vg, pvs)) if (!import_extents(mem, vg, pvs))
goto bad; goto bad;
if (!import_snapshots(mem, vg, pvs))
goto bad;
return vg; return vg;
bad: bad:
@ -145,13 +152,11 @@ static struct volume_group *_vg_read(struct format_instance *fi,
goto bad; goto bad;
} }
if (!(vg = _build_vg(fi->cmd->mem, &pvs))) { if (!(vg = _build_vg(fi->cmd, &pvs))) {
stack; stack;
goto bad; goto bad;
} }
vg->cmd = fi->cmd;
bad: bad:
pool_destroy(mem); pool_destroy(mem);
return vg; 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) if (lvd->lv_access & LV_WRITE)
lv->status |= LVM_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) if (lvd->lv_badblock)
lv->status |= BADBLOCK_ON; lv->status |= BADBLOCK_ON;
@ -336,12 +330,6 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
if (lv->status & LVM_WRITE) if (lv->status & LVM_WRITE)
lvd->lv_access |= LV_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) if (lv->status & SPINDOWN_LV)
lvd->lv_status |= LV_SPINDOWN; lvd->lv_status |= LV_SPINDOWN;
@ -478,13 +466,21 @@ int import_lvs(struct pool *mem, struct volume_group *vg,
return 1; return 1;
} }
/* FIXME: tidy */
int export_lvs(struct disk_list *dl, struct volume_group *vg, int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir) struct physical_volume *pv, const char *dev_dir)
{ {
struct list *lvh; int r = 0;
struct list *lvh, *sh;
struct lv_list *ll; struct lv_list *ll;
struct lvd_list *lvdl; struct lvd_list *lvdl;
int lv_num = 0, len; 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 * 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; len = sizeof(struct pe_disk) * dl->pvd.pe_total;
if (!(dl->extents = pool_alloc(dl->mem, len))) { if (!(dl->extents = pool_alloc(dl->mem, len))) {
stack; stack;
return 0; goto out;
} }
memset(dl->extents, 0, len); memset(dl->extents, 0, len);
list_iterate (lvh, &vg->lvs) { list_iterate (lvh, &vg->lvs) {
ll = list_item(lvh, struct lv_list); ll = list_item(lvh, struct lv_list);
if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) { if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) {
stack; stack;
return 0; goto out;
} }
export_lv(&lvdl->lvd, vg, ll->lv, dev_dir); 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; 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)) { if (!export_extents(dl, lv_num + 1, ll->lv, pv)) {
stack; stack;
return 0; goto out;
} }
list_add(&dl->lvds, &lvdl->list); list_add(&dl->lvds, &lvdl->list);
dl->pvd.lv_cur++; dl->pvd.lv_cur++;
lv_num++; 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; return 1;
} }
int export_uuids(struct disk_list *dl, struct volume_group *vg) int export_uuids(struct disk_list *dl, struct volume_group *vg)
{ {
struct uuid_list *ul; struct uuid_list *ul;

View File

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

View File

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

View File

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

View File

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

View File

@ -44,7 +44,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
return ECMD_FAILED; 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", log_error("Can't remove logical volume \"%s\" under snapshot",
lv->name); lv->name);
return ECMD_FAILED; return ECMD_FAILED;

View File

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