2011-07-06 16:30:08 +00:00
|
|
|
/*
|
|
|
|
* lock_driver_lockd.c: A lock driver which locks nothing
|
|
|
|
*
|
2014-10-28 20:17:04 +00:00
|
|
|
* Copyright (C) 2010-2011, 2014 Red Hat, Inc.
|
2011-07-06 16:30:08 +00:00
|
|
|
*
|
|
|
|
* 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 "lock_driver.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2014-03-05 12:39:00 +00:00
|
|
|
#include "vircrypto.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2011-07-06 16:30:08 +00:00
|
|
|
#include "virfile.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2011-07-06 16:30:08 +00:00
|
|
|
#include "rpc/virnetclient.h"
|
|
|
|
#include "lock_protocol.h"
|
|
|
|
#include "configmake.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2011-07-06 16:30:08 +00:00
|
|
|
|
2016-01-12 15:47:13 +00:00
|
|
|
#include "lock_driver_lockd.h"
|
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_LOCKING
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("locking.lock_driver_lockd");
|
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
typedef struct _virLockManagerLockDaemonPrivate virLockManagerLockDaemonPrivate;
|
|
|
|
typedef virLockManagerLockDaemonPrivate *virLockManagerLockDaemonPrivatePtr;
|
|
|
|
|
|
|
|
typedef struct _virLockManagerLockDaemonResource virLockManagerLockDaemonResource;
|
|
|
|
typedef virLockManagerLockDaemonResource *virLockManagerLockDaemonResourcePtr;
|
|
|
|
|
|
|
|
typedef struct _virLockManagerLockDaemonDriver virLockManagerLockDaemonDriver;
|
|
|
|
typedef virLockManagerLockDaemonDriver *virLockManagerLockDaemonDriverPtr;
|
|
|
|
|
|
|
|
struct _virLockManagerLockDaemonResource {
|
|
|
|
char *lockspace;
|
|
|
|
char *name;
|
|
|
|
unsigned int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _virLockManagerLockDaemonPrivate {
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
char *name;
|
|
|
|
int id;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
size_t nresources;
|
|
|
|
virLockManagerLockDaemonResourcePtr resources;
|
|
|
|
|
|
|
|
bool hasRWDisks;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct _virLockManagerLockDaemonDriver {
|
|
|
|
bool autoDiskLease;
|
|
|
|
bool requireLeaseForDisks;
|
2012-08-14 15:46:08 +00:00
|
|
|
|
|
|
|
char *fileLockSpaceDir;
|
2012-12-11 16:39:50 +00:00
|
|
|
char *lvmLockSpaceDir;
|
2012-12-11 16:39:50 +00:00
|
|
|
char *scsiLockSpaceDir;
|
2011-07-06 16:30:08 +00:00
|
|
|
};
|
|
|
|
|
2014-10-28 20:17:04 +00:00
|
|
|
static virLockManagerLockDaemonDriverPtr driver;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
static int virLockManagerLockDaemonLoadConfig(const char *configFile)
|
|
|
|
{
|
|
|
|
virConfPtr conf;
|
|
|
|
virConfValuePtr p;
|
|
|
|
|
|
|
|
if (access(configFile, R_OK) == -1) {
|
|
|
|
if (errno != ENOENT) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to access config file %s"),
|
|
|
|
configFile);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(conf = virConfReadFile(configFile, 0)))
|
|
|
|
return -1;
|
|
|
|
|
2014-08-22 12:59:28 +00:00
|
|
|
#define CHECK_TYPE(name, typ) if (p && p->type != (typ)) { \
|
2011-07-06 16:30:08 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
|
|
|
"%s: %s: expected type " #typ, \
|
|
|
|
configFile, (name)); \
|
|
|
|
virConfFree(conf); \
|
|
|
|
return -1; \
|
|
|
|
}
|
|
|
|
|
|
|
|
p = virConfGetValue(conf, "auto_disk_leases");
|
2014-12-09 15:22:09 +00:00
|
|
|
CHECK_TYPE("auto_disk_leases", VIR_CONF_ULONG);
|
2011-07-06 16:30:08 +00:00
|
|
|
if (p) driver->autoDiskLease = p->l;
|
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
p = virConfGetValue(conf, "file_lockspace_dir");
|
|
|
|
CHECK_TYPE("file_lockspace_dir", VIR_CONF_STRING);
|
|
|
|
if (p && p->str) {
|
|
|
|
VIR_FREE(driver->fileLockSpaceDir);
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(driver->fileLockSpaceDir, p->str) < 0) {
|
2012-08-14 15:46:08 +00:00
|
|
|
virConfFree(conf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-11 16:39:50 +00:00
|
|
|
p = virConfGetValue(conf, "lvm_lockspace_dir");
|
|
|
|
CHECK_TYPE("lvm_lockspace_dir", VIR_CONF_STRING);
|
|
|
|
if (p && p->str) {
|
|
|
|
VIR_FREE(driver->lvmLockSpaceDir);
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(driver->lvmLockSpaceDir, p->str) < 0) {
|
2012-12-11 16:39:50 +00:00
|
|
|
virConfFree(conf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-11 16:39:50 +00:00
|
|
|
p = virConfGetValue(conf, "scsi_lockspace_dir");
|
|
|
|
CHECK_TYPE("scsi_lockspace_dir", VIR_CONF_STRING);
|
|
|
|
if (p && p->str) {
|
|
|
|
VIR_FREE(driver->scsiLockSpaceDir);
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(driver->scsiLockSpaceDir, p->str) < 0) {
|
2012-12-11 16:39:50 +00:00
|
|
|
virConfFree(conf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
p = virConfGetValue(conf, "require_lease_for_disks");
|
2014-12-09 15:22:09 +00:00
|
|
|
CHECK_TYPE("require_lease_for_disks", VIR_CONF_ULONG);
|
2011-07-06 16:30:08 +00:00
|
|
|
if (p)
|
|
|
|
driver->requireLeaseForDisks = p->l;
|
|
|
|
else
|
|
|
|
driver->requireLeaseForDisks = !driver->autoDiskLease;
|
|
|
|
|
|
|
|
virConfFree(conf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *virLockManagerLockDaemonPath(bool privileged)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
if (privileged) {
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(path, LOCALSTATEDIR "/run/libvirt/virtlockd-sock") < 0)
|
2011-07-06 16:30:08 +00:00
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
char *rundir = NULL;
|
|
|
|
|
|
|
|
if (!(rundir = virGetUserRuntimeDirectory()))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&path, "%s/virtlockd-sock", rundir) < 0) {
|
|
|
|
VIR_FREE(rundir);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-11-24 13:16:23 +00:00
|
|
|
VIR_FREE(rundir);
|
2011-07-06 16:30:08 +00:00
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virLockManagerLockDaemonConnectionRegister(virLockManagerPtr lock,
|
|
|
|
virNetClientPtr client,
|
|
|
|
virNetClientProgramPtr program,
|
|
|
|
int *counter)
|
|
|
|
{
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
|
|
|
virLockSpaceProtocolRegisterArgs args;
|
|
|
|
int rv = -1;
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
args.flags = 0;
|
|
|
|
memcpy(args.owner.uuid, priv->uuid, VIR_UUID_BUFLEN);
|
|
|
|
args.owner.name = priv->name;
|
|
|
|
args.owner.id = priv->id;
|
|
|
|
args.owner.pid = priv->pid;
|
|
|
|
|
|
|
|
if (virNetClientProgramCall(program,
|
|
|
|
client,
|
|
|
|
(*counter)++,
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_PROC_REGISTER,
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
(xdrproc_t)xdr_virLockSpaceProtocolRegisterArgs, (char*)&args,
|
|
|
|
(xdrproc_t)xdr_void, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
cleanup:
|
2011-07-06 16:30:08 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virLockManagerLockDaemonConnectionRestrict(virLockManagerPtr lock ATTRIBUTE_UNUSED,
|
|
|
|
virNetClientPtr client,
|
|
|
|
virNetClientProgramPtr program,
|
|
|
|
int *counter)
|
|
|
|
{
|
|
|
|
virLockSpaceProtocolRestrictArgs args;
|
|
|
|
int rv = -1;
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
args.flags = 0;
|
|
|
|
|
|
|
|
if (virNetClientProgramCall(program,
|
|
|
|
client,
|
|
|
|
(*counter)++,
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_PROC_RESTRICT,
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
(xdrproc_t)xdr_virLockSpaceProtocolRestrictArgs, (char*)&args,
|
|
|
|
(xdrproc_t)xdr_void, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
cleanup:
|
2011-07-06 16:30:08 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virNetClientPtr virLockManagerLockDaemonConnectionNew(bool privileged,
|
|
|
|
virNetClientProgramPtr *prog)
|
|
|
|
{
|
|
|
|
virNetClientPtr client = NULL;
|
|
|
|
char *lockdpath;
|
2014-07-15 11:36:00 +00:00
|
|
|
char *daemonPath = NULL;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
*prog = NULL;
|
|
|
|
|
|
|
|
if (!(lockdpath = virLockManagerLockDaemonPath(privileged)))
|
|
|
|
goto error;
|
|
|
|
|
2014-04-25 10:55:32 +00:00
|
|
|
if (!privileged &&
|
|
|
|
!(daemonPath = virFileFindResourceFull("virtlockd",
|
|
|
|
NULL, NULL,
|
2015-02-13 13:25:27 +00:00
|
|
|
abs_topbuilddir "/src",
|
2014-04-25 10:55:32 +00:00
|
|
|
SBINDIR,
|
|
|
|
"VIRTLOCKD_PATH")))
|
|
|
|
goto error;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
if (!(client = virNetClientNewUNIX(lockdpath,
|
|
|
|
daemonPath != NULL,
|
|
|
|
daemonPath)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!(*prog = virNetClientProgramNew(VIR_LOCK_SPACE_PROTOCOL_PROGRAM,
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_PROGRAM_VERSION,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virNetClientAddProgram(client, *prog) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-07-07 06:18:44 +00:00
|
|
|
VIR_FREE(daemonPath);
|
2011-07-06 16:30:08 +00:00
|
|
|
VIR_FREE(lockdpath);
|
|
|
|
|
|
|
|
return client;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
error:
|
2014-07-07 06:18:44 +00:00
|
|
|
VIR_FREE(daemonPath);
|
2011-07-06 16:30:08 +00:00
|
|
|
VIR_FREE(lockdpath);
|
|
|
|
virNetClientClose(client);
|
|
|
|
virObjectUnref(client);
|
|
|
|
virObjectUnref(*prog);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virNetClientPtr
|
|
|
|
virLockManagerLockDaemonConnect(virLockManagerPtr lock,
|
|
|
|
virNetClientProgramPtr *program,
|
|
|
|
int *counter)
|
|
|
|
{
|
|
|
|
virNetClientPtr client;
|
|
|
|
|
2013-10-09 11:13:45 +00:00
|
|
|
if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, program)))
|
2011-07-06 16:30:08 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virLockManagerLockDaemonConnectionRegister(lock,
|
|
|
|
client,
|
|
|
|
*program,
|
|
|
|
counter) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return client;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
error:
|
2011-07-06 16:30:08 +00:00
|
|
|
virNetClientClose(client);
|
|
|
|
virObjectUnref(client);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
static int virLockManagerLockDaemonSetupLockspace(const char *path)
|
|
|
|
{
|
|
|
|
virNetClientPtr client;
|
|
|
|
virNetClientProgramPtr program = NULL;
|
|
|
|
virLockSpaceProtocolCreateLockSpaceArgs args;
|
|
|
|
int rv = -1;
|
|
|
|
int counter = 0;
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
args.path = (char*)path;
|
|
|
|
|
2013-10-09 11:13:45 +00:00
|
|
|
if (!(client = virLockManagerLockDaemonConnectionNew(geteuid() == 0, &program)))
|
2012-08-14 15:46:08 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virNetClientProgramCall(program,
|
|
|
|
client,
|
|
|
|
counter++,
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_PROC_CREATE_LOCKSPACE,
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
(xdrproc_t)xdr_virLockSpaceProtocolCreateLockSpaceArgs, (char*)&args,
|
|
|
|
(xdrproc_t)xdr_void, NULL) < 0) {
|
|
|
|
virErrorPtr err = virGetLastError();
|
|
|
|
if (err && err->code == VIR_ERR_OPERATION_INVALID) {
|
|
|
|
/* The lockspace already exists */
|
|
|
|
virResetLastError();
|
|
|
|
rv = 0;
|
|
|
|
} else {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
cleanup:
|
2012-08-14 15:46:08 +00:00
|
|
|
virObjectUnref(program);
|
|
|
|
virNetClientClose(client);
|
|
|
|
virObjectUnref(client);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
static int virLockManagerLockDaemonDeinit(void);
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonInit(unsigned int version,
|
|
|
|
const char *configFile,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("version=%u configFile=%s flags=%x", version, NULLSTR(configFile), flags);
|
|
|
|
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (driver)
|
|
|
|
return 0;
|
|
|
|
|
2013-07-04 10:11:02 +00:00
|
|
|
if (VIR_ALLOC(driver) < 0)
|
2011-07-06 16:30:08 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
driver->requireLeaseForDisks = true;
|
|
|
|
driver->autoDiskLease = true;
|
|
|
|
|
|
|
|
if (virLockManagerLockDaemonLoadConfig(configFile) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
if (driver->autoDiskLease) {
|
|
|
|
if (driver->fileLockSpaceDir &&
|
|
|
|
virLockManagerLockDaemonSetupLockspace(driver->fileLockSpaceDir) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2012-12-11 16:39:50 +00:00
|
|
|
if (driver->lvmLockSpaceDir &&
|
|
|
|
virLockManagerLockDaemonSetupLockspace(driver->lvmLockSpaceDir) < 0)
|
|
|
|
goto error;
|
2012-12-11 16:39:50 +00:00
|
|
|
|
|
|
|
if (driver->scsiLockSpaceDir &&
|
|
|
|
virLockManagerLockDaemonSetupLockspace(driver->scsiLockSpaceDir) < 0)
|
|
|
|
goto error;
|
2012-12-11 16:39:50 +00:00
|
|
|
}
|
2012-08-14 15:46:08 +00:00
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
error:
|
2011-07-06 16:30:08 +00:00
|
|
|
virLockManagerLockDaemonDeinit();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonDeinit(void)
|
|
|
|
{
|
|
|
|
if (!driver)
|
|
|
|
return 0;
|
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
VIR_FREE(driver->fileLockSpaceDir);
|
2011-07-06 16:30:08 +00:00
|
|
|
VIR_FREE(driver);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void virLockManagerLockDaemonFree(virLockManagerPtr lock)
|
|
|
|
{
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!priv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lock->privateData = NULL;
|
|
|
|
|
2013-05-21 08:06:00 +00:00
|
|
|
for (i = 0; i < priv->nresources; i++) {
|
2011-07-06 16:30:08 +00:00
|
|
|
VIR_FREE(priv->resources[i].lockspace);
|
|
|
|
VIR_FREE(priv->resources[i].name);
|
|
|
|
}
|
|
|
|
VIR_FREE(priv->resources);
|
|
|
|
|
|
|
|
VIR_FREE(priv->name);
|
|
|
|
|
|
|
|
VIR_FREE(priv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonNew(virLockManagerPtr lock,
|
|
|
|
unsigned int type,
|
|
|
|
size_t nparams,
|
|
|
|
virLockManagerParamPtr params,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv;
|
|
|
|
size_t i;
|
|
|
|
|
2015-03-06 14:58:55 +00:00
|
|
|
virCheckFlags(VIR_LOCK_MANAGER_NEW_STARTED, -1);
|
2011-07-06 16:30:08 +00:00
|
|
|
|
2013-07-04 10:11:02 +00:00
|
|
|
if (VIR_ALLOC(priv) < 0)
|
2011-07-06 16:30:08 +00:00
|
|
|
return -1;
|
|
|
|
lock->privateData = priv;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
|
2013-05-21 08:06:00 +00:00
|
|
|
for (i = 0; i < nparams; i++) {
|
2011-07-06 16:30:08 +00:00
|
|
|
if (STREQ(params[i].key, "uuid")) {
|
|
|
|
memcpy(priv->uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
|
|
|
|
} else if (STREQ(params[i].key, "name")) {
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(priv->name, params[i].value.str) < 0)
|
2011-07-06 16:30:08 +00:00
|
|
|
return -1;
|
|
|
|
} else if (STREQ(params[i].key, "id")) {
|
Convert 'int i' to 'size_t i' in src/locking/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
priv->id = params[i].value.iv;
|
2011-07-06 16:30:08 +00:00
|
|
|
} else if (STREQ(params[i].key, "pid")) {
|
Convert 'int i' to 'size_t i' in src/locking/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
priv->pid = params[i].value.iv;
|
2013-05-03 13:23:03 +00:00
|
|
|
} else if (STREQ(params[i].key, "uri")) {
|
|
|
|
/* ignored */
|
2011-07-06 16:30:08 +00:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unexpected parameter %s for object"),
|
|
|
|
params[i].key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (priv->id == 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing ID parameter for domain object"));
|
|
|
|
return -1;
|
|
|
|
}
|
2015-04-16 17:32:42 +00:00
|
|
|
if (priv->pid == 0)
|
|
|
|
VIR_DEBUG("Missing PID parameter for domain object");
|
2011-07-06 16:30:08 +00:00
|
|
|
if (!priv->name) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing name parameter for domain object"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!virUUIDIsValid(priv->uuid)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing UUID parameter for domain object"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown lock manager object type %d"),
|
|
|
|
type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock,
|
|
|
|
unsigned int type,
|
|
|
|
const char *name,
|
|
|
|
size_t nparams,
|
|
|
|
virLockManagerParamPtr params,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
2012-08-14 15:46:08 +00:00
|
|
|
char *newName = NULL;
|
2011-07-06 16:30:08 +00:00
|
|
|
char *newLockspace = NULL;
|
2012-08-14 15:46:08 +00:00
|
|
|
bool autoCreate = false;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
virCheckFlags(VIR_LOCK_MANAGER_RESOURCE_READONLY |
|
|
|
|
VIR_LOCK_MANAGER_RESOURCE_SHARED, -1);
|
|
|
|
|
|
|
|
if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK:
|
|
|
|
if (params || nparams) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unexpected parameters for disk resource"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!driver->autoDiskLease) {
|
|
|
|
if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED |
|
|
|
|
VIR_LOCK_MANAGER_RESOURCE_READONLY)))
|
|
|
|
priv->hasRWDisks = true;
|
|
|
|
return 0;
|
|
|
|
}
|
2012-08-14 15:46:08 +00:00
|
|
|
|
2012-12-11 16:39:50 +00:00
|
|
|
/* XXX we should somehow pass in TYPE=BLOCK info
|
|
|
|
* from the domain_lock code, instead of assuming /dev
|
|
|
|
*/
|
|
|
|
if (STRPREFIX(name, "/dev") &&
|
|
|
|
driver->lvmLockSpaceDir) {
|
|
|
|
VIR_DEBUG("Trying to find an LVM UUID for %s", name);
|
|
|
|
if (virStorageFileGetLVMKey(name, &newName) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (newName) {
|
|
|
|
VIR_DEBUG("Got an LVM UUID %s for %s", newName, name);
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(newLockspace, driver->lvmLockSpaceDir) < 0)
|
|
|
|
goto error;
|
2012-12-11 16:39:50 +00:00
|
|
|
autoCreate = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
virResetLastError();
|
|
|
|
/* Fallback to generic non-block code */
|
|
|
|
}
|
2012-12-11 16:39:50 +00:00
|
|
|
|
|
|
|
if (STRPREFIX(name, "/dev") &&
|
|
|
|
driver->scsiLockSpaceDir) {
|
|
|
|
VIR_DEBUG("Trying to find an SCSI ID for %s", name);
|
|
|
|
if (virStorageFileGetSCSIKey(name, &newName) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (newName) {
|
|
|
|
VIR_DEBUG("Got an SCSI ID %s for %s", newName, name);
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(newLockspace, driver->scsiLockSpaceDir) < 0)
|
|
|
|
goto error;
|
2012-12-11 16:39:50 +00:00
|
|
|
autoCreate = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
virResetLastError();
|
|
|
|
/* Fallback to generic non-block code */
|
|
|
|
}
|
2012-12-11 16:39:50 +00:00
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
if (driver->fileLockSpaceDir) {
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(newLockspace, driver->fileLockSpaceDir) < 0)
|
|
|
|
goto error;
|
2014-03-05 12:39:00 +00:00
|
|
|
if (virCryptoHashString(VIR_CRYPTO_HASH_SHA256, name, &newName) < 0)
|
2013-07-04 10:11:02 +00:00
|
|
|
goto error;
|
2012-08-14 15:46:08 +00:00
|
|
|
autoCreate = true;
|
|
|
|
VIR_DEBUG("Using indirect lease %s for %s", newName, name);
|
|
|
|
} else {
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(newLockspace, "") < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(newName, name) < 0)
|
|
|
|
goto error;
|
2012-08-14 15:46:08 +00:00
|
|
|
VIR_DEBUG("Using direct lease for %s", name);
|
2011-07-06 16:30:08 +00:00
|
|
|
}
|
2012-08-14 15:46:08 +00:00
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
break;
|
|
|
|
case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: {
|
|
|
|
size_t i;
|
|
|
|
char *path = NULL;
|
|
|
|
char *lockspace = NULL;
|
2013-05-21 08:06:00 +00:00
|
|
|
for (i = 0; i < nparams; i++) {
|
2011-07-06 16:30:08 +00:00
|
|
|
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"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} 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);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!path || !lockspace) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Missing path or lockspace for lease resource"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (virAsprintf(&newLockspace, "%s/%s",
|
2013-07-04 10:11:02 +00:00
|
|
|
path, lockspace) < 0)
|
2011-07-06 16:30:08 +00:00
|
|
|
return -1;
|
2013-05-03 12:43:12 +00:00
|
|
|
if (VIR_STRDUP(newName, name) < 0)
|
|
|
|
goto error;
|
2012-08-14 15:46:08 +00:00
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown lock manager object type %d"),
|
|
|
|
type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_EXPAND_N(priv->resources, priv->nresources, 1) < 0)
|
2013-07-04 10:11:02 +00:00
|
|
|
goto error;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
priv->resources[priv->nresources-1].lockspace = newLockspace;
|
|
|
|
priv->resources[priv->nresources-1].name = newName;
|
|
|
|
|
|
|
|
if (flags & VIR_LOCK_MANAGER_RESOURCE_SHARED)
|
|
|
|
priv->resources[priv->nresources-1].flags |=
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED;
|
|
|
|
|
2012-08-14 15:46:08 +00:00
|
|
|
if (autoCreate)
|
|
|
|
priv->resources[priv->nresources-1].flags |=
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_AUTOCREATE;
|
|
|
|
|
2011-07-06 16:30:08 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
error:
|
2012-08-14 15:46:08 +00:00
|
|
|
VIR_FREE(newLockspace);
|
2011-07-06 16:30:08 +00:00
|
|
|
VIR_FREE(newName);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
|
|
|
|
const char *state ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags,
|
|
|
|
virDomainLockFailureAction action ATTRIBUTE_UNUSED,
|
|
|
|
int *fd)
|
|
|
|
{
|
|
|
|
virNetClientPtr client = NULL;
|
|
|
|
virNetClientProgramPtr program = NULL;
|
|
|
|
int counter = 0;
|
|
|
|
int rv = -1;
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
|
|
|
|
|
|
|
virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY |
|
|
|
|
VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1);
|
|
|
|
|
|
|
|
if (priv->nresources == 0 &&
|
|
|
|
priv->hasRWDisks &&
|
|
|
|
driver->requireLeaseForDisks) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Read/write, exclusive access, disks were present, but no leases specified"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (fd &&
|
|
|
|
(*fd = virNetClientDupFD(client, false)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) {
|
|
|
|
size_t i;
|
2013-05-21 08:06:00 +00:00
|
|
|
for (i = 0; i < priv->nresources; i++) {
|
2011-07-06 16:30:08 +00:00
|
|
|
virLockSpaceProtocolAcquireResourceArgs args;
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
if (priv->resources[i].lockspace)
|
2012-08-14 15:46:08 +00:00
|
|
|
args.path = priv->resources[i].lockspace;
|
2011-07-06 16:30:08 +00:00
|
|
|
args.name = priv->resources[i].name;
|
|
|
|
args.flags = priv->resources[i].flags;
|
|
|
|
|
|
|
|
if (virNetClientProgramCall(program,
|
|
|
|
client,
|
|
|
|
counter++,
|
|
|
|
VIR_LOCK_SPACE_PROTOCOL_PROC_ACQUIRE_RESOURCE,
|
|
|
|
0, NULL, NULL, NULL,
|
|
|
|
(xdrproc_t)xdr_virLockSpaceProtocolAcquireResourceArgs, &args,
|
|
|
|
(xdrproc_t)xdr_void, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & VIR_LOCK_MANAGER_ACQUIRE_RESTRICT) &&
|
|
|
|
virLockManagerLockDaemonConnectionRestrict(lock, client, program, &counter) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
cleanup:
|
2011-07-06 16:30:08 +00:00
|
|
|
if (rv != 0 && fd)
|
|
|
|
VIR_FORCE_CLOSE(*fd);
|
|
|
|
virNetClientClose(client);
|
|
|
|
virObjectUnref(client);
|
|
|
|
virObjectUnref(program);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonRelease(virLockManagerPtr lock,
|
|
|
|
char **state,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virNetClientPtr client = NULL;
|
|
|
|
virNetClientProgramPtr program = NULL;
|
|
|
|
int counter = 0;
|
|
|
|
int rv = -1;
|
2013-05-03 11:00:15 +00:00
|
|
|
size_t i;
|
|
|
|
virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
|
2011-07-06 16:30:08 +00:00
|
|
|
|
2013-05-03 11:00:15 +00:00
|
|
|
virCheckFlags(0, -1);
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
if (state)
|
|
|
|
*state = NULL;
|
|
|
|
|
|
|
|
if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-05-21 08:06:00 +00:00
|
|
|
for (i = 0; i < priv->nresources; i++) {
|
2013-05-03 11:00:15 +00:00
|
|
|
virLockSpaceProtocolReleaseResourceArgs args;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2011-07-06 16:30:08 +00:00
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
|
2014-03-25 06:51:47 +00:00
|
|
|
cleanup:
|
2011-07-06 16:30:08 +00:00
|
|
|
virNetClientClose(client);
|
|
|
|
virObjectUnref(client);
|
|
|
|
virObjectUnref(program);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virLockManagerLockDaemonInquire(virLockManagerPtr lock ATTRIBUTE_UNUSED,
|
|
|
|
char **state,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (state)
|
|
|
|
*state = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
virLockDriver virLockDriverImpl =
|
|
|
|
{
|
|
|
|
.version = VIR_LOCK_MANAGER_VERSION,
|
|
|
|
.flags = 0,
|
|
|
|
|
|
|
|
.drvInit = virLockManagerLockDaemonInit,
|
|
|
|
.drvDeinit = virLockManagerLockDaemonDeinit,
|
|
|
|
|
|
|
|
.drvNew = virLockManagerLockDaemonNew,
|
|
|
|
.drvFree = virLockManagerLockDaemonFree,
|
|
|
|
|
|
|
|
.drvAddResource = virLockManagerLockDaemonAddResource,
|
|
|
|
|
|
|
|
.drvAcquire = virLockManagerLockDaemonAcquire,
|
|
|
|
.drvRelease = virLockManagerLockDaemonRelease,
|
|
|
|
|
|
|
|
.drvInquire = virLockManagerLockDaemonInquire,
|
|
|
|
};
|