提交 09d37f9d 编写于 作者: D Daniel P. Berrangé

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: NDaniel P. Berrangé <berrange@redhat.com>
上级 3e846a16
...@@ -29,10 +29,14 @@ ...@@ -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"); ...@@ -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) ...@@ -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, ...@@ -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"));
goto error;
}
return 0;
error:
virObjectUnref(driver); virObjectUnref(driver);
driver = NULL; driver = NULL;
return -1; return -1;
}
return 0;
} }
......
...@@ -32,14 +32,21 @@ ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -1187,8 +1224,13 @@ udevStateCleanup(void)
if (!driver) if (!driver)
return -1; return -1;
if (driver->udev)
udev_unref(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;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册