libvirt/src/locking/domain_lock.c
Peter Krempa 68f0deb0dc locking: Add APIs to lock individual image files
Add helper APIs to manage individual image files rather than disks. To
simplify the addition some parts of the code were refactored in this
patch.
2014-07-09 10:38:56 +02:00

381 lines
10 KiB
C

/*
* domain_lock.c: Locking for domain lifecycle operations
*
* Copyright (C) 2010-2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include <config.h>
#include "domain_lock.h"
#include "viralloc.h"
#include "viruuid.h"
#include "virerror.h"
#include "virlog.h"
#define VIR_FROM_THIS VIR_FROM_LOCKING
VIR_LOG_INIT("locking.domain_lock");
static int virDomainLockManagerAddLease(virLockManagerPtr lock,
virDomainLeaseDefPtr lease)
{
unsigned int leaseFlags = 0;
virLockManagerParam lparams[] = {
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
.key = "path",
.value = { .str = lease->path },
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_ULONG,
.key = "offset",
.value = { .ul = lease->offset },
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
.key = "lockspace",
.value = { .str = lease->lockspace },
},
};
size_t nparams = ARRAY_CARDINALITY(lparams);
if (!lease->lockspace)
nparams--;
VIR_DEBUG("Add lease %s", lease->path);
if (virLockManagerAddResource(lock,
VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE,
lease->key,
nparams,
lparams,
leaseFlags) < 0) {
VIR_DEBUG("Failed to add lease %s", lease->path);
return -1;
}
return 0;
}
static int virDomainLockManagerAddImage(virLockManagerPtr lock,
virStorageSourcePtr src)
{
unsigned int diskFlags = 0;
int type = virStorageSourceGetActualType(src);
if (!src->path)
return 0;
if (!(type == VIR_STORAGE_TYPE_BLOCK ||
type == VIR_STORAGE_TYPE_FILE ||
type == VIR_STORAGE_TYPE_DIR))
return 0;
if (src->readonly)
diskFlags |= VIR_LOCK_MANAGER_RESOURCE_READONLY;
if (src->shared)
diskFlags |= VIR_LOCK_MANAGER_RESOURCE_SHARED;
VIR_DEBUG("Add disk %s", src->path);
if (virLockManagerAddResource(lock,
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
src->path,
0,
NULL,
diskFlags) < 0) {
VIR_DEBUG("Failed add disk %s", src->path);
return -1;
}
return 0;
}
static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
bool withResources)
{
virLockManagerPtr lock;
size_t i;
virLockManagerParam params[] = {
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
.key = "uuid",
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
.key = "name",
.value = { .str = dom->def->name },
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
.key = "id",
.value = { .iv = dom->def->id },
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
.key = "pid",
.value = { .iv = dom->pid },
},
{ .type = VIR_LOCK_MANAGER_PARAM_TYPE_CSTRING,
.key = "uri",
.value = { .cstr = uri },
},
};
VIR_DEBUG("plugin=%p dom=%p withResources=%d",
plugin, dom, withResources);
memcpy(params[0].value.uuid, dom->def->uuid, VIR_UUID_BUFLEN);
if (!(lock = virLockManagerNew(virLockManagerPluginGetDriver(plugin),
VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN,
ARRAY_CARDINALITY(params),
params,
0)))
goto error;
if (withResources) {
VIR_DEBUG("Adding leases");
for (i = 0; i < dom->def->nleases; i++)
if (virDomainLockManagerAddLease(lock, dom->def->leases[i]) < 0)
goto error;
VIR_DEBUG("Adding disks");
for (i = 0; i < dom->def->ndisks; i++) {
virDomainDiskDefPtr disk = dom->def->disks[i];
if (virDomainLockManagerAddImage(lock, disk->src) < 0)
goto error;
}
}
return lock;
error:
virLockManagerFree(lock);
return NULL;
}
int virDomainLockProcessStart(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
bool paused,
int *fd)
{
virLockManagerPtr lock;
int ret;
int flags = VIR_LOCK_MANAGER_ACQUIRE_RESTRICT;
VIR_DEBUG("plugin=%p dom=%p paused=%d fd=%p",
plugin, dom, paused, fd);
if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true)))
return -1;
if (paused)
flags |= VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY;
ret = virLockManagerAcquire(lock, NULL, flags,
dom->def->onLockFailure, fd);
virLockManagerFree(lock);
return ret;
}
int virDomainLockProcessPause(virLockManagerPluginPtr plugin,
virDomainObjPtr dom,
char **state)
{
virLockManagerPtr lock;
int ret;
VIR_DEBUG("plugin=%p dom=%p state=%p",
plugin, dom, state);
if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true)))
return -1;
ret = virLockManagerRelease(lock, state, 0);
virLockManagerFree(lock);
return ret;
}
int virDomainLockProcessResume(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
const char *state)
{
virLockManagerPtr lock;
int ret;
VIR_DEBUG("plugin=%p dom=%p state=%s",
plugin, dom, NULLSTR(state));
if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true)))
return -1;
ret = virLockManagerAcquire(lock, state, 0, dom->def->onLockFailure, NULL);
virLockManagerFree(lock);
return ret;
}
int virDomainLockProcessInquire(virLockManagerPluginPtr plugin,
virDomainObjPtr dom,
char **state)
{
virLockManagerPtr lock;
int ret;
VIR_DEBUG("plugin=%p dom=%p state=%p",
plugin, dom, state);
if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true)))
return -1;
ret = virLockManagerInquire(lock, state, 0);
virLockManagerFree(lock);
return ret;
}
int virDomainLockImageAttach(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
virStorageSourcePtr src)
{
virLockManagerPtr lock;
int ret = -1;
VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false)))
return -1;
if (virDomainLockManagerAddImage(lock, src) < 0)
goto cleanup;
if (virLockManagerAcquire(lock, NULL, 0,
dom->def->onLockFailure, NULL) < 0)
goto cleanup;
ret = 0;
cleanup:
virLockManagerFree(lock);
return ret;
}
int virDomainLockDiskAttach(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
virDomainDiskDefPtr disk)
{
return virDomainLockImageAttach(plugin, uri, dom, disk->src);
}
int virDomainLockImageDetach(virLockManagerPluginPtr plugin,
virDomainObjPtr dom,
virStorageSourcePtr src)
{
virLockManagerPtr lock;
int ret = -1;
VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false)))
return -1;
if (virDomainLockManagerAddImage(lock, src) < 0)
goto cleanup;
if (virLockManagerRelease(lock, NULL, 0) < 0)
goto cleanup;
ret = 0;
cleanup:
virLockManagerFree(lock);
return ret;
}
int virDomainLockDiskDetach(virLockManagerPluginPtr plugin,
virDomainObjPtr dom,
virDomainDiskDefPtr disk)
{
return virDomainLockImageDetach(plugin, dom, disk->src);
}
int virDomainLockLeaseAttach(virLockManagerPluginPtr plugin,
const char *uri,
virDomainObjPtr dom,
virDomainLeaseDefPtr lease)
{
virLockManagerPtr lock;
int ret = -1;
VIR_DEBUG("plugin=%p dom=%p lease=%p",
plugin, dom, lease);
if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false)))
return -1;
if (virDomainLockManagerAddLease(lock, lease) < 0)
goto cleanup;
if (virLockManagerAcquire(lock, NULL, 0,
dom->def->onLockFailure, NULL) < 0)
goto cleanup;
ret = 0;
cleanup:
virLockManagerFree(lock);
return ret;
}
int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
virDomainObjPtr dom,
virDomainLeaseDefPtr lease)
{
virLockManagerPtr lock;
int ret = -1;
VIR_DEBUG("plugin=%p dom=%p lease=%p",
plugin, dom, lease);
if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false)))
return -1;
if (virDomainLockManagerAddLease(lock, lease) < 0)
goto cleanup;
if (virLockManagerRelease(lock, NULL, 0) < 0)
goto cleanup;
ret = 0;
cleanup:
virLockManagerFree(lock);
return ret;
}