1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

RAID: Capture new RAID kernel sync_action status fields

I've updated the dm_status_raid structure and dm_get_status_raid()
function to make it handle the new kernel status fields that will
be coming in dm-raid v1.5.0.  It is backwards compatible with the
old status line - initializing the new fields to '0'.  The new
structure is also more amenable to future changes.  It includes a
'reserved' field that is currently initialized to zero but could
be used to hold flags describing new features.  It also now uses
pointers for the character strings instead of attempting to allocate
their space along with the structure (causing the size of the
structure to be variable).  This allows future fields to be appended.

The new fields that are available are:
 - sync_action : shows what the sync thread in the kernel is doing
                 (idle, frozen, resync, recover, check, repair, or
                 reshape)
 - mismatch_count: shows the number of discrepancies which were
                   found or repaired by a "check" or "repair"
                   process, respectively.
This commit is contained in:
Jonathan Brassow 2013-04-08 15:04:08 -05:00
parent c22e925ce4
commit 38f8f4a958
4 changed files with 68 additions and 14 deletions

View File

@ -809,8 +809,10 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
if (!(r = dev_manager_raid_status(dm, lv, &status)) ||
!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
status->dev_health)))
stack;
status->dev_health))) {
dev_manager_destroy(dm);
return_0;
}
cached_dev_health = *dev_health;
dev_manager_destroy(dm);

View File

@ -1031,7 +1031,6 @@ int dev_manager_raid_status(struct dev_manager *dm,
char *params = NULL;
const char *layer = lv_layer(lv);
/* Build dlid for the thin pool layer */
if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer)))
return_0;
@ -1051,6 +1050,12 @@ int dev_manager_raid_status(struct dev_manager *dm,
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
if (!type || strcmp(type, "raid")) {
log_debug("Expected raid segment type but got %s instead",
type ? type : "NULL");
goto out;
}
if (!dm_get_status_raid(dm->mem, params, status))
goto_out;

View File

@ -265,12 +265,22 @@ void *dm_get_next_target(struct dm_task *dmt,
*/
struct dm_pool;
/*
* dm_get_status_raid will allocate the dm_status_raid structure and
* the necessary character arrays from the mempool provided to the
* function. If the mempool is from a dev_manager struct (dm->mem),
* then the caller does not need to free the memory - simply calling
* dev_manager_destroy will do.
*/
struct dm_status_raid {
uint64_t reserved;
uint64_t total_regions;
uint64_t insync_regions;
uint64_t mismatch_count;
int dev_count;
char raid_type[16];
char dev_health[0];
char *raid_type;
char *dev_health;
char *sync_action;
};
int dm_get_status_raid(struct dm_pool *mem, const char *params,

View File

@ -2873,28 +2873,39 @@ int dm_tree_node_add_raid_target(struct dm_tree_node *node,
return 1;
}
/*
* Various RAID status versions include:
* Versions < 1.5.0 (4 fields):
* <raid_type> <#devs> <health_str> <sync_ratio>
* Versions 1.5.0+ (6 fields):
* <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
*/
int dm_get_status_raid(struct dm_pool *mem, const char *params,
struct dm_status_raid **status)
{
int dev_count;
const char *p;
int i;
const char *pp, *p;
struct dm_status_raid *s;
if (!params || !(p = strchr(params, ' '))) {
log_error("Failed to parse invalid raid params.");
return 0;
}
p++;
if (sscanf(p, "%d", &dev_count) != 1)
/* second field holds the device count */
if (sscanf(p, "%d", &i) != 1)
return_0;
s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid) + dev_count + 1);
if (!s) {
log_error("Failed to allocate raid status structure.");
return 0;
}
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
return_0;
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
return_0; /* memory is freed went pool is destroyed */
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1)))
return_0;
if (sscanf(params, "%s %d %s %" PRIu64 "/%" PRIu64,
s->raid_type,
@ -2908,6 +2919,32 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
*status = s;
/*
* All pre-1.5.0 version parameters are read. Now we check
* for additional 1.5.0+ parameters.
*
* Note that 'sync_action' will be NULL (and mismatch_count
* will be 0) if the kernel returns a pre-1.5.0 status.
*/
for (p = params, i = 0; i < 4; i++, p++)
if (!(p = strchr(p, ' ')))
return 1; /* return pre-1.5.0 status */
pp = p;
if (!(p = strchr(p, ' '))) {
log_error(INTERNAL_ERROR "Bad RAID status received.");
return 0;
}
p++;
if (!(s->sync_action = dm_pool_zalloc(mem, p - pp)))
return_0;
if (sscanf(pp, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) {
log_error("Failed to parse raid params: %s", params);
return 0;
}
return 1;
}