VISIBLE = 2,
READWRITE = 3,
SUSPENDED = 4,
- NOPROPAGATE = 5
+ NOPROPAGATE = 5,
+ TOPLEVEL = 6
+};
+
+enum {
+ MIRR_DISABLED,
+ MIRR_RUNNING,
+ MIRR_COMPLETED
};
typedef enum {
struct config_tree *cf;
const char *stripe_filler;
uint32_t mirror_region_size;
+ uint32_t pvmove_mirror_count;
char *vg_name;
/*
* Low level device-layer operations.
*/
-static struct dm_task *_setup_task(const char *name, const char *uuid,
+static struct dm_task *_setup_task(const char *name, const char *uuid,
uint32_t *event_nr, int task)
{
struct dm_task *dmt;
return 0;
}
-static int _percent_run(const char *name, const char *uuid,
- const char *target_type, int wait, float *percent,
+static int _percent_run(struct dev_manager *dm, const char *name,
+ const char *uuid,
+ const char *target_type, int wait,
+ struct logical_volume *lv, float *percent,
uint32_t *event_nr)
{
int r = 0;
char *type = NULL;
char *params = NULL;
float percent2;
+ struct list *segh = &lv->segments;
+ struct lv_segment *seg = NULL;
uint64_t numerator, denominator;
uint64_t total_numerator = 0, total_denominator = 0;
do {
next = dm_get_next_target(dmt, next, &start, &length, &type,
¶ms);
+ if (lv) {
+ if (!(segh = list_next(&lv->segments, segh))) {
+ log_error("Number of segments in active LV %s "
+ "does not match metadata", lv->name);
+ goto out;
+ }
+ seg = list_item(segh, struct lv_segment);
+ }
if (!type || !params || strcmp(type, target_type))
continue;
/* Mirror? */
- if (!strcmp(type, "mirror") &&
- sscanf(params, "%*d %*d:%*d %*d:%*d %" PRIu64 "/%" PRIu64,
- &numerator, &denominator) == 2) {
+ if (!strcmp(type, "mirror")) {
+ log_debug("Mirror status: %s", params);
+ if (sscanf(params, "%*d %*x:%*x %*x:%*x %" PRIu64
+ "/%" PRIu64, &numerator,
+ &denominator) != 2) {
+ log_error("Failure parsing mirror status: %s",
+ params);
+ goto out;
+ }
total_numerator += numerator;
total_denominator += denominator;
+
+ if (seg && (seg->status & PVMOVE))
+ seg->extents_moved = dm->mirror_region_size *
+ numerator / lv->vg->extent_size;
continue;
}
}
} while (next);
+ if (lv && (segh = list_next(&lv->segments, segh))) {
+ log_error("Number of segments in active LV %s does not "
+ "match metadata", lv->name);
+ goto out;
+ }
+
if (total_denominator)
- *percent = (float) total_numerator * 100 / total_denominator;
+ *percent = (float) total_numerator *100 / total_denominator;
else
*percent = 100;
+ log_debug("Mirror percent: %f", *percent);
r = 1;
out:
return r;
}
-static int _percent(const char *name, const char *uuid, const char *target_type,
- int wait, float *percent, uint32_t *event_nr)
+static int _percent(struct dev_manager *dm, const char *name, const char *uuid,
+ const char *target_type, int wait,
+ struct logical_volume *lv, float *percent,
+ uint32_t *event_nr)
{
if (uuid && *uuid
- && _percent_run(NULL, uuid, target_type, wait, percent, event_nr))
+ && _percent_run(dm, NULL, uuid, target_type, wait, lv, percent,
+ event_nr))
return 1;
- if (name && _percent_run(name, NULL, target_type, wait, percent,
+ if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr))
return 1;
{
char params[1024];
uint64_t esize = seg->lv->vg->extent_size;
- uint32_t s, areas = seg->area_count;
+ uint32_t s, start_area = 0u, areas = seg->area_count;
int w = 0, tw = 0;
const char *target = NULL;
const char *trailing_space;
+ int mirror_status;
switch (seg->type) {
case SEG_SNAPSHOT:
/* Target formats:
* linear [device offset]+
* striped #stripes stripe_size [device offset]+
- * mirror #logs [log_type #log_params [log_params]*]+
- * #mirrors [device offset log_number]+
+ * mirror log_type #log_params [log_params]*
+ * #mirrors [device offset]+
*/
case SEG_STRIPED:
if (areas == 1)
}
break;
case SEG_MIRRORED:
+ mirror_status = MIRR_RUNNING;
+ if (seg->status & PVMOVE) {
+ if (seg->extents_moved == seg->area_len) {
+ mirror_status = MIRR_COMPLETED;
+ start_area = 1;
+ } else if (dm->pvmove_mirror_count++) {
+ mirror_status = MIRR_DISABLED;
+ areas = 1;
+ }
+ }
+ if (mirror_status != MIRR_RUNNING) {
+ target = "linear";
+ break;
+ }
target = "mirror";
if ((tw = lvm_snprintf(params, sizeof(params),
"core 1 %u %u ",
break;
}
- for (s = 0; s < areas; s++, w += tw) {
+ for (s = start_area; s < areas; s++, w += tw) {
trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV &&
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
struct lv_segment *seg;
struct logical_volume *lv = dl->lv;
+ dm->pvmove_mirror_count = 0u;
+
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
if (!_emit_target(dm, dmt, seg)) {
* Try and get some info on this device.
*/
log_debug("Getting device status percentage for %s", name);
- if (!(_percent(name, lv->lvid.s, "snapshot", 0, percent, NULL))) {
+ if (!(_percent(dm, name, lv->lvid.s, "snapshot", 0, NULL, percent,
+ NULL))) {
stack;
return 0;
}
/* FIXME pool_free ? */
log_debug("Getting device mirror status percentage for %s", name);
- if (!(_percent(name, lv->lvid.s, "mirror", wait, percent, event_nr))) {
+ if (!(_percent(dm, name, lv->lvid.s, "mirror", wait, lv, percent,
+ event_nr))) {
stack;
return 0;
}
return 0;
}
dl->populate = _populate_vanilla;
- if (lv->status & VISIBLE_LV)
+ if (lv->status & VISIBLE_LV) {
_set_flag(dl, VISIBLE);
+ _set_flag(dl, TOPLEVEL);
+ }
+
+ if (lv->status & PVMOVE)
+ _set_flag(dl, TOPLEVEL);
/* Add dependencies for any LVs that segments refer to */
list_iterate(segh, &lv->segments) {
}
dl->populate = _populate_vanilla;
_clear_flag(dl, VISIBLE);
+ _clear_flag(dl, TOPLEVEL);
real_dlid = dl->dlid;
}
dl->populate = _populate_origin;
_set_flag(dl, VISIBLE);
+ _set_flag(dl, TOPLEVEL);
/* add the dependency on the real device */
if (!_pre_list_add(dm->mem, &dl->pre_create,
}
dl->populate = _populate_vanilla;
_clear_flag(dl, VISIBLE);
+ _clear_flag(dl, TOPLEVEL);
cow_dlid = dl->dlid;
}
dl->populate = _populate_snapshot;
_set_flag(dl, VISIBLE);
+ _set_flag(dl, TOPLEVEL);
/* add the dependency on the real device */
if (!_pre_list_add(dm->mem, &dl->pre_create,
if (_get_flag(dep, flag))
continue;
- /* Only propagate LV ACTIVE dependencies for now */
+ /* FIXME Only propagate LV ACTIVE dependencies for now */
if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
continue;
hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn);
- if (_get_flag(dl, ACTIVE) && _get_flag(dl, VISIBLE))
+ if (_get_flag(dl, ACTIVE) && _get_flag(dl, TOPLEVEL))
_create_rec(dm, dl, NULL);
}