diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 387a2db2e64c646b2189abdfef98562b678070e7..5bd5c955a4813b41d18c29f4fd582fdc39801660 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1423,11 +1423,16 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src, virStorageSourcePtr backingStore) { g_autoptr(virJSONValue) props = NULL; + const char *storagenode = src->nodestorage; + + if (src->sliceStorage && + src->format != VIR_STORAGE_FILE_RAW) + storagenode = src->sliceStorage->nodename; if (!(props = qemuBlockStorageSourceGetBlockdevFormatProps(src))) return NULL; - if (virJSONValueObjectAppendString(props, "file", src->nodestorage) < 0) + if (virJSONValueObjectAppendString(props, "file", storagenode) < 0) return NULL; if (backingStore) { @@ -1456,6 +1461,32 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src, } +static virJSONValuePtr +qemuBlockStorageSourceGetBlockdevStorageSliceProps(virStorageSourcePtr src) +{ + g_autoptr(virJSONValue) props = NULL; + + if (qemuBlockNodeNameValidate(src->sliceStorage->nodename) < 0) + return NULL; + + if (virJSONValueObjectCreate(&props, + "s:driver", "raw", + "s:node-name", src->sliceStorage->nodename, + "U:offset", src->sliceStorage->offset, + "U:size", src->sliceStorage->size, + "s:file", src->nodestorage, + "b:auto-read-only", true, + "s:discard", "unmap", + NULL) < 0) + return NULL; + + if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, props) < 0) + return NULL; + + return g_steal_pointer(&props); +} + + void qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data) { @@ -1463,6 +1494,7 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data) return; virJSONValueFree(data->storageProps); + virJSONValueFree(data->storageSliceProps); virJSONValueFree(data->formatProps); virJSONValueFree(data->prmgrProps); virJSONValueFree(data->authsecretProps); @@ -1513,6 +1545,13 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src, data->storageNodeName = src->nodestorage; data->formatNodeName = src->nodeformat; + if (src->sliceStorage && src->format != VIR_STORAGE_FILE_RAW) { + if (!(data->storageSliceProps = qemuBlockStorageSourceGetBlockdevStorageSliceProps(src))) + return NULL; + + data->storageSliceNodeName = src->sliceStorage->nodename; + } + return g_steal_pointer(&data); } @@ -1581,6 +1620,21 @@ qemuBlockStorageSourceAttachApplyFormat(qemuMonitorPtr mon, } +static int +qemuBlockStorageSourceAttachApplyStorageSlice(qemuMonitorPtr mon, + qemuBlockStorageSourceAttachDataPtr data) +{ + if (data->storageSliceProps) { + if (qemuMonitorBlockdevAdd(mon, &data->storageSliceProps) < 0) + return -1; + + data->storageSliceAttached = true; + } + + return 0; +} + + /** * qemuBlockStorageSourceAttachApply: * @mon: monitor object @@ -1600,6 +1654,7 @@ qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon, { if (qemuBlockStorageSourceAttachApplyStorageDeps(mon, data) < 0 || qemuBlockStorageSourceAttachApplyStorage(mon, data) < 0 || + qemuBlockStorageSourceAttachApplyStorageSlice(mon, data) < 0 || qemuBlockStorageSourceAttachApplyFormatDeps(mon, data) < 0 || qemuBlockStorageSourceAttachApplyFormat(mon, data) < 0) return -1; @@ -1642,6 +1697,9 @@ qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon, if (data->formatAttached) ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName)); + if (data->storageSliceAttached) + ignore_value(qemuMonitorBlockdevDel(mon, data->storageSliceNodeName)); + if (data->storageAttached) ignore_value(qemuMonitorBlockdevDel(mon, data->storageNodeName)); @@ -1689,6 +1747,14 @@ qemuBlockStorageSourceDetachPrepare(virStorageSourcePtr src, data->formatAttached = true; data->storageNodeName = src->nodestorage; data->storageAttached = true; + + /* 'raw' format doesn't need the extra 'raw' layer when slicing, thus + * the nodename is NULL */ + if (src->sliceStorage && + src->sliceStorage->nodename) { + data->storageSliceNodeName = src->sliceStorage->nodename; + data->storageSliceAttached = true; + } } if (src->pr && diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index a816190bb78446128ff5f8dbe942b6e51167595f..eab0128d5d92f1d95fbf0fbef77d2049b0c357c1 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -82,6 +82,10 @@ struct qemuBlockStorageSourceAttachData { const char *storageNodeName; bool storageAttached; + virJSONValuePtr storageSliceProps; + const char *storageSliceNodeName; + bool storageSliceAttached; + virJSONValuePtr formatProps; const char *formatNodeName; bool formatAttached; diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 6b59bbeb2c0c098aee55c821b70a2854672ba80f..71df0d1ab2830f78b88bd37e954d96472b41413a 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -1316,6 +1316,7 @@ qemuBlockJobProcessEventConcludedCreate(virQEMUDriverPtr driver, backend->formatAttached = false; if (job->data.create.storage) { backend->storageAttached = false; + backend->storageSliceAttached = false; VIR_FREE(backend->encryptsecretAlias); } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 60f8820c648d2d7e2d6331c2e53f784620f9b801..f69a9e651c08bc75875e77769415d4818b94dccc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2411,6 +2411,14 @@ qemuBuildBlockStorageSourceAttachDataCommandline(virCommandPtr cmd, VIR_FREE(tmp); } + if (data->storageSliceProps) { + if (!(tmp = virJSONValueToString(data->storageSliceProps, false))) + return -1; + + virCommandAddArgList(cmd, "-blockdev", tmp, NULL); + VIR_FREE(tmp); + } + if (data->formatProps) { if (!(tmp = virJSONValueToString(data->formatProps, false))) return -1; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 1c4f76f047c04875d365946a7b59dfe8ea5e31fc..af6817cc0526895759b8a4b14db778bddeae6961 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -16264,6 +16264,10 @@ qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk, src->nodestorage = g_strdup_printf("libvirt-%u-storage", src->id); src->nodeformat = g_strdup_printf("libvirt-%u-format", src->id); + if (src->sliceStorage && + src->format != VIR_STORAGE_FILE_RAW) + src->sliceStorage->nodename = g_strdup_printf("libvirt-%u-slice-sto", src->id); + if (qemuDomainValidateStorageSource(src, priv->qemuCaps) < 0) return -1;