1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-30 17:18:21 +03:00

raid: Tidy dm_get_status_raid. [HM]

This commit is contained in:
Alasdair G Kergon 2016-03-22 21:39:52 +00:00
parent cf39346697
commit 1056894f1f

View File

@ -66,6 +66,23 @@ static const char *_skip_fields(const char *p, unsigned nr)
return p;
}
/*
* Count number of single-space delimited fields.
* Number of fields is number of spaces plus one.
*/
static unsigned _count_fields(const char *p)
{
unsigned nr = 1;
if (!p || !*p)
return 0;
while ((p = _skip_fields(p, 1)))
nr++;
return nr;
}
/*
* Various RAID status versions include:
* Versions < 1.5.0 (4 fields):
@ -77,69 +94,71 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
struct dm_status_raid **status)
{
int i;
const char *pp, *p;
struct dm_status_raid *s;
unsigned num_fields;
const char *p, *pp, *msg_fields = "";
struct dm_status_raid *s = NULL;
if (!params || !(p = strchr(params, ' '))) {
log_error("Failed to parse invalid raid params.");
return 0;
}
p++;
if ((num_fields = _count_fields(params)) < 4)
goto_bad;
/* second field holds the device count */
if (sscanf(p, "%d", &i) != 1)
return_0;
/* Second field holds the device count */
msg_fields = "<#devs> ";
if (!(p = _skip_fields(params, 1)) || (sscanf(p, "%d", &i) != 1))
goto_bad;
msg_fields = "";
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
return_0;
goto_bad;
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
goto_bad; /* memory is freed when pool is destroyed */
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1)))
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1))) /* Space for health chars */
goto_bad;
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64,
s->raid_type,
&s->dev_count,
s->dev_health,
&s->insync_regions,
&s->total_regions) != 5) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
*status = s;
&s->total_regions) != 5)
goto_bad;
/*
* All pre-1.5.0 version parameters are read. Now we check
* for additional 1.5.0+ parameters.
* for additional 1.5.0+ parameters (i.e. num_fields at least 6).
*
* 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 */
if (num_fields < 6)
goto out;
pp = p;
if (!(p = strchr(p, ' '))) {
log_error(INTERNAL_ERROR "Bad RAID status received.");
goto bad;
}
p++;
msg_fields = "<sync_action> and <mismatch_cnt> ";
if (!(s->sync_action = dm_pool_zalloc(mem, p - pp)))
/* Skip pre-1.5.0 params */
if (!(p = _skip_fields(params, 4)) || !(pp = _skip_fields(p, 1)))
goto_bad;
if (sscanf(pp, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) {
log_error("Failed to parse raid params: %s", params);
goto bad;
}
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
goto_bad;
if (sscanf(p, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2)
goto_bad;
out:
*status = s;
return 1;
bad:
dm_pool_free(mem, s);
log_error("Failed to parse %sraid params: %s", msg_fields, params);
if (s)
dm_pool_free(mem, s);
*status = NULL;
return 0;
}