}
+#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"
+
static int
virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
char **const groups,
void *data)
{
virStorageVolDefPtr vol = NULL;
+ bool is_new_vol = false;
unsigned long long offset, size, length;
+ const char *regex_unit = "(\\S+)\\((\\S+)\\)";
+ char *regex = NULL;
+ regex_t *reg = NULL;
+ regmatch_t *vars = NULL;
+ char *p = NULL;
+ int i, err, nextents, nvars, ret = -1;
/* See if we're only looking for a specific volume */
if (data != NULL) {
return -1;
}
+ is_new_vol = true;
vol->type = VIR_STORAGE_VOL_BLOCK;
if ((vol->name = strdup(groups[0])) == NULL) {
virReportOOMError();
- virStorageVolDefFree(vol);
- return -1;
+ goto cleanup;
}
if (VIR_REALLOC_N(pool->volumes.objs,
pool->volumes.count + 1)) {
virReportOOMError();
- virStorageVolDefFree(vol);
- return -1;
+ goto cleanup;
}
pool->volumes.objs[pool->volumes.count++] = vol;
}
if (virAsprintf(&vol->target.path, "%s/%s",
pool->def->target.path, vol->name) < 0) {
virReportOOMError();
- virStorageVolDefFree(vol);
- return -1;
+ goto cleanup;
}
}
if (virAsprintf(&vol->backingStore.path, "%s/%s",
pool->def->target.path, groups[1]) < 0) {
virReportOOMError();
- virStorageVolDefFree(vol);
- return -1;
+ goto cleanup;
}
vol->backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2;
if (vol->key == NULL &&
(vol->key = strdup(groups[2])) == NULL) {
virReportOOMError();
- return -1;
+ goto cleanup;
}
if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
- return -1;
+ goto cleanup;
+ nextents = 1;
+ if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
+ if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed volume extent stripes value"));
+ goto cleanup;
+ }
+ }
/* Finally fill in extents information */
if (VIR_REALLOC_N(vol->source.extents,
- vol->source.nextent + 1) < 0) {
+ vol->source.nextent + nextents) < 0) {
virReportOOMError();
- return -1;
+ goto cleanup;
}
- if ((vol->source.extents[vol->source.nextent].path =
- strdup(groups[3])) == NULL) {
+ if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("malformed volume extent length value"));
+ goto cleanup;
+ }
+ if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("malformed volume extent size value"));
+ goto cleanup;
+ }
+
+ /* Now parse the "devices" feild seperately */
+ regex = strdup(regex_unit);
+
+ for (i = 1; i < nextents; i++) {
+ if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ /* "," is the seperator of "devices" field */
+ strcat(regex, ",");
+ strncat(regex, regex_unit, strlen(regex_unit));
+ }
+
+ if (VIR_ALLOC(reg) < 0) {
virReportOOMError();
- return -1;
+ goto cleanup;
}
- if (virStrToLong_ull(groups[4], NULL, 10, &offset) < 0) {
- virStorageReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed volume extent offset value"));
- return -1;
+ /* Each extent has a "path:offset" pair, and vars[0] will
+ * be the whole matched string.
+ */
+ nvars = (nextents * 2) + 1;
+ if (VIR_ALLOC_N(vars, nvars) < 0) {
+ virReportOOMError();
+ goto cleanup;
}
- if (virStrToLong_ull(groups[5], NULL, 10, &length) < 0) {
+
+ err = regcomp(reg, regex, REG_EXTENDED);
+ if (err != 0) {
+ char error[100];
+ regerror(err, reg, error, sizeof(error));
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed volume extent length value"));
- return -1;
+ _("Failed to compile regex %s"),
+ error);
+ goto cleanup;
}
- if (virStrToLong_ull(groups[6], NULL, 10, &size) < 0) {
- virStorageReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("malformed volume extent size value"));
- return -1;
+
+ if (regexec(reg, groups[3], nvars, vars, 0) != 0) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed volume extent devices value"));
+ goto cleanup;
}
- vol->source.extents[vol->source.nextent].start = offset * size;
- vol->source.extents[vol->source.nextent].end = (offset * size) + length;
- vol->source.nextent++;
+ p = groups[3];
- return 0;
+ /* vars[0] is skipped */
+ for (i = 0; i < nextents; i++) {
+ int j, len;
+ const char *offset_str = NULL;
+
+ j = (i * 2) + 1;
+ len = vars[j].rm_eo - vars[j].rm_so;
+ p[vars[j].rm_eo] = '\0';
+
+ if ((vol->source.extents[vol->source.nextent].path =
+ strndup(p + vars[j].rm_so, len)) == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
+ if (!(offset_str = strndup(p + vars[j + 1].rm_so, len))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed volume extent offset value"));
+ goto cleanup;
+ }
+
+ VIR_FREE(offset_str);
+
+ vol->source.extents[vol->source.nextent].start = offset * size;
+ vol->source.extents[vol->source.nextent].end = (offset * size) + length;
+ vol->source.nextent++;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(regex);
+ VIR_FREE(reg);
+ VIR_FREE(vars);
+ if (is_new_vol && (ret == -1))
+ virStorageVolDefFree(vol);
+ return ret;
}
static int
*
* NB Encrypted logical volumes can print ':' in their name, so it is
* not a suitable separator (rhbz 470693).
+ * NB "devices" field has multiple device paths and "," if the volume is
+ * striped, so "," is not a suitable separator either (rhbz 727474).
*/
const char *regexes[] = {
- "^\\s*(\\S+),(\\S*),(\\S+),(\\S+)\\((\\S+)\\),(\\S+),([0-9]+),?\\s*$"
+ "^\\s*(\\S+)#(\\S*)#(\\S+)#(\\S+)#(\\S+)#([0-9]+)#(\\S+)#([0-9]+)#?\\s*$"
};
int vars[] = {
- 7
+ 8
};
const char *prog[] = {
- LVS, "--separator", ",", "--noheadings", "--units", "b",
+ LVS, "--separator", "#", "--noheadings", "--units", "b",
"--unbuffered", "--nosuffix", "--options",
- "lv_name,origin,uuid,devices,seg_size,vg_extent_size",
+ "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size",
pool->def->source.name, NULL
};