mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
interface: acquire a pidfile in the driver root directory
When we allow multiple instances of the driver for the same user account, using a separate root directory, we need to ensure mutual exclusion. Use a pidfile to guarantee this. In privileged libvirtd this ends up locking /var/run/libvirt/interface/driver.pid In unprivileged libvirtd this ends up locking /run/user/$UID/libvirt/interface/run/driver.pid NB, the latter can vary depending on $XDG_RUNTIME_DIR Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
3e846a1621
commit
09d37f9d65
@ -29,10 +29,14 @@
|
|||||||
#include "interface_conf.h"
|
#include "interface_conf.h"
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
#include "virlog.h"
|
#include "virlog.h"
|
||||||
|
#include "virfile.h"
|
||||||
|
#include "virpidfile.h"
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "viraccessapicheck.h"
|
#include "viraccessapicheck.h"
|
||||||
#include "virinterfaceobj.h"
|
#include "virinterfaceobj.h"
|
||||||
|
|
||||||
|
#include "configmake.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_INTERFACE
|
#define VIR_FROM_THIS VIR_FROM_INTERFACE
|
||||||
|
|
||||||
VIR_LOG_INIT("interface.interface_backend_netcf");
|
VIR_LOG_INIT("interface.interface_backend_netcf");
|
||||||
@ -43,6 +47,10 @@ VIR_LOG_INIT("interface.interface_backend_netcf");
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
virObjectLockable parent;
|
virObjectLockable parent;
|
||||||
|
/* pid file FD, ensures two copies of the driver can't use the same root */
|
||||||
|
int lockFD;
|
||||||
|
|
||||||
|
char *stateDir;
|
||||||
struct netcf *netcf;
|
struct netcf *netcf;
|
||||||
bool privileged;
|
bool privileged;
|
||||||
} virNetcfDriverState, *virNetcfDriverStatePtr;
|
} virNetcfDriverState, *virNetcfDriverStatePtr;
|
||||||
@ -71,6 +79,11 @@ virNetcfDriverStateDispose(void *obj)
|
|||||||
|
|
||||||
if (_driver->netcf)
|
if (_driver->netcf)
|
||||||
ncf_close(_driver->netcf);
|
ncf_close(_driver->netcf);
|
||||||
|
|
||||||
|
if (_driver->lockFD != -1)
|
||||||
|
virPidFileRelease(_driver->stateDir, "driver", _driver->lockFD);
|
||||||
|
|
||||||
|
VIR_FREE(_driver->stateDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,15 +100,41 @@ netcfStateInitialize(bool privileged,
|
|||||||
|
|
||||||
driver->privileged = privileged;
|
driver->privileged = privileged;
|
||||||
|
|
||||||
|
if (privileged) {
|
||||||
|
if (virAsprintf(&driver->stateDir,
|
||||||
|
"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
VIR_AUTOFREE(char *) rundir = NULL;
|
||||||
|
|
||||||
|
if (!(rundir = virGetUserRuntimeDirectory()))
|
||||||
|
goto error;
|
||||||
|
if (virAsprintf(&driver->stateDir, "%s/nodedev/run", rundir) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
|
||||||
|
virReportSystemError(errno, _("cannot create state directory '%s'"),
|
||||||
|
driver->stateDir);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((driver->lockFD =
|
||||||
|
virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* open netcf */
|
/* open netcf */
|
||||||
if (ncf_init(&driver->netcf, NULL) != 0) {
|
if (ncf_init(&driver->netcf, NULL) != 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("failed to initialize netcf"));
|
_("failed to initialize netcf"));
|
||||||
virObjectUnref(driver);
|
goto error;
|
||||||
driver = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virObjectUnref(driver);
|
||||||
|
driver = NULL;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,14 +32,21 @@
|
|||||||
#include "interface_conf.h"
|
#include "interface_conf.h"
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
|
#include "virpidfile.h"
|
||||||
#include "viraccessapicheck.h"
|
#include "viraccessapicheck.h"
|
||||||
#include "virinterfaceobj.h"
|
#include "virinterfaceobj.h"
|
||||||
#include "virnetdev.h"
|
#include "virnetdev.h"
|
||||||
|
|
||||||
|
#include "configmake.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_INTERFACE
|
#define VIR_FROM_THIS VIR_FROM_INTERFACE
|
||||||
|
|
||||||
struct udev_iface_driver {
|
struct udev_iface_driver {
|
||||||
struct udev *udev;
|
struct udev *udev;
|
||||||
|
/* pid file FD, ensures two copies of the driver can't use the same root */
|
||||||
|
int lockFD;
|
||||||
|
|
||||||
|
char *stateDir;
|
||||||
bool privileged;
|
bool privileged;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1157,6 +1164,9 @@ udevInterfaceIsActive(virInterfacePtr ifinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
udevStateCleanup(void);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
udevStateInitialize(bool privileged,
|
udevStateInitialize(bool privileged,
|
||||||
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
|
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
|
||||||
@ -1167,6 +1177,31 @@ udevStateInitialize(bool privileged,
|
|||||||
if (VIR_ALLOC(driver) < 0)
|
if (VIR_ALLOC(driver) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
driver->lockFD = -1;
|
||||||
|
|
||||||
|
if (privileged) {
|
||||||
|
if (virAsprintf(&driver->stateDir,
|
||||||
|
"%s/run/libvirt/nodedev", LOCALSTATEDIR) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
VIR_AUTOFREE(char *) rundir = NULL;
|
||||||
|
|
||||||
|
if (!(rundir = virGetUserRuntimeDirectory()))
|
||||||
|
goto cleanup;
|
||||||
|
if (virAsprintf(&driver->stateDir, "%s/nodedev/run", rundir) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
|
||||||
|
virReportSystemError(errno, _("cannot create state directory '%s'"),
|
||||||
|
driver->stateDir);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((driver->lockFD =
|
||||||
|
virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
driver->udev = udev_new();
|
driver->udev = udev_new();
|
||||||
if (!driver->udev) {
|
if (!driver->udev) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
@ -1178,6 +1213,8 @@ udevStateInitialize(bool privileged,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
if (ret < 0)
|
||||||
|
udevStateCleanup();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,8 +1224,13 @@ udevStateCleanup(void)
|
|||||||
if (!driver)
|
if (!driver)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
udev_unref(driver->udev);
|
if (driver->udev)
|
||||||
|
udev_unref(driver->udev);
|
||||||
|
|
||||||
|
if (driver->lockFD != -1)
|
||||||
|
virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
|
||||||
|
|
||||||
|
VIR_FREE(driver->stateDir);
|
||||||
VIR_FREE(driver);
|
VIR_FREE(driver);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user