1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +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, * In case of a snapshot device, we monitor lv->snapshot->lv,
* not the actual LV itself. * 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); 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) struct logical_volume *lv)
{ {
const char *origin_dlid, *cow_dlid, *merge_dlid; 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"))) if (!(origin_dlid = build_dlid(dm, lv->lvid.s, "real")))
return_0; 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; 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; return_0;
if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid, if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid,
cow_dlid, merge_dlid, cow_dlid, merge_dlid,
lv->merging_snapshot->chunk_size)) merging_cow_seg->chunk_size))
return_0; return_0;
return 1; return 1;
@ -979,7 +980,8 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
return 0; 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; return 1;
if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real"))) 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"); log_error("Clustered snapshots are not yet supported");
return 0; return 0;
} }
if (seg->lv->merging_snapshot) { if (lv_is_merging_origin(seg->lv)) {
if (!_add_new_lv_to_dtree(dm, dtree, if (!_add_new_lv_to_dtree(dm, dtree,
seg->lv->merging_snapshot->cow, "cow")) find_merging_cow(seg->lv)->cow, "cow"))
return_0; return_0;
/* /*
* Must also add "real" LV for use when * 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 */ /* Now we've added its dependencies, we can add the target itself */
if (lv_is_origin(seg->lv) && !layer) { 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)) if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
return_0; return_0;
} else { } 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); uint32_t read_ahead_flags = UINT32_C(0);
uint16_t udev_flags = 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: * Clear merge attributes if merge isn't currently possible:
* either origin or merging snapshot are open * 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, if ((dev_manager_info(dm->mem, NULL, lv,
0, 1, 0, &dinfo, NULL) && dinfo.open_count) || 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)) { 0, 1, 0, &dinfo, NULL) && dinfo.open_count)) {
if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge")) { if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge"))
/* clear merge attributes */ clear_snapshot_merge(lv);
lv->merging_snapshot->status &= ~SNAPSHOT_MERGE;
lv->merging_snapshot = NULL;
}
} }
} }
lv_name = lv->name; 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) { if (layer) {
/* /*
* use origin's name as basis for snapshot-merge device names; * 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)) { if (lv_is_cow(lv)) {
origin = origin_from_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); log_verbose("Removing snapshot %s", lv->name);
if (!vg_remove_snapshot(lv)) if (!vg_remove_snapshot(lv))
return_0; return_0;
@ -2953,7 +2953,7 @@ int lv_create_single(struct volume_group *vg,
"supported yet"); "supported yet");
return 0; return 0;
} }
if (org->merging_snapshot) { if (lv_is_merging_origin(org)) {
log_error("Snapshots of an origin that has a " log_error("Snapshots of an origin that has a "
"merging snapshot is not supported"); "merging snapshot is not supported");
return 0; 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_origin(const struct logical_volume *lv);
int lv_is_virtual_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_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 */ /* Test if given LV is visible from user's perspective */
int lv_is_visible(const struct logical_volume *lv); int lv_is_visible(const struct logical_volume *lv);
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv); 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 */ /* Given a cow LV, return return the snapshot lv_segment that uses it */
struct lv_segment *find_cow(const struct logical_volume *lv); 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 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, int vg_add_snapshot(struct logical_volume *origin, struct logical_volume *cow,
union lvid *lvid, uint32_t extent_count, union lvid *lvid, uint32_t extent_count,
uint32_t chunk_size); 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))) if (lv_is_virtual_origin(origin_from_cow(lv)))
return 1; return 1;
if (find_cow(lv)->status & SNAPSHOT_MERGE) if (lv_is_merging_cow(lv))
return 0; return 0;
return lv_is_visible(origin_from_cow(lv)); 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; 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 */ /* Given a cow LV, return the snapshot lv_segment that uses it */
struct lv_segment *find_cow(const struct logical_volume *lv) 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; 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, int vg_add_snapshot(struct logical_volume *origin,
struct logical_volume *cow, union lvid *lvid, struct logical_volume *cow, union lvid *lvid,
uint32_t extent_count, uint32_t chunk_size) 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) int vg_remove_snapshot(struct logical_volume *cow)
{ {
struct logical_volume *origin = origin_from_cow(cow);
dm_list_del(&cow->snapshot->origin_list); dm_list_del(&cow->snapshot->origin_list);
cow->snapshot->origin->origin_count--; origin->origin_count--;
if (cow->snapshot->origin->merging_snapshot == cow->snapshot) if (find_merging_cow(origin) == find_cow(cow))
cow->snapshot->origin->merging_snapshot = NULL; clear_snapshot_merge(origin_from_cow(cow));
if (!lv_remove(cow->snapshot->lv)) { if (!lv_remove(cow->snapshot->lv)) {
log_error("Failed to remove internal snapshot LV %s", 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'; repstr[0] = 'v';
/* Origin takes precedence over Mirror */ /* Origin takes precedence over Mirror */
else if (lv_is_origin(lv)) { else if (lv_is_origin(lv)) {
if (lv->merging_snapshot) if (lv_is_merging_origin(lv))
repstr[0] = 'O'; repstr[0] = 'O';
else else
repstr[0] = 'o'; 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) else if (lv->status & MIRROR_LOG)
repstr[0] = 'l'; repstr[0] = 'l';
else if (lv_is_cow(lv)) { else if (lv_is_cow(lv)) {
if (find_cow(lv)->status & SNAPSHOT_MERGE) if (lv_is_merging_cow(lv))
repstr[0] = 'S'; repstr[0] = 'S';
else else
repstr[0] = 's'; repstr[0] = 's';
@ -1023,7 +1023,7 @@ static int _snpercent_disp(struct dm_report *rh __attribute((unused)), struct dm
return 0; 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)) { (lv_info(lv->vg->cmd, lv, &info, 0, 0) && !info.exists)) {
*sortval = UINT64_C(0); *sortval = UINT64_C(0);
dm_report_field_set_value(field, "", sortval); 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) || if (!lv_snapshot_percent(lv, &snap_percent, &percent_range) ||
(percent_range == PERCENT_INVALID)) { (percent_range == PERCENT_INVALID)) {
if (!lv->merging_snapshot) { if (!lv_is_merging_origin(lv)) {
*sortval = UINT64_C(100); *sortval = UINT64_C(100);
dm_report_field_set_value(field, "100.00", sortval); dm_report_field_set_value(field, "100.00", sortval);
} else { } else {

View File

@ -377,7 +377,7 @@ static int _finish_lvconvert_merge(struct cmd_context *cmd,
struct logical_volume *lv, struct logical_volume *lv,
struct dm_list *lvs_changed __attribute((unused))) 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) { if (!snap_seg) {
log_error("Logical volume %s has no merging snapshot.", lv->name); log_error("Logical volume %s has no merging snapshot.", lv->name);
return 0; return 0;
@ -450,7 +450,7 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv,
memcpy(uuid, &lv->lvid, sizeof(lv->lvid)); 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, return poll_daemon(cmd, lv_full_name, uuid, background, 0,
&_lvconvert_mirror_fns, "Converted"); &_lvconvert_mirror_fns, "Converted");
else else
@ -1123,13 +1123,13 @@ static int lvconvert_merge(struct cmd_context *cmd,
struct lvinfo info; struct lvinfo info;
/* Check if merge is possible */ /* 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); log_error("Snapshot %s is already merging", lv->name);
return 0; return 0;
} }
if (origin->merging_snapshot) { if (lv_is_merging_origin(origin)) {
log_error("Snapshot %s is already merging into the origin", log_error("Snapshot %s is already merging into the origin",
origin->merging_snapshot->cow->name); find_merging_cow(origin)->cow->name);
return 0; 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 * - fortunately: polldaemon will immediately shutdown if the
* origin doesn't have a status with a snapshot percentage * 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); lv_spawn_background_polling(cmd, lv);
out: out:
@ -1307,7 +1307,7 @@ void lv_spawn_background_polling(struct cmd_context *cmd,
pvmove_poll(cmd, pvname, 1); 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", log_verbose("Spawning background lvconvert process for %s",
lv->name); lv->name);
lvconvert_poll(cmd, lv, 1); lvconvert_poll(cmd, lv, 1);

View File

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