提交 22baf6e0 编写于 作者: M Michal Privoznik

lock_driver: Introduce new VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON

We will want virtlockd to lock files on behalf of libvirtd and
not qemu process, because it is libvirtd that needs an exclusive
access not qemu. This requires new lock context.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NJohn Ferlan <jferlan@redhat.com>
上级 21c34b86
...@@ -42,6 +42,8 @@ typedef enum { ...@@ -42,6 +42,8 @@ typedef enum {
typedef enum { typedef enum {
/* The managed object is a virtual guest domain */ /* The managed object is a virtual guest domain */
VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN = 0, VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN = 0,
/* The managed object is a daemon (e.g. libvirtd) */
VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON = 1,
} virLockManagerObjectType; } virLockManagerObjectType;
typedef enum { typedef enum {
......
...@@ -56,10 +56,21 @@ struct _virLockManagerLockDaemonResource { ...@@ -56,10 +56,21 @@ struct _virLockManagerLockDaemonResource {
}; };
struct _virLockManagerLockDaemonPrivate { struct _virLockManagerLockDaemonPrivate {
unsigned char uuid[VIR_UUID_BUFLEN]; virLockManagerObjectType type;
char *name; union {
int id; struct {
pid_t pid; unsigned char uuid[VIR_UUID_BUFLEN];
char *name;
int id;
pid_t pid;
} dom;
struct {
unsigned char uuid[VIR_UUID_BUFLEN];
char *name;
pid_t pid;
} daemon;
} t;
size_t nresources; size_t nresources;
virLockManagerLockDaemonResourcePtr resources; virLockManagerLockDaemonResourcePtr resources;
...@@ -156,10 +167,30 @@ virLockManagerLockDaemonConnectionRegister(virLockManagerPtr lock, ...@@ -156,10 +167,30 @@ virLockManagerLockDaemonConnectionRegister(virLockManagerPtr lock,
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.flags = 0; args.flags = 0;
memcpy(args.owner.uuid, priv->uuid, VIR_UUID_BUFLEN);
args.owner.name = priv->name; switch (priv->type) {
args.owner.id = priv->id; case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
args.owner.pid = priv->pid; memcpy(args.owner.uuid, priv->t.dom.uuid, VIR_UUID_BUFLEN);
args.owner.name = priv->t.dom.name;
args.owner.id = priv->t.dom.id;
args.owner.pid = priv->t.dom.pid;
break;
case VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON:
memcpy(args.owner.uuid, priv->t.daemon.uuid, VIR_UUID_BUFLEN);
args.owner.name = priv->t.daemon.name;
args.owner.pid = priv->t.daemon.pid;
/* This one should not be needed. However, virtlockd
* checks for ID because not every domain has a PID. */
args.owner.id = priv->t.daemon.pid;
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown lock manager object type %d"),
priv->type);
return -1;
}
if (virNetClientProgramCall(program, if (virNetClientProgramCall(program,
client, client,
...@@ -391,7 +422,18 @@ virLockManagerLockDaemonPrivateFree(virLockManagerLockDaemonPrivatePtr priv) ...@@ -391,7 +422,18 @@ virLockManagerLockDaemonPrivateFree(virLockManagerLockDaemonPrivatePtr priv)
} }
VIR_FREE(priv->resources); VIR_FREE(priv->resources);
VIR_FREE(priv->name); switch (priv->type) {
case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
VIR_FREE(priv->t.dom.name);
break;
case VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON:
VIR_FREE(priv->t.daemon.name);
break;
default:
break;
}
VIR_FREE(priv); VIR_FREE(priv);
} }
...@@ -420,46 +462,82 @@ static int virLockManagerLockDaemonNew(virLockManagerPtr lock, ...@@ -420,46 +462,82 @@ static int virLockManagerLockDaemonNew(virLockManagerPtr lock,
if (VIR_ALLOC(priv) < 0) if (VIR_ALLOC(priv) < 0)
return -1; return -1;
switch (type) { priv->type = type;
switch ((virLockManagerObjectType) type) {
case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN: case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
for (i = 0; i < nparams; i++) { for (i = 0; i < nparams; i++) {
if (STREQ(params[i].key, "uuid")) { if (STREQ(params[i].key, "uuid")) {
memcpy(priv->uuid, params[i].value.uuid, VIR_UUID_BUFLEN); memcpy(priv->t.dom.uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
} else if (STREQ(params[i].key, "name")) { } else if (STREQ(params[i].key, "name")) {
if (VIR_STRDUP(priv->name, params[i].value.str) < 0) if (VIR_STRDUP(priv->t.dom.name, params[i].value.str) < 0)
goto cleanup; goto cleanup;
} else if (STREQ(params[i].key, "id")) { } else if (STREQ(params[i].key, "id")) {
priv->id = params[i].value.iv; priv->t.dom.id = params[i].value.iv;
} else if (STREQ(params[i].key, "pid")) { } else if (STREQ(params[i].key, "pid")) {
priv->pid = params[i].value.iv; priv->t.dom.pid = params[i].value.iv;
} else if (STREQ(params[i].key, "uri")) { } else if (STREQ(params[i].key, "uri")) {
/* ignored */ /* ignored */
} else { } else {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected parameter %s for object"), _("Unexpected parameter %s for domain object"),
params[i].key); params[i].key);
goto cleanup; goto cleanup;
} }
} }
if (priv->id == 0) { if (priv->t.dom.id == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing ID parameter for domain object")); _("Missing ID parameter for domain object"));
goto cleanup; goto cleanup;
} }
if (priv->pid == 0) if (priv->t.dom.pid == 0)
VIR_DEBUG("Missing PID parameter for domain object"); VIR_DEBUG("Missing PID parameter for domain object");
if (!priv->name) { if (!priv->t.dom.name) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing name parameter for domain object")); _("Missing name parameter for domain object"));
goto cleanup; goto cleanup;
} }
if (!virUUIDIsValid(priv->uuid)) { if (!virUUIDIsValid(priv->t.dom.uuid)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing UUID parameter for domain object")); _("Missing UUID parameter for domain object"));
goto cleanup; goto cleanup;
} }
break; break;
case VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON:
for (i = 0; i < nparams; i++) {
if (STREQ(params[i].key, "uuid")) {
memcpy(priv->t.daemon.uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
} else if (STREQ(params[i].key, "name")) {
if (VIR_STRDUP(priv->t.daemon.name, params[i].value.str) < 0)
goto cleanup;
} else if (STREQ(params[i].key, "pid")) {
priv->t.daemon.pid = params[i].value.iv;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected parameter %s for daemon object"),
params[i].key);
goto cleanup;
}
}
if (!virUUIDIsValid(priv->t.daemon.uuid)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing UUID parameter for daemon object"));
goto cleanup;
}
if (!priv->t.daemon.name) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing name parameter for daemon object"));
goto cleanup;
}
if (priv->t.daemon.pid == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing PID parameter for daemon object"));
goto cleanup;
}
break;
default: default:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown lock manager object type %d"), _("Unknown lock manager object type %d"),
...@@ -494,107 +572,119 @@ static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock, ...@@ -494,107 +572,119 @@ static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock,
if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY) if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY)
return 0; return 0;
switch (type) { switch (priv->type) {
case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK: case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
if (params || nparams) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected parameters for disk resource"));
goto cleanup;
}
if (!driver->autoDiskLease) {
if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED |
VIR_LOCK_MANAGER_RESOURCE_READONLY)))
priv->hasRWDisks = true;
return 0;
}
/* XXX we should somehow pass in TYPE=BLOCK info switch (type) {
* from the domain_lock code, instead of assuming /dev case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK:
*/ if (params || nparams) {
if (STRPREFIX(name, "/dev") && virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
driver->lvmLockSpaceDir) { _("Unexpected parameters for disk resource"));
VIR_DEBUG("Trying to find an LVM UUID for %s", name);
if (virStorageFileGetLVMKey(name, &newName) < 0)
goto cleanup; goto cleanup;
}
if (!driver->autoDiskLease) {
if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED |
VIR_LOCK_MANAGER_RESOURCE_READONLY)))
priv->hasRWDisks = true;
return 0;
}
if (newName) { /* XXX we should somehow pass in TYPE=BLOCK info
VIR_DEBUG("Got an LVM UUID %s for %s", newName, name); * from the domain_lock code, instead of assuming /dev
if (VIR_STRDUP(newLockspace, driver->lvmLockSpaceDir) < 0) */
if (STRPREFIX(name, "/dev") &&
driver->lvmLockSpaceDir) {
VIR_DEBUG("Trying to find an LVM UUID for %s", name);
if (virStorageFileGetLVMKey(name, &newName) < 0)
goto cleanup; goto cleanup;
autoCreate = true;
break; if (newName) {
VIR_DEBUG("Got an LVM UUID %s for %s", newName, name);
if (VIR_STRDUP(newLockspace, driver->lvmLockSpaceDir) < 0)
goto cleanup;
autoCreate = true;
break;
}
virResetLastError();
/* Fallback to generic non-block code */
} }
virResetLastError();
/* Fallback to generic non-block code */
}
if (STRPREFIX(name, "/dev") && if (STRPREFIX(name, "/dev") &&
driver->scsiLockSpaceDir) { driver->scsiLockSpaceDir) {
VIR_DEBUG("Trying to find an SCSI ID for %s", name); VIR_DEBUG("Trying to find an SCSI ID for %s", name);
if (virStorageFileGetSCSIKey(name, &newName) < 0) if (virStorageFileGetSCSIKey(name, &newName) < 0)
goto cleanup; goto cleanup;
if (newName) {
VIR_DEBUG("Got an SCSI ID %s for %s", newName, name);
if (VIR_STRDUP(newLockspace, driver->scsiLockSpaceDir) < 0)
goto cleanup;
autoCreate = true;
break;
}
virResetLastError();
/* Fallback to generic non-block code */
}
if (newName) { if (driver->fileLockSpaceDir) {
VIR_DEBUG("Got an SCSI ID %s for %s", newName, name); if (VIR_STRDUP(newLockspace, driver->fileLockSpaceDir) < 0)
if (VIR_STRDUP(newLockspace, driver->scsiLockSpaceDir) < 0) goto cleanup;
if (virCryptoHashString(VIR_CRYPTO_HASH_SHA256, name, &newName) < 0)
goto cleanup; goto cleanup;
autoCreate = true; autoCreate = true;
break; VIR_DEBUG("Using indirect lease %s for %s", newName, name);
} else {
if (VIR_STRDUP(newLockspace, "") < 0)
goto cleanup;
if (VIR_STRDUP(newName, name) < 0)
goto cleanup;
VIR_DEBUG("Using direct lease for %s", name);
} }
virResetLastError();
/* Fallback to generic non-block code */
}
if (driver->fileLockSpaceDir) { break;
if (VIR_STRDUP(newLockspace, driver->fileLockSpaceDir) < 0) case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: {
goto cleanup; size_t i;
if (virCryptoHashString(VIR_CRYPTO_HASH_SHA256, name, &newName) < 0) char *path = NULL;
char *lockspace = NULL;
for (i = 0; i < nparams; i++) {
if (STREQ(params[i].key, "offset")) {
if (params[i].value.ul != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Offset must be zero for this lock manager"));
goto cleanup;
}
} else if (STREQ(params[i].key, "lockspace")) {
lockspace = params[i].value.str;
} else if (STREQ(params[i].key, "path")) {
path = params[i].value.str;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected parameter %s for lease resource"),
params[i].key);
goto cleanup;
}
}
if (!path || !lockspace) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing path or lockspace for lease resource"));
goto cleanup; goto cleanup;
autoCreate = true; }
VIR_DEBUG("Using indirect lease %s for %s", newName, name); if (virAsprintf(&newLockspace, "%s/%s",
} else { path, lockspace) < 0)
if (VIR_STRDUP(newLockspace, "") < 0)
goto cleanup; goto cleanup;
if (VIR_STRDUP(newName, name) < 0) if (VIR_STRDUP(newName, name) < 0)
goto cleanup; goto cleanup;
VIR_DEBUG("Using direct lease for %s", name);
}
break; } break;
case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: { default:
size_t i; virReportError(VIR_ERR_INTERNAL_ERROR,
char *path = NULL; _("Unknown lock manager object type %d for domain lock object"),
char *lockspace = NULL; type);
for (i = 0; i < nparams; i++) {
if (STREQ(params[i].key, "offset")) {
if (params[i].value.ul != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Offset must be zero for this lock manager"));
goto cleanup;
}
} else if (STREQ(params[i].key, "lockspace")) {
lockspace = params[i].value.str;
} else if (STREQ(params[i].key, "path")) {
path = params[i].value.str;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected parameter %s for lease resource"),
params[i].key);
goto cleanup;
}
}
if (!path || !lockspace) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing path or lockspace for lease resource"));
goto cleanup; goto cleanup;
} }
if (virAsprintf(&newLockspace, "%s/%s", break;
path, lockspace) < 0)
goto cleanup;
if (VIR_STRDUP(newName, name) < 0)
goto cleanup;
} break; case VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON:
default: default:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown lock manager object type %d"), _("Unknown lock manager object type %d"),
...@@ -639,7 +729,8 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock, ...@@ -639,7 +729,8 @@ static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY | virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY |
VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1); VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1);
if (priv->nresources == 0 && if (priv->type == VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN &&
priv->nresources == 0 &&
priv->hasRWDisks && priv->hasRWDisks &&
driver->requireLeaseForDisks) { driver->requireLeaseForDisks) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
......
...@@ -513,21 +513,32 @@ static int virLockManagerSanlockNew(virLockManagerPtr lock, ...@@ -513,21 +513,32 @@ static int virLockManagerSanlockNew(virLockManagerPtr lock,
priv->flags = flags; priv->flags = flags;
for (i = 0; i < nparams; i++) { switch ((virLockManagerObjectType) type) {
param = &params[i]; case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
for (i = 0; i < nparams; i++) {
if (STREQ(param->key, "uuid")) { param = &params[i];
memcpy(priv->vm_uuid, param->value.uuid, 16);
} else if (STREQ(param->key, "name")) { if (STREQ(param->key, "uuid")) {
if (VIR_STRDUP(priv->vm_name, param->value.str) < 0) memcpy(priv->vm_uuid, param->value.uuid, 16);
goto error; } else if (STREQ(param->key, "name")) {
} else if (STREQ(param->key, "pid")) { if (VIR_STRDUP(priv->vm_name, param->value.str) < 0)
priv->vm_pid = param->value.iv; goto error;
} else if (STREQ(param->key, "id")) { } else if (STREQ(param->key, "pid")) {
priv->vm_id = param->value.ui; priv->vm_pid = param->value.iv;
} else if (STREQ(param->key, "uri")) { } else if (STREQ(param->key, "id")) {
priv->vm_uri = param->value.cstr; priv->vm_id = param->value.ui;
} else if (STREQ(param->key, "uri")) {
priv->vm_uri = param->value.cstr;
}
} }
break;
case VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON:
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unknown lock manager object type %d"),
type);
goto error;
} }
/* Sanlock needs process registration, but the only way how to probe /* Sanlock needs process registration, but the only way how to probe
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册