mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-30 05:49:28 +03:00
Distinguish between visible & top level devices.
This commit is contained in:
@ -47,7 +47,14 @@ enum {
|
|||||||
VISIBLE = 2,
|
VISIBLE = 2,
|
||||||
READWRITE = 3,
|
READWRITE = 3,
|
||||||
SUSPENDED = 4,
|
SUSPENDED = 4,
|
||||||
NOPROPAGATE = 5
|
NOPROPAGATE = 5,
|
||||||
|
TOPLEVEL = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MIRR_DISABLED,
|
||||||
|
MIRR_RUNNING,
|
||||||
|
MIRR_COMPLETED
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -96,6 +103,7 @@ struct dev_manager {
|
|||||||
struct config_tree *cf;
|
struct config_tree *cf;
|
||||||
const char *stripe_filler;
|
const char *stripe_filler;
|
||||||
uint32_t mirror_region_size;
|
uint32_t mirror_region_size;
|
||||||
|
uint32_t pvmove_mirror_count;
|
||||||
|
|
||||||
char *vg_name;
|
char *vg_name;
|
||||||
|
|
||||||
@ -271,7 +279,7 @@ static char *_build_dlid(struct pool *mem, const char *lvid, const char *layer)
|
|||||||
/*
|
/*
|
||||||
* Low level device-layer operations.
|
* 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)
|
uint32_t *event_nr, int task)
|
||||||
{
|
{
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
@ -410,8 +418,10 @@ static int _status(const char *name, const char *uuid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _percent_run(const char *name, const char *uuid,
|
static int _percent_run(struct dev_manager *dm, const char *name,
|
||||||
const char *target_type, int wait, float *percent,
|
const char *uuid,
|
||||||
|
const char *target_type, int wait,
|
||||||
|
struct logical_volume *lv, float *percent,
|
||||||
uint32_t *event_nr)
|
uint32_t *event_nr)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@ -422,6 +432,8 @@ static int _percent_run(const char *name, const char *uuid,
|
|||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
char *params = NULL;
|
char *params = NULL;
|
||||||
float percent2;
|
float percent2;
|
||||||
|
struct list *segh = &lv->segments;
|
||||||
|
struct lv_segment *seg = NULL;
|
||||||
|
|
||||||
uint64_t numerator, denominator;
|
uint64_t numerator, denominator;
|
||||||
uint64_t total_numerator = 0, total_denominator = 0;
|
uint64_t total_numerator = 0, total_denominator = 0;
|
||||||
@ -451,16 +463,34 @@ static int _percent_run(const char *name, const char *uuid,
|
|||||||
do {
|
do {
|
||||||
next = dm_get_next_target(dmt, next, &start, &length, &type,
|
next = dm_get_next_target(dmt, next, &start, &length, &type,
|
||||||
¶ms);
|
¶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))
|
if (!type || !params || strcmp(type, target_type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Mirror? */
|
/* Mirror? */
|
||||||
if (!strcmp(type, "mirror") &&
|
if (!strcmp(type, "mirror")) {
|
||||||
sscanf(params, "%*d %*d:%*d %*d:%*d %" PRIu64 "/%" PRIu64,
|
log_debug("Mirror status: %s", params);
|
||||||
&numerator, &denominator) == 2) {
|
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_numerator += numerator;
|
||||||
total_denominator += denominator;
|
total_denominator += denominator;
|
||||||
|
|
||||||
|
if (seg && (seg->status & PVMOVE))
|
||||||
|
seg->extents_moved = dm->mirror_region_size *
|
||||||
|
numerator / lv->vg->extent_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,11 +511,18 @@ static int _percent_run(const char *name, const char *uuid,
|
|||||||
}
|
}
|
||||||
} while (next);
|
} 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)
|
if (total_denominator)
|
||||||
*percent = (float) total_numerator * 100 / total_denominator;
|
*percent = (float) total_numerator *100 / total_denominator;
|
||||||
else
|
else
|
||||||
*percent = 100;
|
*percent = 100;
|
||||||
|
|
||||||
|
log_debug("Mirror percent: %f", *percent);
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -493,14 +530,17 @@ static int _percent_run(const char *name, const char *uuid,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _percent(const char *name, const char *uuid, const char *target_type,
|
static int _percent(struct dev_manager *dm, const char *name, const char *uuid,
|
||||||
int wait, float *percent, uint32_t *event_nr)
|
const char *target_type, int wait,
|
||||||
|
struct logical_volume *lv, float *percent,
|
||||||
|
uint32_t *event_nr)
|
||||||
{
|
{
|
||||||
if (uuid && *uuid
|
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;
|
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))
|
event_nr))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -708,10 +748,11 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
|||||||
{
|
{
|
||||||
char params[1024];
|
char params[1024];
|
||||||
uint64_t esize = seg->lv->vg->extent_size;
|
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;
|
int w = 0, tw = 0;
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
const char *trailing_space;
|
const char *trailing_space;
|
||||||
|
int mirror_status;
|
||||||
|
|
||||||
switch (seg->type) {
|
switch (seg->type) {
|
||||||
case SEG_SNAPSHOT:
|
case SEG_SNAPSHOT:
|
||||||
@ -721,8 +762,8 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
|||||||
/* Target formats:
|
/* Target formats:
|
||||||
* linear [device offset]+
|
* linear [device offset]+
|
||||||
* striped #stripes stripe_size [device offset]+
|
* striped #stripes stripe_size [device offset]+
|
||||||
* mirror #logs [log_type #log_params [log_params]*]+
|
* mirror log_type #log_params [log_params]*
|
||||||
* #mirrors [device offset log_number]+
|
* #mirrors [device offset]+
|
||||||
*/
|
*/
|
||||||
case SEG_STRIPED:
|
case SEG_STRIPED:
|
||||||
if (areas == 1)
|
if (areas == 1)
|
||||||
@ -740,6 +781,20 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SEG_MIRRORED:
|
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";
|
target = "mirror";
|
||||||
if ((tw = lvm_snprintf(params, sizeof(params),
|
if ((tw = lvm_snprintf(params, sizeof(params),
|
||||||
"core 1 %u %u ",
|
"core 1 %u %u ",
|
||||||
@ -749,7 +804,7 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s = 0; s < areas; s++, w += tw) {
|
for (s = start_area; s < areas; s++, w += tw) {
|
||||||
trailing_space = (areas - s - 1) ? " " : "";
|
trailing_space = (areas - s - 1) ? " " : "";
|
||||||
if ((seg->area[s].type == AREA_PV &&
|
if ((seg->area[s].type == AREA_PV &&
|
||||||
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
|
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
|
||||||
@ -801,6 +856,8 @@ static int _populate_vanilla(struct dev_manager *dm,
|
|||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
struct logical_volume *lv = dl->lv;
|
struct logical_volume *lv = dl->lv;
|
||||||
|
|
||||||
|
dm->pvmove_mirror_count = 0u;
|
||||||
|
|
||||||
list_iterate(segh, &lv->segments) {
|
list_iterate(segh, &lv->segments) {
|
||||||
seg = list_item(segh, struct lv_segment);
|
seg = list_item(segh, struct lv_segment);
|
||||||
if (!_emit_target(dm, dmt, seg)) {
|
if (!_emit_target(dm, dmt, seg)) {
|
||||||
@ -986,7 +1043,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
|||||||
* Try and get some info on this device.
|
* Try and get some info on this device.
|
||||||
*/
|
*/
|
||||||
log_debug("Getting device status percentage for %s", name);
|
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;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1016,7 +1074,8 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
|||||||
/* FIXME pool_free ? */
|
/* FIXME pool_free ? */
|
||||||
|
|
||||||
log_debug("Getting device mirror status percentage for %s", name);
|
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;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1128,8 +1187,13 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dl->populate = _populate_vanilla;
|
dl->populate = _populate_vanilla;
|
||||||
if (lv->status & VISIBLE_LV)
|
if (lv->status & VISIBLE_LV) {
|
||||||
_set_flag(dl, VISIBLE);
|
_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 */
|
/* Add dependencies for any LVs that segments refer to */
|
||||||
list_iterate(segh, &lv->segments) {
|
list_iterate(segh, &lv->segments) {
|
||||||
@ -1165,6 +1229,7 @@ static int _expand_origin_real(struct dev_manager *dm,
|
|||||||
}
|
}
|
||||||
dl->populate = _populate_vanilla;
|
dl->populate = _populate_vanilla;
|
||||||
_clear_flag(dl, VISIBLE);
|
_clear_flag(dl, VISIBLE);
|
||||||
|
_clear_flag(dl, TOPLEVEL);
|
||||||
|
|
||||||
real_dlid = dl->dlid;
|
real_dlid = dl->dlid;
|
||||||
|
|
||||||
@ -1174,6 +1239,7 @@ static int _expand_origin_real(struct dev_manager *dm,
|
|||||||
}
|
}
|
||||||
dl->populate = _populate_origin;
|
dl->populate = _populate_origin;
|
||||||
_set_flag(dl, VISIBLE);
|
_set_flag(dl, VISIBLE);
|
||||||
|
_set_flag(dl, TOPLEVEL);
|
||||||
|
|
||||||
/* add the dependency on the real device */
|
/* add the dependency on the real device */
|
||||||
if (!_pre_list_add(dm->mem, &dl->pre_create,
|
if (!_pre_list_add(dm->mem, &dl->pre_create,
|
||||||
@ -1220,6 +1286,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
|
|||||||
}
|
}
|
||||||
dl->populate = _populate_vanilla;
|
dl->populate = _populate_vanilla;
|
||||||
_clear_flag(dl, VISIBLE);
|
_clear_flag(dl, VISIBLE);
|
||||||
|
_clear_flag(dl, TOPLEVEL);
|
||||||
|
|
||||||
cow_dlid = dl->dlid;
|
cow_dlid = dl->dlid;
|
||||||
|
|
||||||
@ -1229,6 +1296,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
|
|||||||
}
|
}
|
||||||
dl->populate = _populate_snapshot;
|
dl->populate = _populate_snapshot;
|
||||||
_set_flag(dl, VISIBLE);
|
_set_flag(dl, VISIBLE);
|
||||||
|
_set_flag(dl, TOPLEVEL);
|
||||||
|
|
||||||
/* add the dependency on the real device */
|
/* add the dependency on the real device */
|
||||||
if (!_pre_list_add(dm->mem, &dl->pre_create,
|
if (!_pre_list_add(dm->mem, &dl->pre_create,
|
||||||
@ -1301,7 +1369,7 @@ static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
|
|||||||
if (_get_flag(dep, flag))
|
if (_get_flag(dep, flag))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Only propagate LV ACTIVE dependencies for now */
|
/* FIXME Only propagate LV ACTIVE dependencies for now */
|
||||||
if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
|
if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1587,7 +1655,7 @@ static int _execute(struct dev_manager *dm, struct volume_group *vg)
|
|||||||
hash_iterate(hn, dm->layers) {
|
hash_iterate(hn, dm->layers) {
|
||||||
dl = hash_get_data(dm->layers, hn);
|
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);
|
_create_rec(dm, dl, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user