[...] VIR_FROM_THIS VIR_FROM_SECURITY > > VIR_LOG_INIT("security.security_manager"); > > +virMutex lockManagerMutex = VIR_MUTEX_INITIALIZER; > + > struct _virSecurityManager { > virObjectLockable parent; > > @@ -43,6 +47,7 @@ struct _virSecurityManager { > void *privateData; > > virLockManagerPluginPtr lockPlugin; > + int fd; > }; > > static virClassPtr virSecurityManagerClass; > @@ -57,6 +62,7 @@ void virSecurityManagerDispose(void *obj) > mgr->drv->close(mgr); > > virObjectUnref(mgr->lockPlugin); > + VIR_FORCE_CLOSE(mgr->fd); > > VIR_FREE(mgr->privateData); > } > @@ -109,6 +115,7 @@ virSecurityManagerNewDriver(virSecurityDriverPtr drv, > mgr->flags = flags; > mgr->virtDriver = virtDriver; > VIR_STEAL_PTR(mgr->privateData, privateData); > + mgr->fd = -1; > > if (drv->open(mgr) < 0) > goto error; > @@ -1263,3 +1270,131 @@ virSecurityManagerRestoreTPMLabels(virSecurityManagerPtr mgr, > > return 0; > } > + > + > +static virLockManagerPtr > +virSecurityManagerNewLockManager(virSecurityManagerPtr mgr, > + const char * const *paths, > + size_t npaths) > +{ > + virLockManagerPtr lock; > + virLockManagerParam params[] = { > + { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID, > + .key = "uuid", > + }, > + { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING, > + .key = "name", > + .value = { .cstr = "libvirtd-sec" }, > + }, > + { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT, > + .key = "pid", > + .value = { .iv = getpid() }, > + }, > + }; > + const unsigned int flags = 0; > + size_t i; > + > + if (virGetHostUUID(params[0].value.uuid) < 0) > + return NULL; > + > + if (!(lock = virLockManagerNew(virLockManagerPluginGetDriver(mgr->lockPlugin), > + VIR_LOCK_MANAGER_OBJECT_TYPE_DAEMON, > + ARRAY_CARDINALITY(params), > + params, > + flags))) > + return NULL; > + > + for (i = 0; i < npaths; i++) { > + if (virLockManagerAddResource(lock, > + VIR_LOCK_MANAGER_RESOURCE_TYPE_METADATA, > + paths[i], 0, NULL, 0) < 0) > + goto error; > + } > + > + return lock; > + error: > + virLockManagerFree(lock); > + return NULL; > +} > + > + > +/* How many seconds should we try to acquire the lock before > + * giving up. */ > +#define LOCK_ACQUIRE_TIMEOUT 60 > + > +int > +virSecurityManagerMetadataLock(virSecurityManagerPtr mgr, > + const char * const *paths, > + size_t npaths) > +{ > + virLockManagerPtr lock; > + virTimeBackOffVar timebackoff; > + int fd = -1; > + int rv; > + int ret = -1; > + > + virMutexLock(&lockManagerMutex); > + > + if (!(lock = virSecurityManagerNewLockManager(mgr, paths, npaths))) > + goto cleanup; > + After seeing it in use in patch 19 and thinking about it for a very short period of time, would it make more sense to store @lock somewhere so that virSecurityManagerMetadataUnlock doesn't fail because the virSecurityManagerNewLockManager fails? The @mgr is mutex locked so that nothing can change @mgr while this Meta Lock/Unlock is occurring. It'd be a shame to not call virLockManagerRelease just because we didn't save @lock John > + if (virTimeBackOffStart(&timebackoff, 1, LOCK_ACQUIRE_TIMEOUT * 1000) < 0) > + goto cleanup; > + while (virTimeBackOffWait(&timebackoff)) { > + rv = virLockManagerAcquire(lock, NULL, > + VIR_LOCK_MANAGER_ACQUIRE_ROLLBACK, > + VIR_DOMAIN_LOCK_FAILURE_DEFAULT, &fd); > + > + if (rv >= 0) > + break; > + > + if (virGetLastErrorCode() == VIR_ERR_RESOURCE_BUSY) > + continue; > + > + goto cleanup; > + } > + > + if (rv < 0) > + goto cleanup; > + > + mgr->fd = fd; > + fd = -1; > + > + ret = 0; > + cleanup: > + virLockManagerFree(lock); > + VIR_FORCE_CLOSE(fd); > + if (ret < 0) > + virMutexUnlock(&lockManagerMutex); > + return ret; > +} > + > + > +int > +virSecurityManagerMetadataUnlock(virSecurityManagerPtr mgr, > + const char * const *paths, > + size_t npaths) > +{ > + virLockManagerPtr lock; > + int fd; > + int ret = -1; > + > + /* lockManagerMutex acquired from previous > + * virSecurityManagerMetadataLock() call. */ > + > + fd = mgr->fd; > + mgr->fd = -1; > + > + if (!(lock = virSecurityManagerNewLockManager(mgr, paths, npaths))) > + goto cleanup; > + > + if (virLockManagerRelease(lock, NULL, 0) < 0) > + goto cleanup; > + > + ret = 0; > + cleanup: > + virLockManagerFree(lock); > + VIR_FORCE_CLOSE(fd); > + virMutexUnlock(&lockManagerMutex); > + return ret; > +} -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list