mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
cleanup: use dm_get_status_mirror
Use libdm function to parse mirror status report.
This commit is contained in:
parent
6336ef98d4
commit
86e7894ecc
@ -1,5 +1,6 @@
|
||||
Version 2.02.137 -
|
||||
=====================================
|
||||
Use dm_get_status_mirror() instead of individual parsers.
|
||||
Add mem pool arg for check_transient_status() target function.
|
||||
Avoid misleading error with -m is omitted with lvconvert to raid types.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
Version 1.02.113 -
|
||||
=====================================
|
||||
Mirror plugin in dmeventd uses dm_get_status_mirror().
|
||||
Add dm_get_status_mirror() for parsing mirror status line.
|
||||
|
||||
Version 1.02.112 - 28th November 2015
|
||||
|
@ -31,8 +31,9 @@ struct dso_state {
|
||||
|
||||
DM_EVENT_LOG_FN("mirr")
|
||||
|
||||
static int _process_status_code(const char status_code, const char *dev_name,
|
||||
const char *dev_type, int r)
|
||||
static void _process_status_code(dm_status_mirror_health_t health,
|
||||
uint32_t major, uint32_t minor,
|
||||
const char *dev_type, int *r)
|
||||
{
|
||||
/*
|
||||
* A => Alive - No failures
|
||||
@ -42,90 +43,60 @@ static int _process_status_code(const char status_code, const char *dev_name,
|
||||
* R => Read - A read failure occurred, mirror data unaffected
|
||||
* U => Unclassified failure (bug)
|
||||
*/
|
||||
if (status_code == 'F') {
|
||||
log_error("%s device %s flush failed.", dev_type, dev_name);
|
||||
r = ME_FAILURE;
|
||||
} else if (status_code == 'S')
|
||||
log_error("%s device %s sync failed.", dev_type, dev_name);
|
||||
else if (status_code == 'R')
|
||||
log_error("%s device %s read failed.", dev_type, dev_name);
|
||||
else if (status_code != 'A') {
|
||||
log_error("%s device %s has failed (%c).",
|
||||
dev_type, dev_name, status_code);
|
||||
r = ME_FAILURE;
|
||||
switch (health) {
|
||||
case DM_STATUS_MIRROR_ALIVE:
|
||||
return;
|
||||
case DM_STATUS_MIRROR_FLUSH_FAILED:
|
||||
log_error("%s device %u:%u flush failed.",
|
||||
dev_type, major, minor);
|
||||
*r = ME_FAILURE;
|
||||
break;
|
||||
case DM_STATUS_MIRROR_SYNC_FAILED:
|
||||
log_error("%s device %u:%u sync failed.",
|
||||
dev_type, major, minor);
|
||||
break;
|
||||
case DM_STATUS_MIRROR_READ_FAILED:
|
||||
log_error("%s device %u:%u read failed.",
|
||||
dev_type, major, minor);
|
||||
break;
|
||||
default:
|
||||
log_error("%s device %u:%u has failed (%c).",
|
||||
dev_type, major, minor, (char)health);
|
||||
*r = ME_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
static int _get_mirror_event(struct dso_state *state, char *params)
|
||||
{
|
||||
int i, r = ME_INSYNC;
|
||||
char **args = NULL;
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p = NULL;
|
||||
int log_argc, num_devs;
|
||||
int r = ME_INSYNC;
|
||||
unsigned i;
|
||||
struct dm_status_mirror *ms;
|
||||
|
||||
/*
|
||||
* dm core parms: 0 409600 mirror
|
||||
* Mirror core parms: 2 253:4 253:5 400/400
|
||||
* New-style failure params: 1 AA
|
||||
* New-style log params: 3 cluster 253:3 A
|
||||
* or 3 disk 253:3 A
|
||||
* or 1 core
|
||||
*/
|
||||
|
||||
/* number of devices */
|
||||
if (!dm_split_words(params, 1, 0, &p))
|
||||
goto out_parse;
|
||||
|
||||
if (!(num_devs = atoi(p)) ||
|
||||
(num_devs > DEFAULT_MIRROR_MAX_IMAGES) || (num_devs < 0))
|
||||
goto out_parse;
|
||||
p += strlen(p) + 1;
|
||||
|
||||
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||
goto out_parse;
|
||||
|
||||
/* FIXME: Code differs from lib/mirror/mirrored.c */
|
||||
dev_status_str = args[2 + num_devs];
|
||||
log_argc = atoi(args[3 + num_devs]);
|
||||
log_status_str = args[3 + num_devs + log_argc];
|
||||
sync_str = args[num_devs];
|
||||
if (dm_get_status_mirror(state->mem, params, &ms))
|
||||
goto_out;
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++)
|
||||
r = _process_status_code(dev_status_str[i], args[i],
|
||||
i ? "Secondary mirror" : "Primary mirror", r);
|
||||
for (i = 0; i < ms->dev_count; ++i)
|
||||
_process_status_code(ms->devs[i].health,
|
||||
ms->devs[i].major, ms->devs[i].minor,
|
||||
i ? "Secondary mirror" : "Primary mirror", &r);
|
||||
|
||||
/* Check for bad disk log device */
|
||||
if (log_argc > 1)
|
||||
r = _process_status_code(log_status_str[0],
|
||||
args[2 + num_devs + log_argc],
|
||||
"Log", r);
|
||||
for (i = 0; i < ms->log_count; ++i)
|
||||
_process_status_code(ms->logs[i].health,
|
||||
ms->logs[i].major, ms->logs[i].minor,
|
||||
"Log", &r);
|
||||
|
||||
if (r == ME_FAILURE)
|
||||
goto out;
|
||||
/* Ignore if not in-sync */
|
||||
if ((r == ME_INSYNC) && (ms->insync_regions != ms->total_regions))
|
||||
r = ME_IGNORE;
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
r = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else
|
||||
goto out_parse;
|
||||
dm_pool_free(state->mem, ms);
|
||||
|
||||
out:
|
||||
dm_free(args);
|
||||
return r;
|
||||
|
||||
out_parse:
|
||||
dm_free(args);
|
||||
out:
|
||||
log_error("Unable to parse mirror status string.");
|
||||
|
||||
return ME_IGNORE;
|
||||
@ -172,7 +143,7 @@ void process_event(struct dm_task *dmt,
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
switch(_get_mirror_event(state, params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -246,79 +246,6 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* _parse_mirror_status
|
||||
* @mirror_status_string
|
||||
* @image_health: return for allocated copy of image health characters
|
||||
* @log_device: return for 'dev_t' of log device
|
||||
* @log_health: NULL if corelog, otherwise dm_malloc'ed log health char which
|
||||
* the caller must free
|
||||
*
|
||||
* This function takes the mirror status string, breaks it up and returns
|
||||
* its components. For now, we only return the health characters. This
|
||||
* is an internal function. If there are more things we want to return
|
||||
* later, we can do that then.
|
||||
*
|
||||
* Returns: 1 on success, 0 on failure
|
||||
*/
|
||||
static int _parse_mirror_status(char *mirror_status_str,
|
||||
char **images_health,
|
||||
dev_t *log_dev, char **log_health)
|
||||
{
|
||||
int major, minor;
|
||||
char *p = NULL;
|
||||
char **args, **log_args;
|
||||
unsigned num_devs, log_argc;
|
||||
|
||||
*images_health = NULL;
|
||||
*log_health = NULL;
|
||||
*log_dev = 0;
|
||||
|
||||
if (!dm_split_words(mirror_status_str, 1, 0, &p) ||
|
||||
!(num_devs = (unsigned) atoi(p)))
|
||||
/* On errors, we must assume the mirror is to be avoided */
|
||||
return_0;
|
||||
|
||||
p += strlen(p) + 1;
|
||||
args = alloca((num_devs + 5) * sizeof(char *));
|
||||
|
||||
if ((unsigned)dm_split_words(p, num_devs + 4, 0, args) < num_devs + 4)
|
||||
return_0;
|
||||
|
||||
log_argc = (unsigned) atoi(args[3 + num_devs]);
|
||||
log_args = alloca(log_argc * sizeof(char *));
|
||||
|
||||
if ((unsigned)dm_split_words(args[3 + num_devs] + strlen(args[3 + num_devs]) + 1,
|
||||
log_argc, 0, log_args) < log_argc)
|
||||
return_0;
|
||||
|
||||
if (!strcmp(log_args[0], "disk")) {
|
||||
if (!(*log_health = dm_strdup(log_args[2]))) {
|
||||
log_error("Allocation of log string failed.");
|
||||
return 0;
|
||||
}
|
||||
if (sscanf(log_args[1], "%d:%d", &major, &minor) != 2) {
|
||||
log_error("Failed to parse log's device number from %s.", log_args[1]);
|
||||
goto out;
|
||||
}
|
||||
*log_dev = MKDEV((dev_t)major, minor);
|
||||
}
|
||||
|
||||
if (!(*images_health = dm_strdup(args[2 + num_devs]))) {
|
||||
log_error("Allocation of images string failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
out:
|
||||
dm_free(*log_health);
|
||||
*log_health = NULL;
|
||||
*log_dev = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore_blocked_mirror_devices
|
||||
* @dev
|
||||
@ -349,44 +276,45 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
uint64_t start, uint64_t length,
|
||||
char *mirror_status_str)
|
||||
{
|
||||
struct dm_pool *mem;
|
||||
struct dm_status_mirror *sm;
|
||||
unsigned i, check_for_blocking = 0;
|
||||
dev_t log_dev;
|
||||
char *images_health, *log_health;
|
||||
uint64_t s,l;
|
||||
char *p, *params, *target_type = NULL;
|
||||
void *next = NULL;
|
||||
struct dm_task *dmt = NULL;
|
||||
int r = 0;
|
||||
struct device *tmp_dev;
|
||||
char buf[16];
|
||||
|
||||
if (!_parse_mirror_status(mirror_status_str,
|
||||
&images_health, &log_dev, &log_health))
|
||||
if (!(mem = dm_pool_create("blocked_mirrors", 128)))
|
||||
return_0;
|
||||
|
||||
for (i = 0; images_health[i]; i++)
|
||||
if (images_health[i] != 'A') {
|
||||
if (!dm_get_status_mirror(mem, mirror_status_str, &sm))
|
||||
goto_out;
|
||||
|
||||
for (i = 0; i < sm->dev_count; ++i)
|
||||
if (sm->devs[i].health != DM_STATUS_MIRROR_ALIVE) {
|
||||
log_debug_activation("%s: Mirror image %d marked as failed",
|
||||
dev_name(dev), i);
|
||||
check_for_blocking = 1;
|
||||
}
|
||||
|
||||
if (!check_for_blocking && log_dev) {
|
||||
if (log_health[0] != 'A') {
|
||||
if (!check_for_blocking && sm->log_count) {
|
||||
if (sm->logs[0].health != DM_STATUS_MIRROR_ALIVE) {
|
||||
log_debug_activation("%s: Mirror log device marked as failed",
|
||||
dev_name(dev));
|
||||
check_for_blocking = 1;
|
||||
} else {
|
||||
struct device *tmp_dev;
|
||||
char buf[16];
|
||||
|
||||
if (dm_snprintf(buf, sizeof(buf), "%d:%d",
|
||||
(int)MAJOR(log_dev),
|
||||
(int)MINOR(log_dev)) < 0)
|
||||
if (dm_snprintf(buf, sizeof(buf), "%u:%u",
|
||||
sm->logs[0].major, sm->logs[0].minor) < 0)
|
||||
goto_out;
|
||||
|
||||
if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 0)))
|
||||
goto_out;
|
||||
|
||||
tmp_dev->dev = log_dev;
|
||||
tmp_dev->dev = MKDEV((dev_t)sm->logs[0].major, sm->logs[0].minor);
|
||||
if (device_is_usable(tmp_dev, (struct dev_usable_check_params)
|
||||
{ .check_empty = 1,
|
||||
.check_blocked = 1,
|
||||
@ -440,8 +368,8 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
out:
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
dm_free(log_health);
|
||||
dm_free(images_health);
|
||||
|
||||
dm_pool_destroy(mem);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@ -168,161 +168,94 @@ static int _mirrored_target_percent(void **target_state,
|
||||
uint64_t *total_numerator,
|
||||
uint64_t *total_denominator)
|
||||
{
|
||||
uint64_t numerator, denominator;
|
||||
unsigned mirror_count, m;
|
||||
int used;
|
||||
char *pos = params;
|
||||
struct dm_status_mirror *sm;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _mirrored_init_target(mem, cmd);
|
||||
|
||||
/* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
|
||||
log_debug_activation("Mirror status: %s", params);
|
||||
if (!dm_get_status_mirror(mem, params, &sm))
|
||||
return_0;
|
||||
|
||||
if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) {
|
||||
log_error("Failure parsing mirror status mirror count: %s",
|
||||
params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
|
||||
for (m = 0; m < mirror_count; m++) {
|
||||
if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
|
||||
log_error("Failure parsing mirror status devices: %s",
|
||||
params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
}
|
||||
|
||||
if (sscanf(pos, FMTu64 "/" FMTu64 "%n", &numerator, &denominator,
|
||||
&used) != 2) {
|
||||
log_error("Failure parsing mirror status fraction: %s", params);
|
||||
return 0;
|
||||
}
|
||||
pos += used;
|
||||
|
||||
*total_numerator += numerator;
|
||||
*total_denominator += denominator;
|
||||
*total_numerator += sm->insync_regions;
|
||||
*total_denominator += sm->total_regions;
|
||||
|
||||
if (seg)
|
||||
seg->extents_copied = seg->area_len * numerator / denominator;
|
||||
seg->extents_copied = seg->area_len * sm->insync_regions / sm->total_regions;
|
||||
|
||||
*percent = dm_make_percent(numerator, denominator);
|
||||
*percent = dm_make_percent(sm->insync_regions, sm->total_regions);
|
||||
|
||||
dm_pool_free(mem, sm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _mirrored_transient_status(struct dm_pool *mem, struct lv_segment *seg, char *params)
|
||||
{
|
||||
unsigned i, j;
|
||||
struct logical_volume *lv = seg->lv;
|
||||
struct lvinfo info;
|
||||
char *p = NULL;
|
||||
char **args, **log_args;
|
||||
struct logical_volume **images;
|
||||
struct dm_status_mirror *sm;
|
||||
struct logical_volume *log;
|
||||
unsigned num_devs, log_argc;
|
||||
int failed = 0;
|
||||
char *status;
|
||||
struct logical_volume *lv = seg->lv;
|
||||
int failed = 0, r = 0;
|
||||
unsigned i, j;
|
||||
struct lvinfo info;
|
||||
|
||||
log_very_verbose("Mirrored transient status: \"%s\"", params);
|
||||
|
||||
/* number of devices */
|
||||
if (!dm_split_words(params, 1, 0, &p))
|
||||
if (!dm_get_status_mirror(mem, params, &sm))
|
||||
return_0;
|
||||
|
||||
if (!(num_devs = (unsigned) atoi(p)))
|
||||
return_0;
|
||||
|
||||
p += strlen(p) + 1;
|
||||
|
||||
if (num_devs > DEFAULT_MIRROR_MAX_IMAGES) {
|
||||
log_error("Unexpectedly many (%d) mirror images in %s.",
|
||||
num_devs, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args = alloca((num_devs + 5) * sizeof(char *));
|
||||
images = alloca(num_devs * sizeof(struct logical_volume *));
|
||||
|
||||
/* FIXME: dm_split_words() should return unsigned */
|
||||
if ((unsigned)dm_split_words(p, num_devs + 4, 0, args) < num_devs + 4)
|
||||
return_0;
|
||||
|
||||
log_argc = (unsigned) atoi(args[3 + num_devs]);
|
||||
|
||||
if (log_argc > 16) {
|
||||
log_error("Unexpectedly many (%d) log arguments in %s.",
|
||||
log_argc, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_args = alloca(log_argc * sizeof(char *));
|
||||
|
||||
if ((unsigned)dm_split_words(args[3 + num_devs] + strlen(args[3 + num_devs]) + 1,
|
||||
log_argc, 0, log_args) < log_argc)
|
||||
return_0;
|
||||
|
||||
if (num_devs != seg->area_count) {
|
||||
if (sm->dev_count != seg->area_count) {
|
||||
log_error("Active mirror has a wrong number of mirror images!");
|
||||
log_error("Metadata says %d, kernel says %d.", seg->area_count, num_devs);
|
||||
return 0;
|
||||
log_error("Metadata says %u, kernel says %u.",
|
||||
seg->area_count, sm->dev_count);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!strcmp(log_args[0], "disk")) {
|
||||
char buf[32];
|
||||
if (!strcmp(sm->log_type, "disk")) {
|
||||
log = first_seg(lv)->log_lv;
|
||||
if (!lv_info(lv->vg->cmd, log, 0, &info, 0, 0)) {
|
||||
log_error("Check for existence of mirror log %s failed.",
|
||||
log->name);
|
||||
return 0;
|
||||
display_lvname(log));
|
||||
goto out;
|
||||
}
|
||||
log_debug_activation("Found mirror log at %d:%d", info.major, info.minor);
|
||||
sprintf(buf, "%d:%d", info.major, info.minor);
|
||||
if (strcmp(buf, log_args[1])) {
|
||||
log_error("Mirror log mismatch. Metadata says %s, kernel says %s.",
|
||||
buf, log_args[1]);
|
||||
return 0;
|
||||
if (info.major != (int)sm->logs[0].major ||
|
||||
info.minor != (int)sm->logs[0].minor) {
|
||||
log_error("Mirror log mismatch. Metadata says %d:%d, kernel says %u:%u.",
|
||||
info.major, info.minor,
|
||||
sm->logs[0].major, sm->logs[0].minor);
|
||||
goto out;
|
||||
}
|
||||
log_very_verbose("Status of log (%s): %s", buf, log_args[2]);
|
||||
if (log_args[2][0] != 'A') {
|
||||
log_very_verbose("Status of log (%d:%d): %c.",
|
||||
info.major, info.minor,
|
||||
sm->logs[0].health);
|
||||
if (sm->logs[0].health != DM_STATUS_MIRROR_ALIVE) {
|
||||
log->status |= PARTIAL_LV;
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_devs; ++i)
|
||||
images[i] = NULL;
|
||||
|
||||
for (i = 0; i < seg->area_count; ++i) {
|
||||
char buf[32];
|
||||
if (!lv_info(lv->vg->cmd, seg_lv(seg, i), 0, &info, 0, 0)) {
|
||||
log_error("Check for existence of mirror image %s failed.",
|
||||
seg_lv(seg, i)->name);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
log_debug_activation("Found mirror image at %d:%d", info.major, info.minor);
|
||||
sprintf(buf, "%d:%d", info.major, info.minor);
|
||||
for (j = 0; j < num_devs; ++j) {
|
||||
if (!strcmp(buf, args[j])) {
|
||||
log_debug_activation("Match: metadata image %d matches kernel image %d", i, j);
|
||||
images[j] = seg_lv(seg, i);
|
||||
for (j = 0; j < sm->dev_count; ++j)
|
||||
if (info.major == (int)sm->devs[j].major &&
|
||||
info.minor == (int)sm->devs[j].minor) {
|
||||
log_very_verbose("Status of image %d: %c.",
|
||||
i, sm->devs[j].health);
|
||||
if (sm->devs[j].health != DM_STATUS_MIRROR_ALIVE) {
|
||||
seg_lv(seg, i)->status |= PARTIAL_LV;
|
||||
++failed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = args[2 + num_devs];
|
||||
|
||||
for (i = 0; i < num_devs; ++i) {
|
||||
if (!images[i]) {
|
||||
log_error("Failed to find image %d (%s).", i, args[i]);
|
||||
return 0;
|
||||
}
|
||||
log_very_verbose("Status of image %d: %c", i, status[i]);
|
||||
if (status[i] != 'A') {
|
||||
images[i]->status |= PARTIAL_LV;
|
||||
++failed;
|
||||
if (j == sm->dev_count) {
|
||||
log_error("Failed to find image %d (%d:%d).",
|
||||
i, info.major, info.minor);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +263,11 @@ static int _mirrored_transient_status(struct dm_pool *mem, struct lv_segment *se
|
||||
if (failed)
|
||||
vg_mark_partial_lvs(lv->vg, 0);
|
||||
|
||||
return 1;
|
||||
r = 1;
|
||||
out:
|
||||
dm_pool_free(mem, sm);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _add_log(struct dm_pool *mem, struct lv_segment *seg,
|
||||
|
Loading…
Reference in New Issue
Block a user