mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
o Rejig activation code device dependencies to make things a bit more robust
and further reduce the number of ioctl calls made. o Metadata area struct change. o Make config file accessible to activation functions & get stripe_filler from it. o Allow kernel to return snapshot status as a fraction or a percentage.
This commit is contained in:
parent
75833edb80
commit
a9953411a8
@ -144,7 +144,7 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -217,7 +217,7 @@ static int _lv_activate(struct logical_volume *lv)
|
|||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ static int _lv_deactivate(struct logical_volume *lv)
|
|||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ static int _lv_suspend(struct logical_volume *lv)
|
|||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,11 @@ int activation(void);
|
|||||||
int driver_version(char *version, size_t size);
|
int driver_version(char *version, size_t size);
|
||||||
int library_version(char *version, size_t size);
|
int library_version(char *version, size_t size);
|
||||||
|
|
||||||
|
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns 1 if info structure has been populated, else 0.
|
* Returns 1 if info structure has been populated, else 0.
|
||||||
*/
|
*/
|
||||||
@ -37,20 +42,6 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info);
|
|||||||
*/
|
*/
|
||||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
||||||
|
|
||||||
/*
|
|
||||||
* These should eventually use config file
|
|
||||||
* to determine whether or not to activate
|
|
||||||
*/
|
|
||||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
|
||||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
|
||||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
|
|
||||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
* I don't like the *lvs_in_vg* function names.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return number of LVs in the VG that are active.
|
* Return number of LVs in the VG that are active.
|
||||||
*/
|
*/
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "defaults.h"
|
||||||
|
|
||||||
#include <libdevmapper.h>
|
#include <libdevmapper.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -45,7 +46,8 @@ enum {
|
|||||||
RELOAD = 1,
|
RELOAD = 1,
|
||||||
VISIBLE = 2,
|
VISIBLE = 2,
|
||||||
READWRITE = 3,
|
READWRITE = 3,
|
||||||
SUSPENDED = 4
|
SUSPENDED = 4,
|
||||||
|
NOPROPAGATE = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -73,8 +75,8 @@ struct dev_layer {
|
|||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Devices that must be created before this one can be
|
* Devices that must be created before this one can be created.
|
||||||
* created. Holds str_lists.
|
* Reloads get propagated to this list. Holds str_lists.
|
||||||
*/
|
*/
|
||||||
struct list pre_create;
|
struct list pre_create;
|
||||||
|
|
||||||
@ -85,9 +87,14 @@ struct dl_list {
|
|||||||
struct dev_layer *dl;
|
struct dev_layer *dl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *stripe_filler = NULL;
|
||||||
|
|
||||||
struct dev_manager {
|
struct dev_manager {
|
||||||
struct pool *mem;
|
struct pool *mem;
|
||||||
|
|
||||||
|
struct config_tree *cf;
|
||||||
|
const char *stripe_filler;
|
||||||
|
|
||||||
char *vg_name;
|
char *vg_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -375,6 +382,11 @@ static int _status_run(const char *name, const char *uuid,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _status(const char *name, const char *uuid,
|
||||||
|
unsigned long long *start, unsigned long long *length,
|
||||||
|
char **type, uint32_t type_size, char **params,
|
||||||
|
uint32_t param_size) __attribute__ ((unused));
|
||||||
|
|
||||||
static int _status(const char *name, const char *uuid,
|
static int _status(const char *name, const char *uuid,
|
||||||
unsigned long long *start, unsigned long long *length,
|
unsigned long long *start, unsigned long long *length,
|
||||||
char **type, uint32_t type_size, char **params,
|
char **type, uint32_t type_size, char **params,
|
||||||
@ -392,6 +404,78 @@ static int _status(const char *name, const char *uuid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _percent_run(const char *name, const char *uuid,
|
||||||
|
const char *target_type, float *percent)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
void *next = NULL;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *type = NULL;
|
||||||
|
char *params = NULL;
|
||||||
|
float percent2;
|
||||||
|
|
||||||
|
uint64_t numerator, denominator;
|
||||||
|
uint64_t total_numerator = 0, total_denominator = 0;
|
||||||
|
|
||||||
|
*percent = -1;
|
||||||
|
|
||||||
|
if (!(dmt = _setup_task(name, uuid, DM_DEVICE_STATUS))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm_task_run(dmt)) {
|
||||||
|
stack;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
next = dm_get_next_target(dmt, next, &start, &length, &type,
|
||||||
|
¶ms);
|
||||||
|
|
||||||
|
if (!type || !params || strcmp(type, target_type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(type, "snapshot"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Snapshot */
|
||||||
|
if (index(params, '/')) {
|
||||||
|
if (sscanf(params, "%" PRIu64 "/%" PRIu64,
|
||||||
|
&numerator, &denominator) == 2) {
|
||||||
|
total_numerator += numerator;
|
||||||
|
total_denominator += denominator;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (sscanf(params, "%f", &percent2) == 1) {
|
||||||
|
*percent += percent2;
|
||||||
|
*percent /= 2;
|
||||||
|
}
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
if (total_denominator)
|
||||||
|
*percent = (float) total_numerator *100 / total_denominator;
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _percent(const char *name, const char *uuid, const char *target_type,
|
||||||
|
float *percent)
|
||||||
|
{
|
||||||
|
if (uuid && *uuid && _percent_run(NULL, uuid, target_type, percent))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (name && _percent_run(name, NULL, target_type, percent))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _rename(struct dev_layer *dl, char *newname)
|
static int _rename(struct dev_layer *dl, char *newname)
|
||||||
{
|
{
|
||||||
int r = 1;
|
int r = 1;
|
||||||
@ -553,7 +637,7 @@ static int _suspend_or_resume(const char *name, action_t suspend)
|
|||||||
|
|
||||||
static int _suspend(struct dev_layer *dl)
|
static int _suspend(struct dev_layer *dl)
|
||||||
{
|
{
|
||||||
if (dl->info.suspended)
|
if (!dl->info.exists || dl->info.suspended)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!_suspend_or_resume(dl->name, SUSPEND)) {
|
if (!_suspend_or_resume(dl->name, SUSPEND)) {
|
||||||
@ -567,7 +651,7 @@ static int _suspend(struct dev_layer *dl)
|
|||||||
|
|
||||||
static int _resume(struct dev_layer *dl)
|
static int _resume(struct dev_layer *dl)
|
||||||
{
|
{
|
||||||
if (!dl->info.suspended)
|
if (!dl->info.exists || !dl->info.suspended)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!_suspend_or_resume(dl->name, RESUME)) {
|
if (!_suspend_or_resume(dl->name, RESUME)) {
|
||||||
@ -588,47 +672,73 @@ static int _resume(struct dev_layer *dl)
|
|||||||
* Emit a target for a given segment.
|
* Emit a target for a given segment.
|
||||||
* FIXME: tidy this function.
|
* FIXME: tidy this function.
|
||||||
*/
|
*/
|
||||||
static int _emit_target(struct dm_task *dmt, struct lv_segment *seg)
|
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||||
|
struct lv_segment *seg)
|
||||||
{
|
{
|
||||||
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, stripes = seg->stripes;
|
uint32_t s, areas = seg->area_count;
|
||||||
int w = 0, tw = 0;
|
int w = 0, tw = 0;
|
||||||
const char *filler = "/dev/ioerror";
|
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
|
const char *trailing_space;
|
||||||
|
|
||||||
if (stripes == 1) {
|
switch (seg->type) {
|
||||||
if (!seg->area[0].pv) {
|
case SEG_SNAPSHOT:
|
||||||
target = "error";
|
log_error("_emit_target: Internal error: Can't handle "
|
||||||
goto add_target;
|
"SEG_SNAPSHOT");
|
||||||
} else
|
return 0;
|
||||||
|
/* Target formats:
|
||||||
|
* linear [device offset]+
|
||||||
|
* striped #stripes stripe_size [device offset]+
|
||||||
|
*/
|
||||||
|
case SEG_STRIPED:
|
||||||
|
if (areas == 1)
|
||||||
target = "linear";
|
target = "linear";
|
||||||
} else if (stripes > 1) {
|
else if (areas > 1) {
|
||||||
target = "striped";
|
target = "striped";
|
||||||
if ((tw = lvm_snprintf(params, sizeof(params), "%u %u ",
|
if ((tw = lvm_snprintf(params, sizeof(params), "%u %u ",
|
||||||
stripes, seg->stripe_size)) < 0)
|
areas, seg->stripe_size)) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
w = tw;
|
w = tw;
|
||||||
|
} else {
|
||||||
|
log_error("_emit_target: Internal error: SEG_STRIPED "
|
||||||
|
"with no stripes");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEG_MIRRORED:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s = 0; s < stripes; s++, w += tw) {
|
for (s = 0; s < areas; s++, w += tw) {
|
||||||
if (!seg->area[s].pv || !seg->area[s].pv->dev)
|
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)) ||
|
||||||
|
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
|
||||||
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||||
"%s 0%s", filler,
|
"%s 0%s", dm->stripe_filler,
|
||||||
s == (stripes - 1) ? "" : " ");
|
trailing_space);
|
||||||
else
|
else if (seg->area[s].type == AREA_PV)
|
||||||
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||||
"%s %" PRIu64 "%s",
|
"%s %" PRIu64 "%s",
|
||||||
dev_name(seg->area[s].pv->dev),
|
dev_name(seg->area[s].u.pv.pv->dev),
|
||||||
(seg->area[s].pv->pe_start +
|
(seg->area[s].u.pv.pv->pe_start +
|
||||||
(esize * seg->area[s].pe)),
|
(esize * seg->area[s].u.pv.pe)),
|
||||||
s == (stripes - 1) ? "" : " ");
|
trailing_space);
|
||||||
|
else
|
||||||
|
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||||
|
"%s/%s %" PRIu64 "%s", dm_dir(),
|
||||||
|
_build_name(dm->mem,
|
||||||
|
seg->lv->vg->name,
|
||||||
|
seg->area[s].u.lv.lv->
|
||||||
|
name, NULL),
|
||||||
|
esize * seg->area[s].u.lv.le,
|
||||||
|
trailing_space);
|
||||||
|
|
||||||
if (tw < 0)
|
if (tw < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_target:
|
|
||||||
log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
|
log_debug("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
|
||||||
esize * seg->le, esize * seg->len, target, params);
|
esize * seg->le, esize * seg->len, target, params);
|
||||||
|
|
||||||
@ -641,7 +751,7 @@ static int _emit_target(struct dm_task *dmt, struct lv_segment *seg)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
log_error("Insufficient space to write target parameters.");
|
log_error("Insufficient space in params[] to write target parameters.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,7 +764,7 @@ static int _populate_vanilla(struct dev_manager *dm,
|
|||||||
|
|
||||||
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(dmt, seg)) {
|
if (!_emit_target(dm, dmt, seg)) {
|
||||||
log_error("Unable to build table for '%s'", lv->name);
|
log_error("Unable to build table for '%s'", lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -734,7 +844,8 @@ static int _populate_snapshot(struct dev_manager *dm,
|
|||||||
/*
|
/*
|
||||||
* dev_manager implementation.
|
* dev_manager implementation.
|
||||||
*/
|
*/
|
||||||
struct dev_manager *dev_manager_create(const char *vg_name)
|
struct dev_manager *dev_manager_create(const char *vg_name,
|
||||||
|
struct config_tree *cf)
|
||||||
{
|
{
|
||||||
struct pool *mem;
|
struct pool *mem;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
@ -750,6 +861,13 @@ struct dev_manager *dev_manager_create(const char *vg_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dm->mem = mem;
|
dm->mem = mem;
|
||||||
|
dm->cf = cf;
|
||||||
|
if (!stripe_filler) {
|
||||||
|
stripe_filler = find_config_str(cf->root,
|
||||||
|
"activation/missing_stripe_filler",
|
||||||
|
'/', DEFAULT_STRIPE_FILLER);
|
||||||
|
}
|
||||||
|
dm->stripe_filler = stripe_filler;
|
||||||
|
|
||||||
if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
|
if (!(dm->vg_name = pool_strdup(dm->mem, vg_name))) {
|
||||||
stack;
|
stack;
|
||||||
@ -807,23 +925,7 @@ int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
|||||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||||
struct logical_volume *lv, float *percent)
|
struct logical_volume *lv, float *percent)
|
||||||
{
|
{
|
||||||
char *name, *type, *params;
|
char *name;
|
||||||
unsigned long long start, length;
|
|
||||||
unsigned int numerator, denominator;
|
|
||||||
|
|
||||||
/* FIXME: Use #defines - & move allocations into _status_run ? */
|
|
||||||
uint32_t type_size = 32;
|
|
||||||
uint32_t param_size = 32;
|
|
||||||
|
|
||||||
if (!(type = pool_alloc(dm->mem, sizeof(*type) * type_size))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(params = pool_alloc(dm->mem, sizeof(*params) * param_size))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build a name for the top layer.
|
* Build a name for the top layer.
|
||||||
@ -836,31 +938,16 @@ 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 for %s", name);
|
log_debug("Getting device status percentage for %s", name);
|
||||||
if (!(_status(name, lv->lvid.s, &start, &length, &type, type_size,
|
if (!(_percent(name, lv->lvid.s, "snapshot", percent))) {
|
||||||
¶ms, param_size))) {
|
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Ensure this is a *snapshot* target with percentage! */
|
|
||||||
/* FIXME pool_free ? */
|
/* FIXME pool_free ? */
|
||||||
|
|
||||||
/* If the snapshot isn't available, percent will be -1 */
|
/* If the snapshot isn't available, percent will be -1 */
|
||||||
*percent = -1;
|
return 1;
|
||||||
|
|
||||||
if (!params)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (index(params, '/')) {
|
|
||||||
if (sscanf(params, "%u/%u", &numerator, &denominator) == 2) {
|
|
||||||
*percent = (float) numerator *100 / denominator;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else if (sscanf(params, "%f", percent) == 1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
|
static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
|
||||||
@ -958,13 +1045,36 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
|
|||||||
* only one layer.
|
* only one layer.
|
||||||
*/
|
*/
|
||||||
struct dev_layer *dl;
|
struct dev_layer *dl;
|
||||||
|
struct list *segh;
|
||||||
|
struct lv_segment *seg;
|
||||||
|
uint32_t s;
|
||||||
|
|
||||||
if (!(dl = _create_layer(dm, NULL, lv))) {
|
if (!(dl = _create_layer(dm, NULL, lv))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dl->populate = _populate_vanilla;
|
dl->populate = _populate_vanilla;
|
||||||
_set_flag(dl, VISIBLE);
|
if (lv->status & VISIBLE_LV)
|
||||||
|
_set_flag(dl, VISIBLE);
|
||||||
|
|
||||||
|
/* Add dependencies for any LVs that segments refer to */
|
||||||
|
list_iterate(segh, &lv->segments) {
|
||||||
|
seg = list_item(segh, struct lv_segment);
|
||||||
|
if (seg->type != SEG_STRIPED && seg->type != SEG_MIRRORED)
|
||||||
|
continue;
|
||||||
|
for (s = 0; s < seg->area_count; s++) {
|
||||||
|
if (seg->area[s].type != AREA_LV)
|
||||||
|
continue;
|
||||||
|
if (!_pre_list_add(dm->mem, &dl->pre_create,
|
||||||
|
_build_dlid(dm->mem,
|
||||||
|
seg->area[s].u.lv.lv->
|
||||||
|
lvid.s, NULL))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_set_flag(dl, NOPROPAGATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1117,6 +1227,10 @@ 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 */
|
||||||
|
if ((flag != ACTIVE) && _get_flag(dl, NOPROPAGATE))
|
||||||
|
continue;
|
||||||
|
|
||||||
_set_flag(dep, flag);
|
_set_flag(dep, flag);
|
||||||
|
|
||||||
if (!_trace_layer_marks(dm, dep, flag)) {
|
if (!_trace_layer_marks(dm, dep, flag)) {
|
||||||
@ -1452,6 +1566,7 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME Get this info directly from the driver not the unreliable fs */
|
||||||
static int _scan_existing_devices(struct dev_manager *dm)
|
static int _scan_existing_devices(struct dev_manager *dm)
|
||||||
{
|
{
|
||||||
const char *dev_dir = dm_dir();
|
const char *dev_dir = dm_dir();
|
||||||
@ -1570,12 +1685,34 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
|
|||||||
return _add_lvs(dm->mem, &dm->reload_list, old_origin);
|
return _add_lvs(dm->mem, &dm->reload_list, old_origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _remove_suspended_lvs(struct dev_manager *dm,
|
||||||
|
struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
struct logical_volume *suspended;
|
||||||
|
struct snapshot *s;
|
||||||
|
struct list *sh, *suspend_head;
|
||||||
|
|
||||||
|
suspend_head = &dm->suspend_list;
|
||||||
|
|
||||||
|
/* Remove from list any snapshots with given origin */
|
||||||
|
list_iterate(sh, suspend_head) {
|
||||||
|
suspended = list_item(sh, struct lv_list)->lv;
|
||||||
|
if ((s = find_cow(suspended)) && s->origin == lv) {
|
||||||
|
_remove_lv(suspend_head, suspended);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_remove_lv(suspend_head, lv);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
|
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
int found;
|
|
||||||
char *dlid;
|
char *dlid;
|
||||||
struct list *lvh;
|
struct list *lvh;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
struct dev_layer *dl;
|
||||||
|
|
||||||
list_iterate(lvh, &vg->lvs) {
|
list_iterate(lvh, &vg->lvs) {
|
||||||
lv = list_item(lvh, struct lv_list)->lv;
|
lv = list_item(lvh, struct lv_list)->lv;
|
||||||
@ -1585,16 +1722,24 @@ static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = hash_lookup(dm->layers, dlid) ? 1 : 0;
|
dl = hash_lookup(dm->layers, dlid);
|
||||||
pool_free(dm->mem, dlid);
|
pool_free(dm->mem, dlid);
|
||||||
|
|
||||||
if (found) {
|
if (dl) {
|
||||||
log_debug("Found active lv %s", lv->name);
|
log_debug("Found active lv %s%s", lv->name,
|
||||||
|
dl->info.suspended ? " (suspended)" : "");
|
||||||
|
|
||||||
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
|
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dl->info.suspended) {
|
||||||
|
if (!_add_lv(dm->mem, &dm->suspend_list, lv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1630,6 +1775,13 @@ static int _action(struct dev_manager *dm, struct logical_volume *lv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action == SUSPEND || action == RESUME || action == ACTIVATE)
|
||||||
|
/* Get into known state - remove from suspend list if present */
|
||||||
|
if (!_remove_suspended_lvs(dm, lv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (action == SUSPEND) {
|
if (action == SUSPEND) {
|
||||||
if (!_add_lvs(dm->mem, &dm->suspend_list, lv)) {
|
if (!_add_lvs(dm->mem, &dm->suspend_list, lv)) {
|
||||||
stack;
|
stack;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define _LVM_DEV_MANAGER_H
|
#define _LVM_DEV_MANAGER_H
|
||||||
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
struct dev_manager;
|
struct dev_manager;
|
||||||
struct dm_info;
|
struct dm_info;
|
||||||
@ -15,7 +16,8 @@ struct dm_info;
|
|||||||
/*
|
/*
|
||||||
* Constructor and destructor.
|
* Constructor and destructor.
|
||||||
*/
|
*/
|
||||||
struct dev_manager *dev_manager_create(const char *vg_name);
|
struct dev_manager *dev_manager_create(const char *vg_name,
|
||||||
|
struct config_tree *cf);
|
||||||
void dev_manager_destroy(struct dev_manager *dm);
|
void dev_manager_destroy(struct dev_manager *dm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user