mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Basic framework for lock manager plugins
Define the basic framework lock manager plugins. The basic plugin API for 3rd parties to implemented is defined in src/locking/lock_driver.h This allows dlopen()able modules for alternative locking schemes, however, we do not install the header. This requires lock plugins to be in-tree allowing changing of the lock manager plugin API in future. The libvirt code for loading & calling into plugins is in src/locking/lock_manager.{c,h} * include/libvirt/virterror.h, src/util/virterror.c: Add VIR_FROM_LOCKING * src/locking/lock_driver.h: API for lock driver plugins to implement * src/locking/lock_manager.c, src/locking/lock_manager.h: Internal API for managing locking * src/Makefile.am: Add locking code
This commit is contained in:
parent
1ea83207c8
commit
6a943419c5
@ -81,6 +81,7 @@ typedef enum {
|
||||
VIR_FROM_VMWARE = 39, /* Error from VMware driver */
|
||||
VIR_FROM_EVENT = 40, /* Error from event loop impl */
|
||||
VIR_FROM_LIBXL = 41, /* Error from libxenlight driver */
|
||||
VIR_FROM_LOCKING = 42, /* Error from lock manager */
|
||||
} virErrorDomain;
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@ src/fdstream.c
|
||||
src/interface/netcf_driver.c
|
||||
src/internal.h
|
||||
src/libvirt.c
|
||||
src/locking/lock_manager.c
|
||||
src/lxc/lxc_container.c
|
||||
src/lxc/lxc_conf.c
|
||||
src/lxc/lxc_controller.c
|
||||
|
@ -93,7 +93,8 @@ DRIVER_SOURCES = \
|
||||
datatypes.c datatypes.h \
|
||||
fdstream.c fdstream.h \
|
||||
$(NODE_INFO_SOURCES) \
|
||||
libvirt.c libvirt_internal.h
|
||||
libvirt.c libvirt_internal.h \
|
||||
locking/lock_manager.c locking/lock_manager.h
|
||||
|
||||
|
||||
# XML configuration format handling sources
|
||||
|
@ -596,6 +596,20 @@ virRegisterSecretDriver;
|
||||
virRegisterStorageDriver;
|
||||
|
||||
|
||||
# locking.h
|
||||
virLockManagerAcquire;
|
||||
virLockManagerAddResource;
|
||||
virLockManagerFree;
|
||||
virLockManagerInquire;
|
||||
virLockManagerNew;
|
||||
virLockManagerPluginNew;
|
||||
virLockManagerPluginRef;
|
||||
virLockManagerPluginUnref;
|
||||
virLockManagerPluginUsesState;
|
||||
virLockManagerPluginGetName;
|
||||
virLockManagerRelease;
|
||||
|
||||
|
||||
# logging.h
|
||||
virLogDefineFilter;
|
||||
virLogDefineOutput;
|
||||
|
158
src/locking/README
Normal file
158
src/locking/README
Normal file
@ -0,0 +1,158 @@
|
||||
|
||||
At libvirtd startup:
|
||||
|
||||
plugin = virLockManagerPluginLoad("sync-manager");
|
||||
|
||||
|
||||
At libvirtd shtudown:
|
||||
|
||||
virLockManagerPluginUnload(plugin)
|
||||
|
||||
|
||||
At guest startup:
|
||||
|
||||
manager = virLockManagerNew(plugin,
|
||||
VIR_LOCK_MANAGER_OBJECT_DOMAIN,
|
||||
0);
|
||||
|
||||
virLockManagerSetParameter(manager, "id", id);
|
||||
virLockManagerSetParameter(manager, "uuid", uuid);
|
||||
virLockManagerSetParameter(manager, "name", name);
|
||||
|
||||
foreach disk
|
||||
virLockManagerRegisterResource(manager,
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
|
||||
disk.path,
|
||||
..flags...);
|
||||
|
||||
if (!virLockManagerAcquireObject(manager))
|
||||
abort..
|
||||
|
||||
run QEMU
|
||||
|
||||
|
||||
At guest shutdown:
|
||||
|
||||
...send QEMU 'quit' monitor command, and/or kill(qemupid)...
|
||||
|
||||
if (!virLockManagerShutdown(manager))
|
||||
kill(supervisorpid); /* XXX or leave it running ??? */
|
||||
|
||||
virLockManagerFree(manager);
|
||||
|
||||
|
||||
|
||||
At libvirtd restart with running guests:
|
||||
|
||||
foreach still running guest
|
||||
manager = virLockManagerNew(driver,
|
||||
VIR_LOCK_MANAGER_START_DOMAIN,
|
||||
VIR_LOCK_MANAGER_NEW_ATTACH);
|
||||
virLockManagerSetParameter(manager, "id", id);
|
||||
virLockManagerSetParameter(manager, "uuid", uuid);
|
||||
virLockManagerSetParameter(manager, "name", name);
|
||||
|
||||
if (!virLockManagerGetChild(manager, &qemupid))
|
||||
kill(supervisorpid); /* XXX or leave it running ??? */
|
||||
|
||||
|
||||
|
||||
With disk hotplug:
|
||||
|
||||
if (virLockManagerAcquireResource(manager,
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
|
||||
disk.path
|
||||
..flags..))
|
||||
...abort hotplug attempt ...
|
||||
|
||||
...hotplug the device...
|
||||
|
||||
|
||||
|
||||
With disk unhotplug:
|
||||
|
||||
...hotunplug the device...
|
||||
|
||||
if (virLockManagerReleaseResource(manager,
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
|
||||
disk.path
|
||||
..flags..))
|
||||
...log warning ...
|
||||
|
||||
|
||||
|
||||
During migration:
|
||||
|
||||
1. On source host
|
||||
|
||||
if (!virLockManagerPrepareMigrate(manager, hosturi))
|
||||
..don't start migration..
|
||||
|
||||
2. On dest host
|
||||
|
||||
manager = virLockManagerNew(driver,
|
||||
VIR_LOCK_MANAGER_START_DOMAIN,
|
||||
VIR_LOCK_MANAGER_NEW_MIGRATE);
|
||||
virLockManagerSetParameter(manager, "id", id);
|
||||
virLockManagerSetParameter(manager, "uuid", uuid);
|
||||
virLockManagerSetParameter(manager, "name", name);
|
||||
|
||||
foreach disk
|
||||
virLockManagerRegisterResource(manager,
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
|
||||
disk.path,
|
||||
..flags...);
|
||||
|
||||
char **supervisorargv;
|
||||
int supervisorargc;
|
||||
|
||||
supervisor = virLockManagerGetSupervisorPath(manager);
|
||||
virLockManagerGetSupervisorArgs(&argv, &argc);
|
||||
|
||||
cmd = qemuBuildCommandLine(supervisor, supervisorargv, supervisorargv);
|
||||
|
||||
supervisorpid = virCommandExec(cmd);
|
||||
|
||||
if (!virLockManagerGetChild(manager, &qemupid))
|
||||
kill(supervisorpid); /* XXX or leave it running ??? */
|
||||
|
||||
3. Initiate migration in QEMU on source and wait for completion
|
||||
|
||||
4a. On failure
|
||||
|
||||
4a1 On target
|
||||
|
||||
virLockManagerCompleteMigrateIn(manager,
|
||||
VIR_LOCK_MANAGER_MIGRATE_CANCEL);
|
||||
virLockManagerShutdown(manager);
|
||||
virLockManagerFree(manager);
|
||||
|
||||
4a2 On source
|
||||
|
||||
virLockManagerCompleteMigrateIn(manager,
|
||||
VIR_LOCK_MANAGER_MIGRATE_CANCEL);
|
||||
|
||||
4b. On succcess
|
||||
|
||||
|
||||
4b1 On target
|
||||
|
||||
virLockManagerCompleteMigrateIn(manager, 0);
|
||||
|
||||
42 On source
|
||||
|
||||
virLockManagerCompleteMigrateIn(manager, 0);
|
||||
virLockManagerShutdown(manager);
|
||||
virLockManagerFree(manager);
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
- If a lock manager impl does just VM level leases, it can
|
||||
ignore all the resource paths at startup.
|
||||
|
||||
- If a lock manager impl does not support migrate
|
||||
it can return an error from all migrate calls
|
||||
|
||||
- If a lock manger impl does not support hotplug
|
||||
it can return an error from all resource acquire/release calls
|
293
src/locking/lock_driver.h
Normal file
293
src/locking/lock_driver.h
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* lock_driver.h: Defines the lock driver plugin API
|
||||
*
|
||||
* Copyright (C) 2010-2011 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VIR_PLUGINS_LOCK_DRIVER_H__
|
||||
# define __VIR_PLUGINS_LOCK_DRIVER_H__
|
||||
|
||||
# include "internal.h"
|
||||
|
||||
typedef struct _virLockManager virLockManager;
|
||||
typedef virLockManager *virLockManagerPtr;
|
||||
|
||||
typedef struct _virLockDriver virLockDriver;
|
||||
typedef virLockDriver *virLockDriverPtr;
|
||||
|
||||
typedef struct _virLockManagerParam virLockManagerParam;
|
||||
typedef virLockManagerParam *virLockManagerParamPtr;
|
||||
|
||||
typedef enum {
|
||||
/* State passing is used to re-acquire existing leases */
|
||||
VIR_LOCK_MANAGER_USES_STATE = (1 << 0)
|
||||
} virLockManagerFlags;
|
||||
|
||||
typedef enum {
|
||||
/* The managed object is a virtual guest domain */
|
||||
VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN = 0,
|
||||
} virLockManagerObjectType;
|
||||
|
||||
typedef enum {
|
||||
/* The resource to be locked is a virtual disk */
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK = 0,
|
||||
/* A lease against an arbitrary resource */
|
||||
VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE = 1,
|
||||
} virLockManagerResourceType;
|
||||
|
||||
typedef enum {
|
||||
/* The resource is assigned in readonly mode */
|
||||
VIR_LOCK_MANAGER_RESOURCE_READONLY = (1 << 0),
|
||||
/* The resource is assigned in shared, writable mode */
|
||||
VIR_LOCK_MANAGER_RESOURCE_SHARED = (1 << 1),
|
||||
} virLockManagerResourceFlags;
|
||||
|
||||
typedef enum {
|
||||
/* Don't acquire the resources, just register the object PID */
|
||||
VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY = (1 << 0)
|
||||
} virLockManagerAcquireFlags;
|
||||
|
||||
enum {
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_INT,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_LONG,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_ULONG,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_DOUBLE,
|
||||
VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
|
||||
};
|
||||
|
||||
struct _virLockManagerParam {
|
||||
int type;
|
||||
const char *key;
|
||||
union {
|
||||
int i;
|
||||
long long l;
|
||||
unsigned int ui;
|
||||
unsigned long long ul;
|
||||
double d;
|
||||
char *str;
|
||||
unsigned char uuid[16];
|
||||
} value;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Changes in major version denote incompatible ABI changes
|
||||
* Changes in minor version denote new compatible API entry points
|
||||
* Changes in micro version denote new compatible flags
|
||||
*/
|
||||
# define VIR_LOCK_MANAGER_VERSION_MAJOR 1
|
||||
# define VIR_LOCK_MANAGER_VERSION_MINOR 0
|
||||
# define VIR_LOCK_MANAGER_VERSION_MICRO 0
|
||||
|
||||
# define VIR_LOCK_MANAGER_VERSION \
|
||||
((VIR_LOCK_MANAGER_VERSION_MAJOR * 1000 * 1000) + \
|
||||
(VIR_LOCK_MANAGER_VERSION_MINOR * 1000) + \
|
||||
(VIR_LOCK_MANAGER_VERSION_MICRO))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* virLockDriverInit:
|
||||
* @version: the libvirt requested plugin ABI version
|
||||
* @flags: the libvirt requested plugin optional extras
|
||||
*
|
||||
* Allow the plugin to validate the libvirt requested
|
||||
* plugin version / flags. This allows the plugin impl
|
||||
* to block its use in versions of libvirtd which are
|
||||
* too old to support key features.
|
||||
*
|
||||
* NB: A plugin may be loaded multiple times, for different
|
||||
* libvirt drivers (eg QEMU, LXC, UML)
|
||||
*
|
||||
* Returns -1 if the requested version/flags were inadequate
|
||||
*/
|
||||
typedef int (*virLockDriverInit)(unsigned int version,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* virLockDriverDeinit:
|
||||
*
|
||||
* Called to release any resources prior to the plugin
|
||||
* being unloaded from memory. Returns -1 to prevent
|
||||
* plugin from being unloaded from memory.
|
||||
*/
|
||||
typedef int (*virLockDriverDeinit)(void);
|
||||
|
||||
/**
|
||||
* virLockManagerNew:
|
||||
* @man: the lock manager context
|
||||
* @type: the type of process to be supervised
|
||||
* @nparams: number of metadata parameters
|
||||
* @params: extra metadata parameters
|
||||
* @flags: optional flags, currently unused
|
||||
*
|
||||
* Initialize a new context to supervise a process, usually
|
||||
* a virtual machine. The lock driver implementation can use
|
||||
* the <code>privateData</code> field of <code>man</code>
|
||||
* to store a pointer to any driver specific state.
|
||||
*
|
||||
* A process of VIR_LOCK_MANAGER_START_DOMAIN will be
|
||||
* given the following parameters
|
||||
*
|
||||
* - id: the domain unique id (unsigned int)
|
||||
* - uuid: the domain uuid (uuid)
|
||||
* - name: the domain name (string)
|
||||
* - pid: process ID to own/owning the lock (unsigned int)
|
||||
*
|
||||
* Returns 0 if successful initialized a new context, -1 on error
|
||||
*/
|
||||
typedef int (*virLockDriverNew)(virLockManagerPtr man,
|
||||
unsigned int type,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* virLockDriverFree:
|
||||
* @manager: the lock manager context
|
||||
*
|
||||
* Release any resources associated with the lock manager
|
||||
* context private data
|
||||
*/
|
||||
typedef void (*virLockDriverFree)(virLockManagerPtr man);
|
||||
|
||||
/**
|
||||
* virLockDriverAddResource:
|
||||
* @manager: the lock manager context
|
||||
* @type: the resource type virLockManagerResourceType
|
||||
* @name: the resource name
|
||||
* @nparams: number of metadata parameters
|
||||
* @params: extra metadata parameters
|
||||
* @flags: the resource access flags
|
||||
*
|
||||
* Assign a resource to a managed object. This will
|
||||
* only be called prior to the object is being locked
|
||||
* when it is inactive. eg, to set the initial boot
|
||||
* time disk assignments on a VM
|
||||
* The format of @name varies according to
|
||||
* the resource @type. A VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK
|
||||
* will have the fully qualified file path, while a resource
|
||||
* of type VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE will have the
|
||||
* unique name of the lease
|
||||
*
|
||||
* A resource of type VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE
|
||||
* will receive at least the following extra parameters
|
||||
*
|
||||
* - 'path': a fully qualified path to the lockspace
|
||||
* - 'lockspace': globally string identifying the lockspace name
|
||||
* - 'offset': byte offset within the lease (unsigned long long)
|
||||
*
|
||||
* If no flags are given, the resource is assumed to be
|
||||
* used in exclusive, read-write mode. Access can be
|
||||
* relaxed to readonly, or shared read-write.
|
||||
*
|
||||
* Returns 0 on success, or -1 on failure
|
||||
*/
|
||||
typedef int (*virLockDriverAddResource)(virLockManagerPtr man,
|
||||
unsigned int type,
|
||||
const char *name,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* virLockDriverAcquire:
|
||||
* @manager: the lock manager context
|
||||
* @state: the current lock state
|
||||
* @flags: optional flags, currently unused
|
||||
*
|
||||
* Start managing resources for the object. This
|
||||
* must be called from the PID that represents the
|
||||
* object to be managed. If the lock is lost at any
|
||||
* time, the PID will be killed off by the lock manager.
|
||||
* The optional state contains information about the
|
||||
* locks previously held for the object.
|
||||
*
|
||||
* Returns 0 on success, or -1 on failure
|
||||
*/
|
||||
typedef int (*virLockDriverAcquire)(virLockManagerPtr man,
|
||||
const char *state,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* virLockDriverRelease:
|
||||
* @manager: the lock manager context
|
||||
* @state: pointer to be filled with lock state
|
||||
* @flags: optional flags
|
||||
*
|
||||
* Inform the lock manager that the supervised process has
|
||||
* been, or can be stopped.
|
||||
*
|
||||
* Returns 0 on success, or -1 on failure
|
||||
*/
|
||||
typedef int (*virLockDriverRelease)(virLockManagerPtr man,
|
||||
char **state,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* virLockDriverInquire:
|
||||
* @manager: the lock manager context
|
||||
* @state: pointer to be filled with lock state
|
||||
* @flags: optional flags, currently unused
|
||||
*
|
||||
* Retrieve the current lock state. The returned
|
||||
* lock state may be NULL if none is required. The
|
||||
* caller is responsible for freeing the lock
|
||||
* state string when it is no longer required
|
||||
*
|
||||
* Returns 0 on success, or -1 on failure.
|
||||
*/
|
||||
typedef int (*virLockDriverInquire)(virLockManagerPtr man,
|
||||
char **state,
|
||||
unsigned int flags);
|
||||
|
||||
|
||||
struct _virLockManager {
|
||||
virLockDriverPtr driver;
|
||||
void *privateData;
|
||||
};
|
||||
|
||||
/**
|
||||
* The plugin must export a static instance of this
|
||||
* driver table, with the name 'virLockDriverImpl'
|
||||
*/
|
||||
struct _virLockDriver {
|
||||
/**
|
||||
* @version: the newest implemented plugin ABI version
|
||||
* @flags: optional flags, currently unused
|
||||
*/
|
||||
unsigned int version;
|
||||
unsigned int flags;
|
||||
|
||||
virLockDriverInit drvInit;
|
||||
virLockDriverDeinit drvDeinit;
|
||||
|
||||
virLockDriverNew drvNew;
|
||||
virLockDriverFree drvFree;
|
||||
|
||||
virLockDriverAddResource drvAddResource;
|
||||
|
||||
virLockDriverAcquire drvAcquire;
|
||||
virLockDriverRelease drvRelease;
|
||||
virLockDriverInquire drvInquire;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __VIR_PLUGINS_LOCK_DRIVER_H__ */
|
357
src/locking/lock_manager.c
Normal file
357
src/locking/lock_manager.c
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* lock_manager.c: Implements the internal lock manager API
|
||||
*
|
||||
* Copyright (C) 2010-2011 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "lock_manager.h"
|
||||
#include "virterror_internal.h"
|
||||
#include "logging.h"
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "uuid.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "configmake.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_LOCKING
|
||||
|
||||
#define virLockError(code, ...) \
|
||||
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
|
||||
__FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#define CHECK_PLUGIN(field, errret) \
|
||||
if (!plugin->driver->field) { \
|
||||
virLockError(VIR_ERR_INTERNAL_ERROR, \
|
||||
_("Missing '%s' field in lock manager driver"), \
|
||||
#field); \
|
||||
return errret; \
|
||||
}
|
||||
|
||||
#define CHECK_MANAGER(field, errret) \
|
||||
if (!lock->driver->field) { \
|
||||
virLockError(VIR_ERR_INTERNAL_ERROR, \
|
||||
_("Missing '%s' field in lock manager driver"), \
|
||||
#field); \
|
||||
return errret; \
|
||||
}
|
||||
|
||||
struct _virLockManagerPlugin {
|
||||
char *name;
|
||||
virLockDriverPtr driver;
|
||||
void *handle;
|
||||
int refs;
|
||||
};
|
||||
|
||||
#define DEFAULT_LOCK_MANAGER_PLUGIN_DIR LIBDIR "/libvirt/lock-driver"
|
||||
|
||||
static void virLockManagerLogParams(size_t nparams,
|
||||
virLockManagerParamPtr params)
|
||||
{
|
||||
int i;
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
for (i = 0 ; i < nparams ; i++) {
|
||||
switch (params[i].type) {
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_INT:
|
||||
VIR_DEBUG(" key=%s type=int value=%d", params[i].key, params[i].value.i);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_UINT:
|
||||
VIR_DEBUG(" key=%s type=uint value=%u", params[i].key, params[i].value.ui);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_LONG:
|
||||
VIR_DEBUG(" key=%s type=long value=%lld", params[i].key, params[i].value.l);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_ULONG:
|
||||
VIR_DEBUG(" key=%s type=ulong value=%llu", params[i].key, params[i].value.ul);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_DOUBLE:
|
||||
VIR_DEBUG(" key=%s type=double value=%lf", params[i].key, params[i].value.d);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_STRING:
|
||||
VIR_DEBUG(" key=%s type=string value=%s", params[i].key, params[i].value.str);
|
||||
break;
|
||||
case VIR_LOCK_MANAGER_PARAM_TYPE_UUID:
|
||||
virUUIDFormat(params[i].value.uuid, uuidstr);
|
||||
VIR_DEBUG(" key=%s type=uuid value=%s", params[i].key, uuidstr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virLockManagerPluginNew:
|
||||
* @name: the name of the plugin
|
||||
* @flag: optional plugin flags
|
||||
*
|
||||
* Attempt to load the plugin $(libdir)/libvirt/lock-driver/@name.so
|
||||
* The plugin driver entry point will be resolved & invoked to obtain
|
||||
* the lock manager driver.
|
||||
*
|
||||
* Even if the loading of the plugin succeeded, this may still
|
||||
* return NULL if the plugin impl decided that we (libvirtd)
|
||||
* are too old to support a feature it requires
|
||||
*
|
||||
* Returns a plugin object, or NULL if loading failed.
|
||||
*/
|
||||
virLockManagerPluginPtr virLockManagerPluginNew(const char *name,
|
||||
unsigned int flags)
|
||||
{
|
||||
void *handle = NULL;
|
||||
virLockDriverPtr driver;
|
||||
virLockManagerPluginPtr plugin;
|
||||
const char *moddir = getenv("LIBVIRT_LOCK_MANAGER_PLUGIN_DIR");
|
||||
char *modfile = NULL;
|
||||
|
||||
if (moddir == NULL)
|
||||
moddir = DEFAULT_LOCK_MANAGER_PLUGIN_DIR;
|
||||
|
||||
VIR_DEBUG("Module load %s from %s", name, moddir);
|
||||
|
||||
if (virAsprintf(&modfile, "%s/%s.so", moddir, name) < 0) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (access(modfile, R_OK) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Plugin %s not accessible"),
|
||||
modfile);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
handle = dlopen(modfile, RTLD_NOW | RTLD_LOCAL);
|
||||
if (!handle) {
|
||||
virLockError(VIR_ERR_SYSTEM_ERROR,
|
||||
_("Failed to load plugin %s: %s"),
|
||||
modfile, dlerror());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(driver = dlsym(handle, "virLockDriverImpl"))) {
|
||||
virLockError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("Missing plugin initialization symbol 'virLockDriverImpl'"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (driver->drvInit(VIR_LOCK_MANAGER_VERSION, flags) < 0) {
|
||||
virLockError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("plugin ABI is not compatible"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(plugin) < 0) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
plugin->driver = driver;
|
||||
plugin->handle = handle;
|
||||
plugin->refs = 1;
|
||||
if (!(plugin->name = strdup(name))) {
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FREE(modfile);
|
||||
return plugin;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(modfile);
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virLockManagerPluginRef:
|
||||
* @plugin: the plugin implementation to ref
|
||||
*
|
||||
* Acquires an additional reference on the plugin.
|
||||
*/
|
||||
void virLockManagerPluginRef(virLockManagerPluginPtr plugin)
|
||||
{
|
||||
plugin->refs++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virLockManagerPluginUnref:
|
||||
* @plugin: the plugin implementation to unref
|
||||
*
|
||||
* Releases a reference on the plugin. When the last reference
|
||||
* is released, it will attempt to unload the plugin from memory.
|
||||
* The plugin may refuse to allow unloading if this would
|
||||
* result in an unsafe scenario.
|
||||
*
|
||||
*/
|
||||
void virLockManagerPluginUnref(virLockManagerPluginPtr plugin)
|
||||
{
|
||||
if (!plugin)
|
||||
return;
|
||||
|
||||
plugin->refs--;
|
||||
|
||||
if (plugin->refs > 0)
|
||||
return;
|
||||
|
||||
if (plugin->driver->drvDeinit() >= 0) {
|
||||
if (plugin->handle)
|
||||
dlclose(plugin->handle);
|
||||
} else {
|
||||
VIR_WARN("Unable to unload lock maanger plugin from memory");
|
||||
return;
|
||||
}
|
||||
|
||||
VIR_FREE(plugin->name);
|
||||
VIR_FREE(plugin);
|
||||
}
|
||||
|
||||
|
||||
const char *virLockManagerPluginGetName(virLockManagerPluginPtr plugin)
|
||||
{
|
||||
VIR_DEBUG("plugin=%p", plugin);
|
||||
|
||||
return plugin->name;
|
||||
}
|
||||
|
||||
|
||||
bool virLockManagerPluginUsesState(virLockManagerPluginPtr plugin)
|
||||
{
|
||||
VIR_DEBUG("plugin=%p", plugin);
|
||||
|
||||
return plugin->driver->flags & VIR_LOCK_MANAGER_USES_STATE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virLockManagerNew:
|
||||
* @plugin: the plugin implementation to use
|
||||
* @type: the type of process to be supervised
|
||||
* @flags: optional flags, currently unused
|
||||
*
|
||||
* Create a new context to supervise a process, usually
|
||||
* a virtual machine.
|
||||
*
|
||||
* Returns a new lock manager context
|
||||
*/
|
||||
virLockManagerPtr virLockManagerNew(virLockManagerPluginPtr plugin,
|
||||
unsigned int type,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags)
|
||||
{
|
||||
virLockManagerPtr lock;
|
||||
VIR_DEBUG("plugin=%p type=%u nparams=%zu params=%p flags=%u",
|
||||
plugin, type, nparams, params, flags);
|
||||
virLockManagerLogParams(nparams, params);
|
||||
|
||||
CHECK_PLUGIN(drvNew, NULL);
|
||||
|
||||
if (VIR_ALLOC(lock) < 0) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock->driver = plugin->driver;
|
||||
|
||||
if (plugin->driver->drvNew(lock, type, nparams, params, flags) < 0) {
|
||||
VIR_FREE(lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
|
||||
int virLockManagerAddResource(virLockManagerPtr lock,
|
||||
unsigned int type,
|
||||
const char *name,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags)
|
||||
{
|
||||
VIR_DEBUG("lock=%p type=%u name=%s nparams=%zu params=%p flags=%u",
|
||||
lock, type, name, nparams, params, flags);
|
||||
virLockManagerLogParams(nparams, params);
|
||||
|
||||
CHECK_MANAGER(drvAddResource, -1);
|
||||
|
||||
return lock->driver->drvAddResource(lock,
|
||||
type, name,
|
||||
nparams, params,
|
||||
flags);
|
||||
}
|
||||
|
||||
int virLockManagerAcquire(virLockManagerPtr lock,
|
||||
const char *state,
|
||||
unsigned int flags)
|
||||
{
|
||||
VIR_DEBUG("lock=%p state='%s' flags=%u", lock, NULLSTR(state), flags);
|
||||
|
||||
CHECK_MANAGER(drvAcquire, -1);
|
||||
|
||||
return lock->driver->drvAcquire(lock, state, flags);
|
||||
}
|
||||
|
||||
|
||||
int virLockManagerRelease(virLockManagerPtr lock,
|
||||
char **state,
|
||||
unsigned int flags)
|
||||
{
|
||||
VIR_DEBUG("lock=%p state=%p flags=%u", lock, state, flags);
|
||||
|
||||
CHECK_MANAGER(drvRelease, -1);
|
||||
|
||||
return lock->driver->drvRelease(lock, state, flags);
|
||||
}
|
||||
|
||||
|
||||
int virLockManagerInquire(virLockManagerPtr lock,
|
||||
char **state,
|
||||
unsigned int flags)
|
||||
{
|
||||
VIR_DEBUG("lock=%p state=%p flags=%u", lock, state, flags);
|
||||
|
||||
CHECK_MANAGER(drvInquire, -1);
|
||||
|
||||
return lock->driver->drvInquire(lock, state, flags);
|
||||
}
|
||||
|
||||
|
||||
int virLockManagerFree(virLockManagerPtr lock)
|
||||
{
|
||||
VIR_DEBUG("lock=%p", lock);
|
||||
|
||||
if (!lock)
|
||||
return 0;
|
||||
|
||||
CHECK_MANAGER(drvFree, -1);
|
||||
|
||||
lock->driver->drvFree(lock);
|
||||
|
||||
VIR_FREE(lock);
|
||||
|
||||
return 0;
|
||||
}
|
65
src/locking/lock_manager.h
Normal file
65
src/locking/lock_manager.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* lock_manager.h: Defines the internal lock manager API
|
||||
*
|
||||
* Copyright (C) 2010-2011 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __VIR_LOCK_MANAGER_H__
|
||||
# define __VIR_LOCK_MANAGER_H__
|
||||
|
||||
# include "internal.h"
|
||||
# include "lock_driver.h"
|
||||
|
||||
typedef struct _virLockManagerPlugin virLockManagerPlugin;
|
||||
typedef virLockManagerPlugin *virLockManagerPluginPtr;
|
||||
|
||||
virLockManagerPluginPtr virLockManagerPluginNew(const char *name,
|
||||
unsigned int flags);
|
||||
void virLockManagerPluginRef(virLockManagerPluginPtr plugin);
|
||||
void virLockManagerPluginUnref(virLockManagerPluginPtr plugin);
|
||||
|
||||
const char *virLockManagerPluginGetName(virLockManagerPluginPtr plugin);
|
||||
bool virLockManagerPluginUsesState(virLockManagerPluginPtr plugin);
|
||||
|
||||
|
||||
virLockManagerPtr virLockManagerNew(virLockManagerPluginPtr plugin,
|
||||
unsigned int type,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags);
|
||||
|
||||
int virLockManagerAddResource(virLockManagerPtr manager,
|
||||
unsigned int type,
|
||||
const char *name,
|
||||
size_t nparams,
|
||||
virLockManagerParamPtr params,
|
||||
unsigned int flags);
|
||||
|
||||
int virLockManagerAcquire(virLockManagerPtr manager,
|
||||
const char *state,
|
||||
unsigned int flags);
|
||||
int virLockManagerRelease(virLockManagerPtr manager,
|
||||
char **state,
|
||||
unsigned int flags);
|
||||
int virLockManagerInquire(virLockManagerPtr manager,
|
||||
char **state,
|
||||
unsigned int flags);
|
||||
|
||||
int virLockManagerFree(virLockManagerPtr manager);
|
||||
|
||||
#endif /* __VIR_LOCK_MANAGER_H__ */
|
@ -169,6 +169,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
|
||||
case VIR_FROM_EVENT:
|
||||
dom = "Events ";
|
||||
break;
|
||||
case VIR_FROM_LOCKING:
|
||||
dom = "Locking ";
|
||||
break;
|
||||
}
|
||||
return(dom);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user