Implement a node device backend using libudev

* configure.in: add new --with-udev, disabled by default, and requiring
  libudev > 145
* src/node_device/node_device_udev.c src/node_device/node_device_udev.h:
  the new node device backend
* src/node_device/node_device_linux_sysfs.c: moved node_device_hal_linux.c
  to a better file name
* src/conf/node_device_conf.c src/conf/node_device_conf.h: add a couple
  of fields in node device definitions, and an API to look them up,
  remove a couple of unused fields from previous patch.
* src/node_device/node_device_driver.c src/node_device/node_device_driver.h:
  plug the new driver
* po/POTFILES.in src/Makefile.am src/libvirt_private.syms: add the new
  files and symbols
* src/util/util.h src/util/util.c: add a new convenience macro
  virBuildPath and virBuildPathInternal() function
This commit is contained in:
David Allan 2009-11-12 22:48:24 +01:00 committed by Daniel Veillard
parent fe2af45bb2
commit 3ad6dcf3dc
15 changed files with 1711 additions and 47 deletions

View File

@ -1654,7 +1654,7 @@ test "$enable_shared" = no && lt_cv_objdir=.
LV_LIBTOOL_OBJDIR=${lt_cv_objdir-.}
AC_SUBST([LV_LIBTOOL_OBJDIR])
dnl HAL or DeviceKit library for host device enumeration
dnl HAL, DeviceKit, or libudev library for host device enumeration
HAL_REQUIRED=0.0
HAL_CFLAGS=
HAL_LIBS=
@ -1748,8 +1748,46 @@ AM_CONDITIONAL([HAVE_DEVKIT], [test "x$with_devkit" = "xyes"])
AC_SUBST([DEVKIT_CFLAGS])
AC_SUBST([DEVKIT_LIBS])
UDEV_REQUIRED=145
UDEV_CFLAGS=
UDEV_LIBS=
AC_ARG_WITH([udev],
[ --with-udev use libudev for host device enumeration],
[],
[with_udev=check])
if test "$with_libvirtd" = "no" ; then
with_udev=no
fi
if test "x$with_udev" = "xyes" -o "x$with_udev" = "xcheck"; then
PKG_CHECK_MODULES(UDEV, libudev >= $UDEV_REQUIRED,
[with_udev=yes], [
if test "x$with_udev" = "xcheck" ; then
with_udev=no
else
AC_MSG_ERROR(
[You must install libudev-devel >= $UDEV_REQUIRED to compile libvirt])
fi
])
if test "x$with_udev" = "xyes" ; then
AC_DEFINE_UNQUOTED([HAVE_UDEV], 1,
[use UDEV for host device enumeration])
old_CFLAGS=$CFLAGS
old_LDFLAGS=$LDFLAGS
CFLAGS="$CFLAGS $UDEV_CFLAGS"
LDFLAGS="$LDFLAGS $UDEV_LIBS"
AC_CHECK_FUNCS([udev_new],,[with_udev=no])
CFLAGS="$old_CFLAGS"
LDFLAGS="$old_LDFLAGS"
fi
fi
AM_CONDITIONAL([HAVE_UDEV], [test "x$with_udev" = "xyes"])
AC_SUBST([UDEV_CFLAGS])
AC_SUBST([UDEV_LIBS])
with_nodedev=no;
if test "$with_devkit" = "yes" -o "$with_hal" = "yes";
if test "$with_devkit" = "yes" -o "$with_hal" = "yes" -o "$with_udev" = "yes";
then
with_nodedev=yes
AC_DEFINE_UNQUOTED([WITH_NODE_DEVICES], 1, [with node device driver])
@ -1914,6 +1952,11 @@ AC_MSG_NOTICE([ devkit: $DEVKIT_CFLAGS $DEVKIT_LIBS])
else
AC_MSG_NOTICE([ devkit: no])
fi
if test "$with_udev" = "yes" ; then
AC_MSG_NOTICE([ udev: $UDEV_CFLAGS $UDEV_LIBS])
else
AC_MSG_NOTICE([ udev: no])
fi
if test "$with_netcf" = "yes" ; then
AC_MSG_NOTICE([ netcf: $NETCF_CFLAGS $NETCF_LIBS])
else

View File

@ -877,8 +877,7 @@ static struct qemud_server *qemudInitialize(void) {
#ifdef WITH_STORAGE_DIR
storageRegister();
#endif
#if defined(WITH_NODE_DEVICES) && \
(defined(HAVE_HAL) || defined(HAVE_DEVKIT))
#if defined(WITH_NODE_DEVICES)
nodedevRegister();
#endif
secretRegister();

View File

@ -17,7 +17,8 @@ src/lxc/lxc_controller.c
src/lxc/lxc_driver.c
src/network/bridge_driver.c
src/node_device/node_device_driver.c
src/node_device/node_device_hal_linux.c
src/node_device/node_device_linux_sysfs.c
src/node_device/node_device_udev.c
src/nodeinfo.c
src/opennebula/one_conf.c
src/opennebula/one_driver.c

View File

@ -259,16 +259,20 @@ SECURITY_DRIVER_APPARMOR_SOURCES = \
NODE_DEVICE_DRIVER_SOURCES = \
node_device/node_device_driver.c node_device/node_device_driver.h
node_device/node_device_driver.c \
node_device/node_device_driver.h \
node_device/node_device_linux_sysfs.c
NODE_DEVICE_DRIVER_HAL_SOURCES = \
node_device/node_device_hal.c \
node_device/node_device_hal.h \
node_device/node_device_hal_linux.c
node_device/node_device_hal.h
NODE_DEVICE_DRIVER_DEVKIT_SOURCES = \
node_device/node_device_devkit.c
NODE_DEVICE_DRIVER_UDEV_SOURCES = \
node_device/node_device_udev.c
#########################
#
@ -647,6 +651,11 @@ libvirt_driver_nodedev_la_SOURCES += $(NODE_DEVICE_DRIVER_DEVKIT_SOURCES)
libvirt_driver_nodedev_la_CFLAGS += $(DEVKIT_CFLAGS)
libvirt_driver_nodedev_la_LDFLAGS += $(DEVKIT_LIBS)
endif
if HAVE_UDEV
libvirt_driver_nodedev_la_SOURCES += $(NODE_DEVICE_DRIVER_UDEV_SOURCES)
libvirt_driver_nodedev_la_CFLAGS += $(UDEV_CFLAGS)
libvirt_driver_nodedev_la_LDFLAGS += $(UDEV_LIBS)
endif
if WITH_DRIVER_MODULES
libvirt_driver_nodedev_la_LDFLAGS += -module -avoid-version
@ -696,6 +705,7 @@ EXTRA_DIST += \
$(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_DEVKIT_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
$(SECURITY_DRIVER_SELINUX_SOURCES) \
$(SECURITY_DRIVER_APPARMOR_SOURCES) \
$(SECRET_DRIVER_SOURCES) \

View File

@ -91,6 +91,26 @@ int virNodeDeviceHasCap(const virNodeDeviceObjPtr dev, const char *cap)
return 0;
}
virNodeDeviceObjPtr
virNodeDeviceFindBySysfsPath(const virNodeDeviceObjListPtr devs,
const char *sysfs_path)
{
unsigned int i;
for (i = 0; i < devs->count; i++) {
virNodeDeviceObjLock(devs->objs[i]);
if ((devs->objs[i]->def->sysfs_path != NULL) &&
(STREQ(devs->objs[i]->def->sysfs_path, sysfs_path))) {
return devs->objs[i];
}
virNodeDeviceObjUnlock(devs->objs[i]);
}
return NULL;
}
virNodeDeviceObjPtr virNodeDeviceFindByName(const virNodeDeviceObjListPtr devs,
const char *name)
{
@ -117,6 +137,8 @@ void virNodeDeviceDefFree(virNodeDeviceDefPtr def)
VIR_FREE(def->name);
VIR_FREE(def->parent);
VIR_FREE(def->driver);
VIR_FREE(def->sysfs_path);
VIR_FREE(def->parent_sysfs_path);
caps = def->caps;
while (caps) {
@ -228,9 +250,17 @@ char *virNodeDeviceDefFormat(virConnectPtr conn,
virBufferAddLit(&buf, "<device>\n");
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
if (def->parent)
if (def->sysfs_path != NULL) {
virBufferEscapeString(&buf, " <sysfs_path>%s</sysfs_path>\n",
def->sysfs_path);
}
if (def->parent) {
virBufferEscapeString(&buf, " <parent>%s</parent>\n", def->parent);
}
if (def->parent_sysfs_path != NULL) {
virBufferEscapeString(&buf, " <parent_sysfs_path>%s</parent_sysfs_path>\n",
def->parent_sysfs_path);
}
if (def->driver) {
virBufferAddLit(&buf, " <driver>\n");
virBufferEscapeString(&buf, " <name>%s</name>\n", def->driver);
@ -248,12 +278,6 @@ char *virNodeDeviceDefFormat(virConnectPtr conn,
if (data->system.product_name)
virBufferEscapeString(&buf, " <product>%s</product>\n",
data->system.product_name);
if (data->system.dmi_devpath)
virBufferEscapeString(&buf, " <dmi_devpath>%s</dmi_devpath>\n",
data->system.dmi_devpath);
if (data->system.description)
virBufferEscapeString(&buf, " <description>%s</description>\n",
data->system.description);
virBufferAddLit(&buf, " <hardware>\n");
if (data->system.hardware.vendor_name)
virBufferEscapeString(&buf, " <vendor>%s</vendor>\n",
@ -331,9 +355,6 @@ char *virNodeDeviceDefFormat(virConnectPtr conn,
data->usb_if.subclass);
virBufferVSprintf(&buf, " <protocol>%d</protocol>\n",
data->usb_if.protocol);
if (data->usb_if.interface_name)
virBufferVSprintf(&buf, " <interface_name>%s</interface_name>\n",
data->usb_if.interface_name);
if (data->usb_if.description)
virBufferVSprintf(&buf, " <description>%s</description>\n",
data->usb_if.description);
@ -1340,8 +1361,6 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
switch (caps->type) {
case VIR_NODE_DEV_CAP_SYSTEM:
VIR_FREE(data->system.product_name);
VIR_FREE(data->system.dmi_devpath);
VIR_FREE(data->system.description);
VIR_FREE(data->system.hardware.vendor_name);
VIR_FREE(data->system.hardware.version);
VIR_FREE(data->system.hardware.serial);
@ -1358,7 +1377,6 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
VIR_FREE(data->usb_dev.vendor_name);
break;
case VIR_NODE_DEV_CAP_USB_INTERFACE:
VIR_FREE(data->usb_if.interface_name);
VIR_FREE(data->usb_if.description);
break;
case VIR_NODE_DEV_CAP_NET:

View File

@ -82,8 +82,6 @@ struct _virNodeDevCapsDef {
union _virNodeDevCapData {
struct {
char *product_name;
char *description;
char *dmi_devpath;
struct {
char *vendor_name;
char *version;
@ -120,7 +118,6 @@ struct _virNodeDevCapsDef {
unsigned _class; /* "class" is reserved in C */
unsigned subclass;
unsigned protocol;
char *interface_name;
char *description;
} usb_if;
struct {
@ -164,7 +161,9 @@ typedef struct _virNodeDeviceDef virNodeDeviceDef;
typedef virNodeDeviceDef *virNodeDeviceDefPtr;
struct _virNodeDeviceDef {
char *name; /* device name (unique on node) */
char *sysfs_path; /* udev name/sysfs path */
char *parent; /* optional parent device name */
char *parent_sysfs_path; /* udev parent name/sysfs path */
char *driver; /* optional driver name */
virNodeDevCapsDefPtr caps; /* optional device capabilities */
};
@ -206,6 +205,9 @@ int virNodeDeviceHasCap(const virNodeDeviceObjPtr dev, const char *cap);
virNodeDeviceObjPtr virNodeDeviceFindByName(const virNodeDeviceObjListPtr devs,
const char *name);
virNodeDeviceObjPtr
virNodeDeviceFindBySysfsPath(const virNodeDeviceObjListPtr devs,
const char *sysfs_path);
virNodeDeviceObjPtr virNodeDeviceAssignDef(virConnectPtr conn,
virNodeDeviceObjListPtr devs,

View File

@ -341,6 +341,7 @@ virNodeDeviceHasCap;
virNodeDeviceObjRemove;
virNodeDevCapTypeToString;
virNodeDeviceFindByName;
virNodeDeviceFindBySysfsPath;
virNodeDeviceObjListFree;
virNodeDeviceDefFree;
virNodeDevCapsDefFree;

View File

@ -70,7 +70,10 @@ static int update_caps(virNodeDeviceObjPtr dev)
}
#ifdef __linux__
#if defined (__linux__) && defined (HAVE_HAL)
/* Under libudev changes to the driver name should be picked up as
* "change" events, so we don't call update driver name unless we're
* using the HAL backend. */
static int update_driver_name(virConnectPtr conn,
virNodeDeviceObjPtr dev)
{
@ -658,10 +661,10 @@ void registerCommonNodeFuncs(virDeviceMonitorPtr driver)
int nodedevRegister(void) {
#if defined(HAVE_HAL) && defined(HAVE_DEVKIT)
#if defined(HAVE_HAL) && defined(HAVE_UDEV)
/* Register only one of these two - they conflict */
if (halNodeRegister() == -1)
return devkitNodeRegister();
return udevNodeRegister();
return 0;
#else
#ifdef HAVE_HAL
@ -670,5 +673,8 @@ int nodedevRegister(void) {
#ifdef HAVE_DEVKIT
return devkitNodeRegister();
#endif
#ifdef HAVE_UDEV
return udevNodeRegister();
#endif
#endif
}

View File

@ -45,6 +45,9 @@ int halNodeRegister(void);
#ifdef HAVE_DEVKIT
int devkitNodeRegister(void);
#endif
#ifdef HAVE_UDEV
int udevNodeRegister(void);
#endif
void nodeDeviceLock(virDeviceMonitorStatePtr driver);
void nodeDeviceUnlock(virDeviceMonitorStatePtr driver);
@ -53,4 +56,23 @@ void registerCommonNodeFuncs(virDeviceMonitorPtr mon);
int nodedevRegister(void);
#ifdef __linux__
#define check_fc_host(d) check_fc_host_linux(d)
int check_fc_host_linux(union _virNodeDevCapData *d);
#define check_vport_capable(d) check_vport_capable_linux(d)
int check_vport_capable_linux(union _virNodeDevCapData *d);
#define read_wwn(host, file, wwn) read_wwn_linux(host, file, wwn)
int read_wwn_linux(int host, const char *file, char **wwn);
#else /* __linux__ */
#define check_fc_host(d)
#define check_vport_capable(d)
#define read_wwn(host, file, wwn)
#endif /* __linux__ */
#endif /* __VIR_NODE_DEVICE_H__ */

View File

@ -22,23 +22,4 @@
#ifndef __VIR_NODE_DEVICE_HAL_H__
#define __VIR_NODE_DEVICE_HAL_H__
#ifdef __linux__
#define check_fc_host(d) check_fc_host_linux(d)
int check_fc_host_linux(union _virNodeDevCapData *d);
#define check_vport_capable(d) check_vport_capable_linux(d)
int check_vport_capable_linux(union _virNodeDevCapData *d);
#define read_wwn(host, file, wwn) read_wwn_linux(host, file, wwn)
int read_wwn_linux(int host, const char *file, char **wwn);
#else /* __linux__ */
#define check_fc_host(d)
#define check_vport_capable(d)
#define read_wwn(host, file, wwn)
#endif /* __linux__ */
#endif /* __VIR_NODE_DEVICE_HAL_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
/*
* node_device_udev.h: node device enumeration - libudev implementation
*
* Copyright (C) 2009 Red Hat
*
* 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
*
* Author: Dave Allan <dallan@redhat.com>
*/
#include <libudev.h>
#include <stdint.h>
#define SYSFS_DATA_SIZE 4096
#define DRV_STATE_UDEV_MONITOR(ds) ((struct udev_monitor *)((ds)->privateData))
#define DMI_DEVPATH "/sys/devices/virtual/dmi/id"
#define PROPERTY_FOUND 0
#define PROPERTY_MISSING 1
#define PROPERTY_ERROR -1

View File

@ -2128,3 +2128,31 @@ void virFileWaitForDevices(virConnectPtr conn)
void virFileWaitForDevices(virConnectPtr conn ATTRIBUTE_UNUSED) {}
#endif
#endif
int virBuildPathInternal(char **path, ...)
{
char *path_component = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
va_list ap;
int ret = 0;
va_start(ap, *path);
path_component = va_arg(ap, char *);
virBufferAdd(&buf, path_component, -1);
while ((path_component = va_arg(ap, char *)) != NULL)
{
virBufferAddChar(&buf, '/');
virBufferAdd(&buf, path_component, -1);
}
va_end(ap);
*path = virBufferContentAndReset(&buf);
if (*path == NULL) {
ret = -1;
}
return ret;
}

View File

@ -248,4 +248,7 @@ char *virFileFindMountPoint(const char *type);
void virFileWaitForDevices(virConnectPtr conn);
#define virBuildPath(path, ...) virBuildPathInternal(path, __VA_ARGS__, NULL)
int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
#endif /* __VIR_UTIL_H__ */