mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Replacement activation code. [Don't use this yet!]
This commit is contained in:
parent
165e4a112b
commit
5f4b2acfe5
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -284,10 +284,8 @@ static int _target_present(const char *target_name)
|
||||
struct dm_versions *target, *last_target;
|
||||
|
||||
log_very_verbose("Getting target version for %s", target_name);
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_debug("Failed to get %s target version", target_name);
|
||||
@ -314,7 +312,7 @@ static int _target_present(const char *target_name)
|
||||
return r;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name)
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
{
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
@ -324,17 +322,19 @@ int target_present(const char *target_name)
|
||||
return 0;
|
||||
|
||||
#ifdef MODPROBE_CMD
|
||||
if (use_modprobe) {
|
||||
if (_target_present(target_name))
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
log_error("target_present module name too long: %s", target_name);
|
||||
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
< 0) {
|
||||
log_error("target_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!exec_cmd(MODPROBE_CMD, module, "", "")) {
|
||||
stack;
|
||||
return 0;
|
||||
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
|
||||
return_0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -353,17 +353,14 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
log_debug("Getting device info for %s", name);
|
||||
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
|
||||
with_open_count, &dminfo)) {
|
||||
dm_pool_free(cmd->mem, name);
|
||||
stack;
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
|
||||
info->exists = dminfo.exists;
|
||||
@ -372,6 +369,8 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, in
|
||||
info->major = dminfo.major;
|
||||
info->minor = dminfo.minor;
|
||||
info->read_only = dminfo.read_only;
|
||||
info->live_table = dminfo.live_table;
|
||||
info->inactive_table = dminfo.inactive_table;
|
||||
|
||||
dm_pool_free(cmd->mem, name);
|
||||
return 1;
|
||||
@ -405,10 +404,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
|
||||
stack;
|
||||
@ -429,18 +426,14 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wa
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_info(cmd, lv, &info, 0))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
|
||||
stack;
|
||||
@ -474,16 +467,13 @@ static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
|
||||
return info.open_count;
|
||||
}
|
||||
|
||||
/* FIXME Need to detect and handle an lv rename */
|
||||
static int _lv_activate_lv(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_activate(dm, lv)))
|
||||
stack;
|
||||
@ -492,15 +482,28 @@ static int _lv_activate_lv(struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_preload(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_preload(dm, lv)))
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_deactivate(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_deactivate(dm, lv)))
|
||||
stack;
|
||||
@ -514,10 +517,8 @@ static int _lv_suspend_lv(struct logical_volume *lv)
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_suspend(dm, lv)))
|
||||
stack;
|
||||
@ -580,14 +581,20 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_info(cmd, lv, &info, 0))
|
||||
return_0;
|
||||
|
||||
if (!info.exists || info.suspended)
|
||||
return error_if_not_suspended ? 0 : 1;
|
||||
|
||||
/* If VG was precommitted, preload devices for the LV */
|
||||
if ((lv->vg->status & PRECOMMITTED)) {
|
||||
if (!_lv_preload(lv)) {
|
||||
/* FIXME Revert preloading */
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
memlock_inc();
|
||||
if (!_lv_suspend_lv(lv)) {
|
||||
memlock_dec();
|
||||
@ -626,10 +633,8 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_info(cmd, lv, &info, 0))
|
||||
return_0;
|
||||
|
||||
if (!info.exists || !info.suspended)
|
||||
return error_if_not_active ? 0 : 1;
|
||||
@ -671,16 +676,14 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 1)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_info(cmd, lv, &info, 1))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
return 1;
|
||||
|
||||
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
||||
log_error("LV %s/%s in use: not removing", lv->vg->name,
|
||||
log_error("LV %s/%s in use: not deactivating", lv->vg->name,
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
@ -741,12 +744,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_info(cmd, lv, &info, 0))
|
||||
return_0;
|
||||
|
||||
if (info.exists && !info.suspended)
|
||||
if (info.exists && !info.suspended && info.live_table)
|
||||
return 1;
|
||||
|
||||
if (exclusive)
|
||||
@ -783,10 +784,8 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!_lv_info(cmd, lv, 1, &info, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_lv_info(cmd, lv, 1, &info, 0))
|
||||
return_0;
|
||||
|
||||
if (info.exists)
|
||||
r = dev_manager_lv_mknodes(lv);
|
||||
|
@ -25,6 +25,8 @@ struct lvinfo {
|
||||
int major;
|
||||
int minor;
|
||||
int read_only;
|
||||
int live_table;
|
||||
int inactive_table;
|
||||
};
|
||||
|
||||
void set_activation(int activation);
|
||||
@ -34,7 +36,7 @@ int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int target_present(const char *target_name);
|
||||
int target_present(const char *target_name, int use_modprobe);
|
||||
|
||||
void activation_exit(void);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
float *percent, uint32_t *event_nr);
|
||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
|
||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||
|
@ -23,6 +23,9 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
int start_area, int areas);
|
||||
|
||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
struct deptree_node *node, int start_area, int areas);
|
||||
|
||||
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
|
||||
size_t bufsize, const char *desc);
|
||||
|
||||
|
@ -38,18 +38,13 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
struct lv_segment *seg,
|
||||
struct deptree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
/* error */
|
||||
|
||||
*target = "error";
|
||||
*params = '\0';
|
||||
|
||||
return 1;
|
||||
return dm_deptree_node_add_error_target(node, len);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
@ -57,8 +52,10 @@ static int _target_present(void)
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("error");
|
||||
/* Reported truncated in older kernels */
|
||||
if (!checked &&
|
||||
(target_present("error", 0) || target_present("erro", 0)))
|
||||
present = 1;
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
@ -74,7 +71,7 @@ static struct segtype_handler _error_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
@ -84,16 +81,14 @@ struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype = dm_malloc(sizeof(*segtype));
|
||||
|
||||
if (!segtype) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!segtype)
|
||||
return_NULL;
|
||||
|
||||
segtype->cmd = cmd;
|
||||
segtype->ops = &_error_ops;
|
||||
segtype->name = "error";
|
||||
segtype->private = NULL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
|
||||
|
||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||
|
||||
|
@ -124,4 +124,8 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
#define log_sys_debug(x, y) \
|
||||
log_debug("%s: %s failed: %s", y, x, strerror(errno))
|
||||
|
||||
#define return_0 do { stack; return 0; } while (0)
|
||||
#define return_NULL do { stack; return NULL; } while (0)
|
||||
#define goto_out do { stack; goto out; } while (0)
|
||||
|
||||
#endif
|
||||
|
@ -204,10 +204,8 @@ int create_mirror_layers(struct alloc_handle *ah,
|
||||
MIRROR_IMAGE);
|
||||
|
||||
/* Already got a non-mirrored area to be converted? */
|
||||
if (!first_area) {
|
||||
if (first_area)
|
||||
_move_lv_segments(img_lvs[0], lv);
|
||||
lv->status |= MIRRORED;
|
||||
}
|
||||
|
||||
if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
|
||||
0, region_size, log_lv)) {
|
||||
@ -216,6 +214,8 @@ int create_mirror_layers(struct alloc_handle *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv->status |= MIRRORED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -31,12 +31,14 @@ struct dev_manager;
|
||||
#define SEG_SNAPSHOT 0x00000008
|
||||
#define SEG_FORMAT1_SUPPORT 0x00000010
|
||||
#define SEG_VIRTUAL 0x00000020
|
||||
#define SEG_CANNOT_BE_ZEROED 0x00000040
|
||||
|
||||
#define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
|
||||
#define seg_is_striped(seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
|
||||
#define seg_is_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0)
|
||||
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
|
||||
#define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
|
||||
#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
|
||||
|
||||
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
|
||||
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
|
||||
@ -64,12 +66,11 @@ struct segtype_handler {
|
||||
struct dm_hash_table * pv_hash);
|
||||
int (*merge_segments) (struct lv_segment * seg1,
|
||||
struct lv_segment * seg2);
|
||||
int (*compose_target_line) (struct dev_manager * dm, struct dm_pool * mem,
|
||||
struct config_tree * cft,
|
||||
void **target_state,
|
||||
struct lv_segment * seg, char *params,
|
||||
size_t paramsize, const char **target,
|
||||
int *pos, uint32_t *pvmove_mirror_count);
|
||||
int (*add_target_line) (struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct deptree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count);
|
||||
int (*target_percent) (void **target_state, struct dm_pool * mem,
|
||||
struct config_tree * cft,
|
||||
struct lv_segment * seg, char *params,
|
||||
|
@ -165,118 +165,6 @@ static struct mirror_state *_init_target(struct dm_pool *mem,
|
||||
return mirr_state;
|
||||
}
|
||||
|
||||
static int _compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
int areas, uint32_t region_size)
|
||||
{
|
||||
int tw;
|
||||
char devbuf[10];
|
||||
const char *clustered = "";
|
||||
char *dlid;
|
||||
|
||||
/*
|
||||
* Use clustered mirror log for non-exclusive activation
|
||||
* in clustered VG.
|
||||
*/
|
||||
if ((!(seg->lv->status & ACTIVATE_EXCL) &&
|
||||
(seg->lv->vg->status & CLUSTERED)))
|
||||
clustered = "cluster ";
|
||||
|
||||
if (!seg->log_lv)
|
||||
tw = lvm_snprintf(params, paramsize, "%score 1 %u %u ",
|
||||
clustered, region_size, areas);
|
||||
else {
|
||||
if (!(dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!build_dev_string(dm, dlid, devbuf,
|
||||
sizeof(devbuf), "log")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME add sync parm? */
|
||||
tw = lvm_snprintf(params, paramsize, "%sdisk 2 %s %u %u ",
|
||||
clustered, devbuf, region_size, areas);
|
||||
}
|
||||
|
||||
if (tw < 0) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos += tw;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
int mirror_status = MIRR_RUNNING;
|
||||
int areas = seg->area_count;
|
||||
int start_area = 0u;
|
||||
uint32_t region_size, region_max;
|
||||
int ret;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _init_target(mem, cft);
|
||||
|
||||
mirr_state = *target_state;
|
||||
|
||||
/* mirror log_type #log_params [log_params]*
|
||||
* #mirrors [device offset]+
|
||||
*/
|
||||
if (seg->status & PVMOVE) {
|
||||
if (seg->extents_copied == seg->area_len) {
|
||||
mirror_status = MIRR_COMPLETED;
|
||||
start_area = 1;
|
||||
} else if ((*pvmove_mirror_count)++) {
|
||||
mirror_status = MIRR_DISABLED;
|
||||
areas = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mirror_status != MIRR_RUNNING) {
|
||||
*target = "linear";
|
||||
} else {
|
||||
*target = "mirror";
|
||||
|
||||
if (!(seg->status & PVMOVE)) {
|
||||
if (!seg->region_size) {
|
||||
log_error("Missing region size for mirror segment.");
|
||||
return 0;
|
||||
}
|
||||
region_size = seg->region_size;
|
||||
} else {
|
||||
/* Find largest power of 2 region size unit we can use */
|
||||
region_max = (1 << (ffs(seg->area_len) - 1)) *
|
||||
seg->lv->vg->extent_size;
|
||||
|
||||
region_size = mirr_state->default_region_size;
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
log_verbose("Using reduced mirror region size of %u sectors",
|
||||
region_size);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = _compose_log_line(dm, seg, params, paramsize, pos,
|
||||
areas, region_size)) <= 0) {
|
||||
stack;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return compose_areas_line(dm, seg, params, paramsize, pos, start_area,
|
||||
areas);
|
||||
}
|
||||
|
||||
static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct config_tree *cft, struct lv_segment *seg,
|
||||
char *params, uint64_t *total_numerator,
|
||||
@ -328,13 +216,109 @@ static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
|
||||
struct deptree_node *node, uint32_t area_count, uint32_t region_size)
|
||||
{
|
||||
unsigned clustered = 0;
|
||||
char *log_dlid = NULL;
|
||||
|
||||
/*
|
||||
* Use clustered mirror log for non-exclusive activation
|
||||
* in clustered VG.
|
||||
*/
|
||||
if ((!(seg->lv->status & ACTIVATE_EXCL) &&
|
||||
(seg->lv->vg->status & CLUSTERED)))
|
||||
clustered = 1;
|
||||
|
||||
if (seg->log_lv &&
|
||||
!(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
|
||||
log_error("Failed to build uuid for log LV %s.",
|
||||
seg->log_lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Add sync parm? */
|
||||
return dm_deptree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count);
|
||||
}
|
||||
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct deptree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
uint32_t area_count = seg->area_count;
|
||||
int start_area = 0u;
|
||||
int mirror_status = MIRR_RUNNING;
|
||||
uint32_t region_size, region_max;
|
||||
int r;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _init_target(mem, cft);
|
||||
|
||||
mirr_state = *target_state;
|
||||
|
||||
/*
|
||||
* For pvmove, only have one mirror segment RUNNING at once.
|
||||
* Segments before this are COMPLETED and use 2nd area.
|
||||
* Segments after this are DISABLED and use 1st area.
|
||||
*/
|
||||
if (seg->status & PVMOVE) {
|
||||
if (seg->extents_copied == seg->area_len) {
|
||||
mirror_status = MIRR_COMPLETED;
|
||||
start_area = 1;
|
||||
} else if ((*pvmove_mirror_count)++) {
|
||||
mirror_status = MIRR_DISABLED;
|
||||
area_count = 1;
|
||||
}
|
||||
/* else MIRR_RUNNING */
|
||||
}
|
||||
|
||||
if (mirror_status != MIRR_RUNNING) {
|
||||
if (!dm_deptree_node_add_linear_target(node, len))
|
||||
return_0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(seg->status & PVMOVE)) {
|
||||
if (!seg->region_size) {
|
||||
log_error("Missing region size for mirror segment.");
|
||||
return 0;
|
||||
}
|
||||
region_size = seg->region_size;
|
||||
} else {
|
||||
/* Find largest power of 2 region size unit we can use */
|
||||
region_max = (1 << (ffs(seg->area_len) - 1)) *
|
||||
seg->lv->vg->extent_size;
|
||||
|
||||
region_size = mirr_state->default_region_size;
|
||||
if (region_max < region_size) {
|
||||
region_size = region_max;
|
||||
log_verbose("Using reduced mirror region size of %u sectors",
|
||||
region_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dm_deptree_node_add_mirror_target(node, len))
|
||||
return_0;
|
||||
|
||||
if ((r = _add_log(dm, seg, node, area_count, region_size)) <= 0) {
|
||||
stack;
|
||||
return r;
|
||||
}
|
||||
|
||||
done:
|
||||
return add_areas_line(dm, seg, node, start_area, seg->area_count);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("mirror");
|
||||
present = target_present("mirror", 1);
|
||||
|
||||
checked = 1;
|
||||
|
||||
@ -354,7 +338,7 @@ static struct segtype_handler _mirrored_ops = {
|
||||
text_import:_text_import,
|
||||
text_export:_text_export,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
add_target_line:_add_target_line,
|
||||
target_percent:_target_percent,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
|
@ -130,15 +130,15 @@ static void _quote_hyphens(char **out, const char *src)
|
||||
/*
|
||||
* <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
|
||||
*/
|
||||
char *build_dm_name(struct dm_pool *mem, const char *vg,
|
||||
const char *lv, const char *layer)
|
||||
char *build_dm_name(struct dm_pool *mem, const char *vgname,
|
||||
const char *lvname, const char *layer)
|
||||
{
|
||||
size_t len = 1;
|
||||
int hyphens = 1;
|
||||
char *r, *out;
|
||||
|
||||
_count_hyphens(vg, &len, &hyphens);
|
||||
_count_hyphens(lv, &len, &hyphens);
|
||||
_count_hyphens(vgname, &len, &hyphens);
|
||||
_count_hyphens(lvname, &len, &hyphens);
|
||||
|
||||
if (layer && *layer) {
|
||||
_count_hyphens(layer, &len, &hyphens);
|
||||
@ -148,14 +148,15 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
|
||||
len += hyphens;
|
||||
|
||||
if (!(r = dm_pool_alloc(mem, len))) {
|
||||
stack;
|
||||
log_error("build_dm_name: Allocation failed for %" PRIsize_t
|
||||
" for %s %s %s.", len, vgname, lvname, layer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = r;
|
||||
_quote_hyphens(&out, vg);
|
||||
_quote_hyphens(&out, vgname);
|
||||
*out++ = '-';
|
||||
_quote_hyphens(&out, lv);
|
||||
_quote_hyphens(&out, lvname);
|
||||
|
||||
if (layer && *layer) {
|
||||
*out++ = '-';
|
||||
@ -174,6 +175,7 @@ static char *_unquote(char *component)
|
||||
{
|
||||
char *c = component;
|
||||
char *o = c;
|
||||
char *r;
|
||||
|
||||
while (*c) {
|
||||
if (*(c + 1)) {
|
||||
@ -189,8 +191,10 @@ static char *_unquote(char *component)
|
||||
c++;
|
||||
}
|
||||
|
||||
r = (*c) ? c + 1 : c;
|
||||
*o = '\0';
|
||||
return (c + 1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int split_dm_name(struct dm_pool *mem, const char *dmname,
|
||||
|
@ -369,24 +369,28 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
if (lv_info(lv->vg->cmd, lv, &info, 1) && info.exists) {
|
||||
if (info.suspended)
|
||||
repstr[4] = 's'; /* Suspended */
|
||||
else
|
||||
else if (info.live_table)
|
||||
repstr[4] = 'a'; /* Active */
|
||||
if (info.open_count)
|
||||
repstr[5] = 'o'; /* Open */
|
||||
else if (info.inactive_table)
|
||||
repstr[4] = 'i'; /* Inactive with table */
|
||||
else
|
||||
repstr[5] = '-';
|
||||
repstr[4] = 'd'; /* Inactive without table */
|
||||
|
||||
/* Snapshot dropped? */
|
||||
if ((snap_seg = find_cow(lv)) &&
|
||||
if (info.live_table && (snap_seg = find_cow(lv)) &&
|
||||
(!lv_snapshot_percent(snap_seg->cow, &snap_percent) ||
|
||||
snap_percent < 0 || snap_percent >= 100)) {
|
||||
repstr[0] = toupper(repstr[0]);
|
||||
if (info.suspended)
|
||||
repstr[4] = 'S';
|
||||
repstr[4] = 'S'; /* Susp Inv snapshot */
|
||||
else
|
||||
repstr[4] = 'I';
|
||||
repstr[4] = 'I'; /* Invalid snapshot */
|
||||
}
|
||||
|
||||
if (info.open_count)
|
||||
repstr[5] = 'o'; /* Open */
|
||||
else
|
||||
repstr[5] = '-';
|
||||
} else {
|
||||
repstr[4] = '-';
|
||||
repstr[5] = '-';
|
||||
|
@ -115,8 +115,8 @@ static int _target_present(void)
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("snapshot") &&
|
||||
target_present("snapshot-origin");
|
||||
present = target_present("snapshot", 1) &&
|
||||
target_present("snapshot-origin", 0);
|
||||
|
||||
checked = 1;
|
||||
|
||||
|
@ -106,7 +106,8 @@ static int _segments_compatible(struct lv_segment *first,
|
||||
unsigned s;
|
||||
|
||||
if ((first->area_count != second->area_count) ||
|
||||
(first->stripe_size != second->stripe_size)) return 0;
|
||||
(first->stripe_size != second->stripe_size))
|
||||
return 0;
|
||||
|
||||
for (s = 0; s < first->area_count; s++) {
|
||||
|
||||
@ -150,32 +151,25 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
struct lv_segment *seg,
|
||||
struct deptree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
/* linear [device offset]+
|
||||
* striped #stripes stripe_size [device offset]+ */
|
||||
|
||||
if (seg->area_count == 1)
|
||||
*target = "linear";
|
||||
else if (seg->area_count > 1) {
|
||||
*target = "striped";
|
||||
if ((*pos = lvm_snprintf(params, paramsize, "%u %u ",
|
||||
seg->area_count,
|
||||
seg->stripe_size)) < 0) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
log_error("Internal error: striped target with no stripes");
|
||||
if (!seg->area_count) {
|
||||
log_error("Internal error: striped add_target_line called "
|
||||
"with no areas for %s.", seg->lv->name);
|
||||
return 0;
|
||||
}
|
||||
if (seg->area_count == 1) {
|
||||
if (!dm_deptree_node_add_linear_target(node, len))
|
||||
return_0;
|
||||
} else if (!dm_deptree_node_add_striped_target(node, len,
|
||||
seg->stripe_size))
|
||||
return_0;
|
||||
|
||||
return compose_areas_line(dm, seg, params, paramsize, pos, 0u,
|
||||
seg->area_count);
|
||||
return add_areas_line(dm, seg, node, 0u, seg->area_count);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
@ -184,7 +178,8 @@ static int _target_present(void)
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("linear") && target_present("striped");
|
||||
present = target_present("linear", 0) &&
|
||||
target_present("striped", 0);
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
@ -204,7 +199,7 @@ static struct segtype_handler _striped_ops = {
|
||||
text_export:_text_export,
|
||||
merge_segments:_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
|
@ -38,18 +38,13 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _compose_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
struct lv_segment *seg,
|
||||
struct deptree_node *node, uint64_t len,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
/* zero */
|
||||
|
||||
*target = "zero";
|
||||
*params = '\0';
|
||||
|
||||
return 1;
|
||||
return dm_deptree_node_add_zero_target(node, len);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
@ -58,7 +53,7 @@ static int _target_present(void)
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("zero");
|
||||
present = target_present("zero", 0);
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
@ -74,7 +69,7 @@ static struct segtype_handler _zero_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
@ -93,7 +88,7 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd)
|
||||
segtype->ops = &_zero_ops;
|
||||
segtype->name = "zero";
|
||||
segtype->private = NULL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
|
||||
|
||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||
|
||||
|
@ -55,7 +55,8 @@ changes, for example during \fBpvmove\fP (8).
|
||||
.IP 4 3
|
||||
fixed (m)inor
|
||||
.IP 5 3
|
||||
State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot
|
||||
State: (a)ctive, (s)uspended, (I)nvalid snapshot, invalid (S)uspended snapshot,
|
||||
mapped (d)evice present without tables, mapped device present with (i)nactive table
|
||||
.IP 6 3
|
||||
device (o)pen
|
||||
.RE
|
||||
|
@ -359,7 +359,8 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
|
||||
/*
|
||||
* Should we zero the lv.
|
||||
*/
|
||||
lp->zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n");
|
||||
lp->zero = strcmp(arg_str_value(cmd, zero_ARG,
|
||||
(lp->segtype->flags & SEG_CANNOT_BE_ZEROED) ? "n" : "y"), "n");
|
||||
|
||||
/*
|
||||
* Alloc policy
|
||||
|
@ -20,6 +20,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct lvinfo info;
|
||||
struct logical_volume *origin = NULL;
|
||||
|
||||
vg = lv->vg;
|
||||
|
||||
@ -74,6 +75,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!archive(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* FIXME Snapshot commit out of sequence if it fails after here? */
|
||||
if (!deactivate_lv(cmd, lv)) {
|
||||
log_error("Unable to deactivate logical volume \"%s\"",
|
||||
lv->name);
|
||||
@ -81,6 +83,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
}
|
||||
|
||||
if (lv_is_cow(lv)) {
|
||||
origin = find_cow(lv)->origin;
|
||||
log_verbose("Removing snapshot %s", lv->name);
|
||||
if (!vg_remove_snapshot(lv)) {
|
||||
stack;
|
||||
@ -103,6 +106,14 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!vg_commit(vg))
|
||||
return ECMD_FAILED;
|
||||
|
||||
/* If no snapshots left, reload without -real. */
|
||||
if (origin && !lv_is_origin(origin)) {
|
||||
if (!suspend_lv(cmd, origin))
|
||||
log_error("Failed to refresh %s without snapshot.", origin->name);
|
||||
else if (!resume_lv(cmd, origin))
|
||||
log_error("Failed to resume %s.", origin->name);
|
||||
}
|
||||
|
||||
log_print("Logical volume \"%s\" successfully removed", lv->name);
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user