diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cbc408f78405f0e8ea3409fdbbd5243ab6a363d9..1c170b6ded797e4b12c33efb0edba80effba0805 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2364,6 +2364,7 @@ virStorageSourceIsBlockLocal;
virStorageSourceIsEmpty;
virStorageSourceIsLocalStorage;
virStorageSourceNewFromBacking;
+virStorageSourceNewFromBackingAbsolute;
virStorageSourceParseRBDColonString;
virStorageSourcePoolDefFree;
virStorageSourcePoolModeTypeFromString;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 16de6035887075fca6b42cd699916a7aec613d1b..0fa96815b69bde38023832eaba17957a954cb8cc 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -2514,7 +2514,7 @@ virStorageSourceParseBackingColon(virStorageSourcePtr src,
}
-static virStorageSourcePtr
+virStorageSourcePtr
virStorageSourceNewFromBackingAbsolute(const char *path)
{
virStorageSourcePtr ret;
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 78beaf4def38840c0c316537cddfdd1b089fd662..1a76fad0f6f8692b74d1e86f2f751fbf2391d731 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -380,4 +380,7 @@ int virStorageFileGetRelativeBackingPath(virStorageSourcePtr from,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int virStorageFileCheckCompat(const char *compat);
+
+virStorageSourcePtr virStorageSourceNewFromBackingAbsolute(const char *path);
+
#endif /* __VIR_STORAGE_FILE_H__ */
diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c
index 580065e04d1cfe4a59257edb90bff6a727a4f4df..6016a3beb8631becb625c2cb5f0aa6d723096ac7 100644
--- a/tests/virstoragetest.c
+++ b/tests/virstoragetest.c
@@ -665,6 +665,58 @@ testPathRelative(const void *args)
}
+struct testBackingParseData {
+ const char *backing;
+ const char *expect;
+};
+
+static int
+testBackingParse(const void *args)
+{
+ const struct testBackingParseData *data = args;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ virStorageSourcePtr src = NULL;
+ char *xml = NULL;
+ int ret = -1;
+
+ if (!(src = virStorageSourceNewFromBackingAbsolute(data->backing))) {
+ if (!data->expect)
+ ret = 0;
+
+ goto cleanup;
+ }
+
+ if (src && !data->expect) {
+ fprintf(stderr, "parsing of backing store string '%s' should "
+ "have failed\n", data->backing);
+ goto cleanup;
+ }
+
+ if (virDomainDiskSourceFormat(&buf, src, 0, 0) < 0 ||
+ !(xml = virBufferContentAndReset(&buf))) {
+ fprintf(stderr, "failed to format disk source xml\n");
+ goto cleanup;
+ }
+
+ if (!STREQ(xml, data->expect)) {
+ fprintf(stderr, "\n backing store string '%s'\n"
+ "expected storage source xml:\n%s\n"
+ "actual storage source xml:\n%s\n",
+ data->backing, data->expect, xml);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virStorageSourceFree(src);
+ virBufferFreeAndReset(&buf);
+ VIR_FREE(xml);
+
+ return ret;
+}
+
+
static int
mymain(void)
{
@@ -674,6 +726,7 @@ mymain(void)
struct testLookupData data2;
struct testPathCanonicalizeData data3;
struct testPathRelativeBacking data4;
+ struct testBackingParseData data5;
virStorageSourcePtr chain = NULL;
virStorageSourcePtr chain2; /* short for chain->backingStore */
virStorageSourcePtr chain3; /* short for chain2->backingStore */
@@ -1276,6 +1329,33 @@ mymain(void)
TEST_RELATIVE_BACKING(21, backingchain[10], backingchain[11], "../../../../blah/image4");
TEST_RELATIVE_BACKING(22, backingchain[11], backingchain[11], "../blah/image4");
+
+ virTestCounterReset("Backing store parse ");
+
+#define TEST_BACKING_PARSE(bck, xml) \
+ do { \
+ data5.backing = bck; \
+ data5.expect = xml; \
+ if (virTestRun(virTestCounterNext(), \
+ testBackingParse, &data5) < 0) \
+ ret = -1; \
+ } while (0)
+
+ TEST_BACKING_PARSE("path", "\n");
+ TEST_BACKING_PARSE("://", NULL);
+ TEST_BACKING_PARSE("http://example.com/file",
+ "\n");
+ TEST_BACKING_PARSE("rbd:testshare:id=asdf:mon_host=example.com",
+ "\n");
+ TEST_BACKING_PARSE("nbd:example.org:6000:exportname=blah",
+ "\n");
+
cleanup:
/* Final cleanup */
virStorageSourceFree(chain);