mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
lock_driver: Introduce VIR_LOCK_MANAGER_ACQUIRE_ROLLBACK
Soon there will be a virtlockd client that wants to either lock all the resources or none (in order to avoid virtlockd killing the client on connection close). Because on the RPC layer we can only acquire one resource at a time, we have to perform a rollback once we hit a resource that can't be acquired. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
997283b54b
commit
385eb8399b
@ -67,6 +67,10 @@ typedef enum {
|
||||
VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY = (1 << 0),
|
||||
/* Prevent further lock/unlock calls from this process */
|
||||
VIR_LOCK_MANAGER_ACQUIRE_RESTRICT = (1 << 1),
|
||||
/* Used when acquiring more resources in which one of them
|
||||
* can't be acquired, perform a rollback and release all
|
||||
* resources acquired so far. */
|
||||
VIR_LOCK_MANAGER_ACQUIRE_ROLLBACK = (1 << 2),
|
||||
} virLockManagerAcquireFlags;
|
||||
|
||||
typedef enum {
|
||||
|
@ -735,6 +735,34 @@ static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock,
|
||||
}
|
||||
|
||||
|
||||
static int virLockManagerLockDaemonReleaseImpl(virNetClientPtr client,
|
||||
virNetClientProgramPtr program,
|
||||
int counter,
|
||||
virLockManagerLockDaemonResourcePtr res)
|
||||
{
|
||||
virLockSpaceProtocolReleaseResourceArgs args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
args.path = res->lockspace;
|
||||
args.name = res->name;
|
||||
args.flags = res->flags;
|
||||
|
||||
args.flags &=
|
||||
~(VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED |
|
||||
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE |
|
||||
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_METADATA);
|
||||
|
||||
return virNetClientProgramCall(program,
|
||||
client,
|
||||
counter,
|
||||
VIR_LOCK_SPACE_PROTOCOL_PROC_RELEASE_RESOURCE,
|
||||
0, NULL, NULL, NULL,
|
||||
(xdrproc_t)xdr_virLockSpaceProtocolReleaseResourceArgs, &args,
|
||||
(xdrproc_t)xdr_void, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
||||
const char *state ATTRIBUTE_UNUSED,
|
||||
unsigned int flags,
|
||||
@ -745,10 +773,13 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
||||
virNetClientProgramPtr program = NULL;
|
||||
int counter = 0;
|
||||
int rv = -1;
|
||||
ssize_t i;
|
||||
ssize_t lastGood = -1;
|
||||
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
||||
|
||||
virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY |
|
||||
VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1);
|
||||
VIR_LOCK_MANAGER_ACQUIRE_RESTRICT |
|
||||
VIR_LOCK_MANAGER_ACQUIRE_ROLLBACK, -1);
|
||||
|
||||
if (priv->type == VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN &&
|
||||
priv->nresources == 0 &&
|
||||
@ -767,7 +798,6 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
||||
goto cleanup;
|
||||
|
||||
if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) {
|
||||
size_t i;
|
||||
for (i = 0; i < priv->nresources; i++) {
|
||||
virLockSpaceProtocolAcquireResourceArgs args;
|
||||
|
||||
@ -785,6 +815,7 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
||||
(xdrproc_t)xdr_virLockSpaceProtocolAcquireResourceArgs, &args,
|
||||
(xdrproc_t)xdr_void, NULL) < 0)
|
||||
goto cleanup;
|
||||
lastGood = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,8 +826,28 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
||||
rv = 0;
|
||||
|
||||
cleanup:
|
||||
if (rv != 0 && fd)
|
||||
VIR_FORCE_CLOSE(*fd);
|
||||
if (rv < 0) {
|
||||
int saved_errno = errno;
|
||||
virErrorPtr origerr;
|
||||
|
||||
virErrorPreserveLast(&origerr);
|
||||
if (fd)
|
||||
VIR_FORCE_CLOSE(*fd);
|
||||
|
||||
if (flags & VIR_LOCK_MANAGER_ACQUIRE_ROLLBACK) {
|
||||
for (i = lastGood; i >= 0; i--) {
|
||||
virLockManagerLockDaemonResourcePtr res = &priv->resources[i];
|
||||
|
||||
if (virLockManagerLockDaemonReleaseImpl(client, program,
|
||||
counter++, res) < 0)
|
||||
VIR_WARN("Unable to release resource lockspace=%s name=%s",
|
||||
res->lockspace, res->name);
|
||||
}
|
||||
}
|
||||
|
||||
virErrorRestore(&origerr);
|
||||
errno = saved_errno;
|
||||
}
|
||||
virNetClientClose(client);
|
||||
virObjectUnref(client);
|
||||
virObjectUnref(program);
|
||||
@ -824,27 +875,10 @@ static int virLockManagerLockDaemonRelease(virLockManagerPtr lock,
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < priv->nresources; i++) {
|
||||
virLockSpaceProtocolReleaseResourceArgs args;
|
||||
virLockManagerLockDaemonResourcePtr res = &priv->resources[i];
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
if (priv->resources[i].lockspace)
|
||||
args.path = priv->resources[i].lockspace;
|
||||
args.name = priv->resources[i].name;
|
||||
args.flags = priv->resources[i].flags;
|
||||
|
||||
args.flags &=
|
||||
~(VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED |
|
||||
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE |
|
||||
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_METADATA);
|
||||
|
||||
if (virNetClientProgramCall(program,
|
||||
client,
|
||||
counter++,
|
||||
VIR_LOCK_SPACE_PROTOCOL_PROC_RELEASE_RESOURCE,
|
||||
0, NULL, NULL, NULL,
|
||||
(xdrproc_t)xdr_virLockSpaceProtocolReleaseResourceArgs, &args,
|
||||
(xdrproc_t)xdr_void, NULL) < 0)
|
||||
if (virLockManagerLockDaemonReleaseImpl(client, program,
|
||||
counter++, res) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user