const char *jobname = NULL;
virDomainDiskDefPtr disk;
virStorageSourcePtr baseSource = NULL;
- unsigned int baseIndex = 0;
g_autofree char *basePath = NULL;
g_autofree char *backingPath = NULL;
unsigned long long speed = bandwidth;
goto endjob;
if (base &&
- (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
- !(baseSource = virStorageSourceChainLookup(disk->src, disk->src,
- base, baseIndex, NULL))))
+ !(baseSource = virStorageSourceChainLookup(disk->src, disk->src,
+ base, disk->dst, NULL)))
goto endjob;
if (baseSource) {
int ret = -1;
virDomainDiskDefPtr disk = NULL;
virStorageSourcePtr topSource;
- unsigned int topIndex = 0;
virStorageSourcePtr baseSource = NULL;
- unsigned int baseIndex = 0;
virStorageSourcePtr top_parent = NULL;
bool clean_access = false;
g_autofree char *topPath = NULL;
if (!top || STREQ(top, disk->dst))
topSource = disk->src;
- else if (virStorageFileParseChainIndex(disk->dst, top, &topIndex) < 0 ||
- !(topSource = virStorageSourceChainLookup(disk->src, NULL,
- top, topIndex,
- &top_parent)))
+ else if (!(topSource = virStorageSourceChainLookup(disk->src, NULL, top,
+ disk->dst, &top_parent)))
goto endjob;
if (topSource == disk->src) {
if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW))
baseSource = topSource->backingStore;
- else if (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 ||
- !(baseSource = virStorageSourceChainLookup(disk->src, topSource,
- base, baseIndex, NULL)))
+ else if (!(baseSource = virStorageSourceChainLookup(disk->src, topSource,
+ base, disk->dst, NULL)))
goto endjob;
if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) &&
}
-/* Given a @chain, look for the backing store @name that is a backing file
- * of @startFrom (or any member of @chain if @startFrom is NULL) and return
- * that location within the chain. @chain must always point to the top of
- * the chain. Pass NULL for @name and 0 for @idx to find the base of the
- * chain. Pass nonzero @idx to find the backing source according to its
- * position in the backing chain. If @parent is not NULL, set *@parent to
- * the preferred name of the parent (or to NULL if @name matches the start
- * of the chain). Since the results point within @chain, they must not be
- * independently freed. Reports an error and returns NULL if @name is not
- * found.
+/**
+ * virStorageSourceChainLookup:
+ * @chain: chain top to look in
+ * @startFrom: move the starting point of @chain if non-NULL
+ * @name: name of the file to look for in @chain
+ * @diskTarget: optional disk target to validate against
+ * @parent: Filled with parent virStorageSource of the returned value if non-NULL.
+ *
+ * Looks up a storage source definition corresponding to @name in @chain and
+ * returns the corresponding virStorageSource. If @startFrom is non-NULL, the
+ * lookup starts from that virStorageSource.
+ *
+ * @name can be:
+ * - NULL: the end of the source chain is returned
+ * - "vda[4]": Storage source with 'id' == 4 is returned. If @diskTarget is
+ * non-NULL it's also validated that the part before the square
+ * bracket matches the requested target
+ * - "/path/to/file": Literal path is matched. Symlink resolution is attempted
+ * if the filename doesn't string-match with the path.
*/
virStorageSourcePtr
virStorageSourceChainLookup(virStorageSourcePtr chain,
virStorageSourcePtr startFrom,
const char *name,
- unsigned int idx,
+ const char *diskTarget,
virStorageSourcePtr *parent)
{
virStorageSourcePtr prev;
const char *start = chain->path;
bool nameIsFile = virStorageSourceBackinStoreStringIsFile(name);
+ g_autofree char *target = NULL;
+ unsigned int idx = 0;
+
+ if (diskTarget)
+ start = diskTarget;
if (!parent)
parent = &prev;
*parent = NULL;
+ /* parse the "vda[4]" type string */
+ if (name &&
+ virStorageFileParseBackingStoreStr(name, &target, &idx) == 0) {
+ if (diskTarget &&
+ idx != 0 &&
+ STRNEQ(diskTarget, target)) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("requested target '%s' does not match target '%s'"),
+ target, diskTarget);
+ return NULL;
+ }
+ }
+
if (startFrom) {
while (virStorageSourceIsBacking(chain) &&
chain != startFrom->backingStore)
virStorageSourceChainLookup(virStorageSourcePtr chain,
virStorageSourcePtr startFrom,
const char *name,
- unsigned int idx,
+ const char *diskTarget,
virStorageSourcePtr *parent)
ATTRIBUTE_NONNULL(1);
}
result = virStorageSourceChainLookup(data->chain, data->from,
- data->name, idx, &actualParent);
+ data->name, data->target, &actualParent);
if (!data->expResult)
virResetLastError();