mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-02 01:45:17 +00:00
Storage driver implementation for CreateXMLFrom
There is some funkiness here, since we are either dealing with 2 different pools (which means validation x 2) or the same pool, where we have to be careful not to deadlock.
This commit is contained in:
parent
5f99a7fd23
commit
4aa0959d60
@ -1,3 +1,8 @@
|
|||||||
|
Tue May 19 09:36:48 EDT 2009 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
|
* src/storage_backend.h src/storage_driver.c: Storage driver
|
||||||
|
implementation for CreateXMLFrom
|
||||||
|
|
||||||
Tue May 19 09:26:53 EDT 2009 Cole Robinson <crobinso@redhat.com>
|
Tue May 19 09:26:53 EDT 2009 Cole Robinson <crobinso@redhat.com>
|
||||||
|
|
||||||
* src/node_device_hal.c: Fix node device media insert/eject
|
* src/node_device_hal.c: Fix node device media insert/eject
|
||||||
|
@ -38,6 +38,7 @@ typedef int (*virStorageBackendBuildVol)(virConnectPtr conn, virStorageVolDefPtr
|
|||||||
typedef int (*virStorageBackendCreateVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
typedef int (*virStorageBackendCreateVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
||||||
typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
||||||
typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
|
typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
|
||||||
|
typedef int (*virStorageBackendBuildVolFrom)(virConnectPtr conn, virStorageVolDefPtr origvol, virStorageVolDefPtr newvol, unsigned int flags);
|
||||||
|
|
||||||
|
|
||||||
typedef struct _virStorageBackend virStorageBackend;
|
typedef struct _virStorageBackend virStorageBackend;
|
||||||
@ -54,6 +55,7 @@ struct _virStorageBackend {
|
|||||||
virStorageBackendDeletePool deletePool;
|
virStorageBackendDeletePool deletePool;
|
||||||
|
|
||||||
virStorageBackendBuildVol buildVol;
|
virStorageBackendBuildVol buildVol;
|
||||||
|
virStorageBackendBuildVolFrom buildVolFrom;
|
||||||
virStorageBackendCreateVol createVol;
|
virStorageBackendCreateVol createVol;
|
||||||
virStorageBackendRefreshVol refreshVol;
|
virStorageBackendRefreshVol refreshVol;
|
||||||
virStorageBackendDeleteVol deleteVol;
|
virStorageBackendDeleteVol deleteVol;
|
||||||
|
@ -1306,6 +1306,160 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static virStorageVolPtr
|
||||||
|
storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
|
||||||
|
const char *xmldesc,
|
||||||
|
virStorageVolPtr vobj,
|
||||||
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||||
|
virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
|
||||||
|
virStoragePoolObjPtr pool, origpool = NULL;
|
||||||
|
virStorageBackendPtr backend;
|
||||||
|
virStorageVolDefPtr origvol = NULL, newvol = NULL;
|
||||||
|
virStorageVolPtr ret = NULL, volobj = NULL;
|
||||||
|
int buildret, diffpool;
|
||||||
|
|
||||||
|
diffpool = !STREQ(obj->name, vobj->pool);
|
||||||
|
|
||||||
|
storageDriverLock(driver);
|
||||||
|
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
||||||
|
if (diffpool)
|
||||||
|
origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
|
||||||
|
else
|
||||||
|
origpool = pool;
|
||||||
|
storageDriverUnlock(driver);
|
||||||
|
|
||||||
|
if (!pool) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
|
||||||
|
"%s", _("no storage pool with matching uuid"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffpool && !origpool) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
|
||||||
|
"%s", _("no storage pool with matching name"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virStoragePoolObjIsActive(pool)) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("storage pool is not active"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffpool && !virStoragePoolObjIsActive(origpool)) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("storage pool is not active"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
origvol = virStorageVolDefFindByName(origpool, vobj->name);
|
||||||
|
if (!origvol) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
|
||||||
|
"%s", _("no storage vol with matching name"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
newvol = virStorageVolDefParse(obj->conn, pool->def, xmldesc, NULL);
|
||||||
|
if (newvol == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virStorageVolDefFindByName(pool, newvol->name)) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
|
||||||
|
_("storage volume name '%s' already in use."),
|
||||||
|
newvol->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there ever a valid case for this? */
|
||||||
|
if (newvol->capacity < origvol->capacity)
|
||||||
|
newvol->capacity = origvol->capacity;
|
||||||
|
|
||||||
|
if (!backend->buildVolFrom) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
|
||||||
|
"%s", _("storage pool does not support volume creation from an existing volume"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (origvol->building) {
|
||||||
|
virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("volume '%s' is still being allocated."),
|
||||||
|
origvol->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->refreshVol &&
|
||||||
|
backend->refreshVol(obj->conn, pool, origvol) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (VIR_REALLOC_N(pool->volumes.objs,
|
||||||
|
pool->volumes.count+1) < 0) {
|
||||||
|
virReportOOMError(obj->conn);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'Define' the new volume so we get async progress reporting */
|
||||||
|
if (backend->createVol(obj->conn, pool, newvol) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->volumes.objs[pool->volumes.count++] = newvol;
|
||||||
|
volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
|
||||||
|
newvol->key);
|
||||||
|
|
||||||
|
/* Drop the pool lock during volume allocation */
|
||||||
|
pool->asyncjobs++;
|
||||||
|
origvol->building = 1;
|
||||||
|
newvol->building = 1;
|
||||||
|
virStoragePoolObjUnlock(pool);
|
||||||
|
|
||||||
|
if (diffpool) {
|
||||||
|
origpool->asyncjobs++;
|
||||||
|
virStoragePoolObjUnlock(origpool);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildret = backend->buildVolFrom(obj->conn, newvol, origvol, flags);
|
||||||
|
|
||||||
|
storageDriverLock(driver);
|
||||||
|
virStoragePoolObjLock(pool);
|
||||||
|
if (diffpool)
|
||||||
|
virStoragePoolObjLock(origpool);
|
||||||
|
storageDriverUnlock(driver);
|
||||||
|
|
||||||
|
origvol->building = 0;
|
||||||
|
newvol->building = 0;
|
||||||
|
newvol = NULL;
|
||||||
|
pool->asyncjobs--;
|
||||||
|
|
||||||
|
if (diffpool) {
|
||||||
|
origpool->asyncjobs--;
|
||||||
|
virStoragePoolObjUnlock(origpool);
|
||||||
|
origpool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildret < 0) {
|
||||||
|
virStoragePoolObjUnlock(pool);
|
||||||
|
storageVolumeDelete(volobj, 0);
|
||||||
|
pool = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = volobj;
|
||||||
|
volobj = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (volobj)
|
||||||
|
virUnrefStorageVol(volobj);
|
||||||
|
virStorageVolDefFree(newvol);
|
||||||
|
if (pool)
|
||||||
|
virStoragePoolObjUnlock(pool);
|
||||||
|
if (diffpool && origpool)
|
||||||
|
virStoragePoolObjUnlock(origpool);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
storageVolumeDelete(virStorageVolPtr obj,
|
storageVolumeDelete(virStorageVolPtr obj,
|
||||||
unsigned int flags) {
|
unsigned int flags) {
|
||||||
@ -1526,10 +1680,6 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static virStorageDriver storageDriver = {
|
static virStorageDriver storageDriver = {
|
||||||
.name = "storage",
|
.name = "storage",
|
||||||
.open = storageOpen,
|
.open = storageOpen,
|
||||||
@ -1561,6 +1711,7 @@ static virStorageDriver storageDriver = {
|
|||||||
.volLookupByKey = storageVolumeLookupByKey,
|
.volLookupByKey = storageVolumeLookupByKey,
|
||||||
.volLookupByPath = storageVolumeLookupByPath,
|
.volLookupByPath = storageVolumeLookupByPath,
|
||||||
.volCreateXML = storageVolumeCreateXML,
|
.volCreateXML = storageVolumeCreateXML,
|
||||||
|
.volCreateXMLFrom = storageVolumeCreateXMLFrom,
|
||||||
.volDelete = storageVolumeDelete,
|
.volDelete = storageVolumeDelete,
|
||||||
.volGetInfo = storageVolumeGetInfo,
|
.volGetInfo = storageVolumeGetInfo,
|
||||||
.volGetXMLDesc = storageVolumeGetXMLDesc,
|
.volGetXMLDesc = storageVolumeGetXMLDesc,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user