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

Add snapshot merge wrappers to abstract the associations and flags used

to represent merging origin and snapshot volumes.
This commit is contained in:
Mike Snitzer 2010-01-13 01:55:43 +00:00
parent a39ac3e11b
commit c79b425135
9 changed files with 64 additions and 35 deletions

View File

@ -754,7 +754,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
* In case of a snapshot device, we monitor lv->snapshot->lv,
* not the actual LV itself.
*/
if (lv_is_cow(lv) && !(find_cow(lv)->status & SNAPSHOT_MERGE))
if (lv_is_cow(lv) && !lv_is_merging_cow(lv))
return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
/*

View File

@ -947,19 +947,20 @@ static int _add_snapshot_merge_target_to_dtree(struct dev_manager *dm,
struct logical_volume *lv)
{
const char *origin_dlid, *cow_dlid, *merge_dlid;
struct lv_segment *merging_cow_seg = find_merging_cow(lv);
if (!(origin_dlid = build_dlid(dm, lv->lvid.s, "real")))
return_0;
if (!(cow_dlid = build_dlid(dm, lv->merging_snapshot->cow->lvid.s, "cow")))
if (!(cow_dlid = build_dlid(dm, merging_cow_seg->cow->lvid.s, "cow")))
return_0;
if (!(merge_dlid = build_dlid(dm, lv->merging_snapshot->cow->lvid.s, NULL)))
if (!(merge_dlid = build_dlid(dm, merging_cow_seg->cow->lvid.s, NULL)))
return_0;
if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid,
cow_dlid, merge_dlid,
lv->merging_snapshot->chunk_size))
merging_cow_seg->chunk_size))
return_0;
return 1;
@ -979,7 +980,8 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
return 0;
}
if (snap_seg->status & SNAPSHOT_MERGE)
/* cow is to be merged so skip adding it */
if (lv_is_merging_cow(lv))
return 1;
if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real")))
@ -1055,9 +1057,9 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
log_error("Clustered snapshots are not yet supported");
return 0;
}
if (seg->lv->merging_snapshot) {
if (lv_is_merging_origin(seg->lv)) {
if (!_add_new_lv_to_dtree(dm, dtree,
seg->lv->merging_snapshot->cow, "cow"))
find_merging_cow(seg->lv)->cow, "cow"))
return_0;
/*
* Must also add "real" LV for use when
@ -1080,7 +1082,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
/* Now we've added its dependencies, we can add the target itself */
if (lv_is_origin(seg->lv) && !layer) {
if (!seg->lv->merging_snapshot) {
if (!lv_is_merging_origin(seg->lv)) {
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
return_0;
} else {
@ -1115,7 +1117,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
uint32_t read_ahead_flags = UINT32_C(0);
uint16_t udev_flags = 0;
if (lv_is_origin(lv) && lv->merging_snapshot && !layer) {
if (lv_is_origin(lv) && lv_is_merging_origin(lv) && !layer) {
/*
* Clear merge attributes if merge isn't currently possible:
* either origin or merging snapshot are open
@ -1125,18 +1127,15 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
*/
if ((dev_manager_info(dm->mem, NULL, lv,
0, 1, 0, &dinfo, NULL) && dinfo.open_count) ||
(dev_manager_info(dm->mem, NULL, lv->merging_snapshot->cow,
(dev_manager_info(dm->mem, NULL, find_merging_cow(lv)->cow,
0, 1, 0, &dinfo, NULL) && dinfo.open_count)) {
if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge")) {
/* clear merge attributes */
lv->merging_snapshot->status &= ~SNAPSHOT_MERGE;
lv->merging_snapshot = NULL;
}
if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge"))
clear_snapshot_merge(lv);
}
}
lv_name = lv->name;
if (lv_is_cow(lv) && find_cow(lv)->status & SNAPSHOT_MERGE) {
if (lv_is_cow(lv) && lv_is_merging_cow(lv)) {
if (layer) {
/*
* use origin's name as basis for snapshot-merge device names;

View File

@ -2127,7 +2127,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
if (lv_is_cow(lv)) {
origin = origin_from_cow(lv);
was_merging = !!origin->merging_snapshot;
was_merging = lv_is_merging_origin(origin);
log_verbose("Removing snapshot %s", lv->name);
if (!vg_remove_snapshot(lv))
return_0;
@ -2953,7 +2953,7 @@ int lv_create_single(struct volume_group *vg,
"supported yet");
return 0;
}
if (org->merging_snapshot) {
if (lv_is_merging_origin(org)) {
log_error("Snapshots of an origin that has a "
"merging snapshot is not supported");
return 0;

View File

@ -616,12 +616,16 @@ struct lv_segment *first_seg(const struct logical_volume *lv);
int lv_is_origin(const struct logical_volume *lv);
int lv_is_virtual_origin(const struct logical_volume *lv);
int lv_is_cow(const struct logical_volume *lv);
int lv_is_merging_origin(const struct logical_volume *origin);
int lv_is_merging_cow(const struct logical_volume *snapshot);
/* Test if given LV is visible from user's perspective */
int lv_is_visible(const struct logical_volume *lv);
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
struct lv_segment *find_merging_cow(const struct logical_volume *origin);
/* Given a cow LV, return return the snapshot lv_segment that uses it */
struct lv_segment *find_cow(const struct logical_volume *lv);
@ -633,6 +637,8 @@ void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
void init_snapshot_merge(struct lv_segment *cow_seg, struct logical_volume *origin);
void clear_snapshot_merge(struct logical_volume *origin);
int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
union lvid *lvid, uint32_t extent_count,
uint32_t chunk_size);

View File

@ -37,7 +37,7 @@ int lv_is_visible(const struct logical_volume *lv)
if (lv_is_virtual_origin(origin_from_cow(lv)))
return 1;
if (find_cow(lv)->status & SNAPSHOT_MERGE)
if (lv_is_merging_cow(lv))
return 0;
return lv_is_visible(origin_from_cow(lv));
@ -51,6 +51,21 @@ int lv_is_virtual_origin(const struct logical_volume *lv)
return (lv->status & VIRTUAL_ORIGIN) ? 1 : 0;
}
int lv_is_merging_origin(const struct logical_volume *origin)
{
return origin->merging_snapshot ? 1 : 0;
}
struct lv_segment *find_merging_cow(const struct logical_volume *origin)
{
return origin->merging_snapshot;
}
int lv_is_merging_cow(const struct logical_volume *snapshot)
{
/* NOTE: use of find_cow() rather than find_merging_cow() */
return (find_cow(snapshot)->status & SNAPSHOT_MERGE) ? 1 : 0;
}
/* Given a cow LV, return the snapshot lv_segment that uses it */
struct lv_segment *find_cow(const struct logical_volume *lv)
@ -106,6 +121,13 @@ void init_snapshot_merge(struct lv_segment *cow_seg,
origin->merging_snapshot = cow_seg;
}
void clear_snapshot_merge(struct logical_volume *origin)
{
/* clear merge attributes */
origin->merging_snapshot->status &= ~SNAPSHOT_MERGE;
origin->merging_snapshot = NULL;
}
int vg_add_snapshot(struct logical_volume *origin,
struct logical_volume *cow, union lvid *lvid,
uint32_t extent_count, uint32_t chunk_size)
@ -143,10 +165,12 @@ int vg_add_snapshot(struct logical_volume *origin,
int vg_remove_snapshot(struct logical_volume *cow)
{
struct logical_volume *origin = origin_from_cow(cow);
dm_list_del(&cow->snapshot->origin_list);
cow->snapshot->origin->origin_count--;
if (cow->snapshot->origin->merging_snapshot == cow->snapshot)
cow->snapshot->origin->merging_snapshot = NULL;
origin->origin_count--;
if (find_merging_cow(origin) == find_cow(cow))
clear_snapshot_merge(origin_from_cow(cow));
if (!lv_remove(cow->snapshot->lv)) {
log_error("Failed to remove internal snapshot LV %s",

View File

@ -306,7 +306,7 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
repstr[0] = 'v';
/* Origin takes precedence over Mirror */
else if (lv_is_origin(lv)) {
if (lv->merging_snapshot)
if (lv_is_merging_origin(lv))
repstr[0] = 'O';
else
repstr[0] = 'o';
@ -324,7 +324,7 @@ static int _lvstatus_disp(struct dm_report *rh __attribute((unused)), struct dm_
else if (lv->status & MIRROR_LOG)
repstr[0] = 'l';
else if (lv_is_cow(lv)) {
if (find_cow(lv)->status & SNAPSHOT_MERGE)
if (lv_is_merging_cow(lv))
repstr[0] = 'S';
else
repstr[0] = 's';
@ -1023,7 +1023,7 @@ static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm
return 0;
}
if ((!lv_is_cow(lv) && !lv->merging_snapshot) ||
if ((!lv_is_cow(lv) && !lv_is_merging_origin(lv)) ||
(lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists)) {
*sortval = UINT64_C(0);
dm_report_field_set_value(field, "", sortval);
@ -1032,7 +1032,7 @@ static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm
if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
(percent_range == PERCENT_INVALID)) {
if (!lv->merging_snapshot) {
if (!lv_is_merging_origin(lv)) {
*sortval = UINT64_C(100);
dm_report_field_set_value(field, "100.00", sortval);
} else {

View File

@ -377,7 +377,7 @@ static int _finish_lvconvert_merge(struct cmd_context *cmd,
struct logical_volume *lv,
struct dm_list *lvs_changed __attribute((unused)))
{
struct lv_segment *snap_seg = lv->merging_snapshot;
struct lv_segment *snap_seg = find_merging_cow(lv);
if (!snap_seg) {
log_error("Logical volume %s has no merging snapshot.", lv->name);
return 0;
@ -450,7 +450,7 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv,
memcpy(uuid, &lv->lvid, sizeof(lv->lvid));
if (!lv->merging_snapshot)
if (!lv_is_merging_origin(lv))
return poll_daemon(cmd, lv_full_name, uuid, background, 0,
&_lvconvert_mirror_fns, "Converted");
else
@ -1123,13 +1123,13 @@ static int lvconvert_merge(struct cmd_context *cmd,
struct lvinfo info;
/* Check if merge is possible */
if (cow_seg->status & SNAPSHOT_MERGE) {
if (lv_is_merging_cow(lv)) {
log_error("Snapshot %s is already merging", lv->name);
return 0;
}
if (origin->merging_snapshot) {
if (lv_is_merging_origin(origin)) {
log_error("Snapshot %s is already merging into the origin",
origin->merging_snapshot->cow->name);
find_merging_cow(origin)->cow->name);
return 0;
}

View File

@ -1270,7 +1270,7 @@ int lv_refresh(struct cmd_context *cmd, struct logical_volume *lv)
* - fortunately: polldaemon will immediately shutdown if the
* origin doesn't have a status with a snapshot percentage
*/
if (background_polling() && lv_is_origin(lv) && lv->merging_snapshot)
if (background_polling() && lv_is_origin(lv) && lv_is_merging_origin(lv))
lv_spawn_background_polling(cmd, lv);
out:
@ -1307,7 +1307,7 @@ void lv_spawn_background_polling(struct cmd_context *cmd,
pvmove_poll(cmd, pvname, 1);
}
if (lv->status & CONVERTING || lv->merging_snapshot) {
if (lv->status & CONVERTING || lv_is_merging_origin(lv)) {
log_verbose("Spawning background lvconvert process for %s",
lv->name);
lvconvert_poll(cmd, lv, 1);

View File

@ -70,7 +70,7 @@ static int _poll_lvs_in_vg(struct cmd_context *cmd,
if (lv_active &&
(lv->status & (PVMOVE|CONVERTING) ||
lv->merging_snapshot)) {
lv_is_merging_origin(lv))) {
lv_spawn_background_polling(cmd, lv);
count++;
}
@ -141,7 +141,7 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
if (background_polling() &&
activate != CHANGE_AN && activate != CHANGE_ALN &&
(lv->status & (PVMOVE|CONVERTING) ||
lv->merging_snapshot))
lv_is_merging_origin(lv)))
lv_spawn_background_polling(cmd, lv);
count++;