[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] udev node device backend



Attached is a fully functional version of the node device udev based backend, incorporating all the feedback from earlier revisions. I broke the new capability fields out into a separate patch per Dan's suggestion, and I have also included a patch removing the DevKit backend.

Dave
>From e95f0c84ff50c4d8736750e93b70b901c7a246ad Mon Sep 17 00:00:00 2001
From: David Allan <dallan redhat com>
Date: Fri, 16 Oct 2009 16:52:40 -0400
Subject: [PATCH 1/3] Add several fields to node device capabilities

---
 src/conf/node_device_conf.c |   22 ++++++++++++++++++++++
 src/conf/node_device_conf.h |    7 +++++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index c2c5a44..87f441d 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -248,6 +248,12 @@ 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",
@@ -325,6 +331,9 @@ 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);
@@ -394,10 +403,20 @@ char *virNodeDeviceDefFormat(virConnectPtr conn,
                                   "</media_available>\n", avl ? 1 : 0);
                 virBufferVSprintf(&buf, "      <media_size>%llu</media_size>\n",
                                   data->storage.removable_media_size);
+                virBufferVSprintf(&buf, "      <logical_block_size>%llu"
+                                  "</logical_block_size>\n",
+                                  data->storage.logical_block_size);
+                virBufferVSprintf(&buf, "      <num_blocks>%llu</num_blocks>\n",
+                                  data->storage.num_blocks);
                 virBufferAddLit(&buf, "    </capability>\n");
             } else {
                 virBufferVSprintf(&buf, "    <size>%llu</size>\n",
                                   data->storage.size);
+                virBufferVSprintf(&buf, "    <logical_block_size>%llu"
+                                  "</logical_block_size>\n",
+                                  data->storage.logical_block_size);
+                virBufferVSprintf(&buf, "    <num_blocks>%llu</num_blocks>\n",
+                                  data->storage.num_blocks);
             }
             if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE)
                 virBufferAddLit(&buf,
@@ -1310,6 +1329,8 @@ 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);
@@ -1326,6 +1347,7 @@ 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:
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index a7bb6c6..f70184d 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -82,6 +82,8 @@ struct _virNodeDevCapsDef {
     union _virNodeDevCapData {
         struct {
             char *product_name;
+            char *description;
+            char *dmi_devpath;
             struct {
                 char *vendor_name;
                 char *version;
@@ -101,6 +103,7 @@ struct _virNodeDevCapsDef {
             unsigned function;
             unsigned product;
             unsigned vendor;
+            unsigned class;
             char *product_name;
             char *vendor_name;
         } pci_dev;
@@ -117,10 +120,12 @@ struct _virNodeDevCapsDef {
             unsigned _class;		/* "class" is reserved in C */
             unsigned subclass;
             unsigned protocol;
+            char *interface_name;
             char *description;
         } usb_if;
         struct {
             char *address;
+            unsigned address_len;
             char *ifname;
             enum virNodeDevNetCapType subtype;  /* LAST -> no subtype */
         } net;
@@ -139,6 +144,8 @@ struct _virNodeDevCapsDef {
         } scsi;
         struct {
             unsigned long long size;
+            unsigned long long num_blocks;
+            unsigned long long logical_block_size;
             unsigned long long removable_media_size;
             char *block;
             char *bus;
-- 
1.6.4.4

>From d8f4ac6806a8f55e4f9fa9c4af3e0c89aa4d0074 Mon Sep 17 00:00:00 2001
From: David Allan <dallan redhat com>
Date: Fri, 16 Oct 2009 10:09:01 -0400
Subject: [PATCH 2/3] Implement a node device backend using libudev.

Monitoring for addition and removal of devices is implemented.

There is a lot of detail work in this code, so we should try to get people running it on a wide variety of hardware so we can shake out the differences in implementation between the HAL and libudev backends.

I have moved the new fields in the node device capabilities to a separate patch.

This version contains changes per all the feedback I've received on earlier versions.
---
 configure.in                                       |   47 +-
 daemon/libvirtd.c                                  |    3 +-
 po/POTFILES.in                                     |    3 +-
 src/Makefile.am                                    |   16 +-
 src/node_device/node_device_driver.c               |   12 +-
 src/node_device/node_device_driver.h               |   22 +
 src/node_device/node_device_hal.h                  |   19 -
 ...evice_hal_linux.c => node_device_linux_sysfs.c} |    0
 src/node_device/node_device_udev.c                 | 1142 ++++++++++++++++++++
 src/node_device/node_device_udev.h                 |   32 +
 src/util/util.c                                    |   28 +
 src/util/util.h                                    |    3 +
 tools/virsh.c                                      |   10 +-
 13 files changed, 1306 insertions(+), 31 deletions(-)
 rename src/node_device/{node_device_hal_linux.c => node_device_linux_sysfs.c} (100%)
 create mode 100644 src/node_device/node_device_udev.c
 create mode 100644 src/node_device/node_device_udev.h

diff --git a/configure.in b/configure.in
index 2f9db72..25ed55f 100644
--- a/configure.in
+++ b/configure.in
@@ -1640,7 +1640,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=
@@ -1734,8 +1734,46 @@ AM_CONDITIONAL([HAVE_DEVKIT], [test "x$with_devkit" = "xyes"])
 AC_SUBST([DEVKIT_CFLAGS])
 AC_SUBST([DEVKIT_LIBS])

+UDEV_REQUIRED=143
+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 udev-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])
@@ -1900,6 +1938,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
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 02bd287..d8d6c00 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -833,8 +833,7 @@ static struct qemud_server *qemudInitialize(int sigread) {
 #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();
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1a12a39..4561e55 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -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
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e27ea7..11da07b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -254,16 +254,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
+

 #########################
 #
@@ -642,6 +646,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
@@ -691,6 +700,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)			\
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index f33ff48..c139907 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -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
 }
diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
index db01624..5be0781 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -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__ */
diff --git a/src/node_device/node_device_hal.h b/src/node_device/node_device_hal.h
index c859fe3..8ac8a35 100644
--- a/src/node_device/node_device_hal.h
+++ b/src/node_device/node_device_hal.h
@@ -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__ */
diff --git a/src/node_device/node_device_hal_linux.c b/src/node_device/node_device_linux_sysfs.c
similarity index 100%
rename from src/node_device/node_device_hal_linux.c
rename to src/node_device/node_device_linux_sysfs.c
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
new file mode 100644
index 0000000..10f45aa
--- /dev/null
+++ b/src/node_device/node_device_udev.c
@@ -0,0 +1,1142 @@
+/*
+ * node_device_udev.c: 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 <config.h>
+#include <libudev.h>
+
+#include "node_device_udev.h"
+#include "virterror_internal.h"
+#include "node_device_conf.h"
+#include "node_device_driver.h"
+#include "driver.h"
+#include "datatypes.h"
+#include "logging.h"
+#include "memory.h"
+#include "uuid.h"
+#include "util.h"
+#include "buf.h"
+#include "daemon/event.h"
+
+#define VIR_FROM_THIS VIR_FROM_NODEDEV
+
+static virDeviceMonitorStatePtr driverState = NULL;
+
+/* This function allocates memory from the heap for the property
+ * value.  That memory must be later freed by some other code. */
+static int udevGetDeviceProperty(struct udev_device *udev_device,
+                                 const char *property_key,
+                                 char **property_value)
+{
+    const char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    udev_value = udev_device_get_property_value(udev_device, property_key);
+    if (udev_value == NULL) {
+        VIR_INFO(_("udev reports device '%s' does not have property '%s'"),
+                 udev_device_get_sysname(udev_device), property_key);
+        ret = PROPERTY_MISSING;
+        goto out;
+    }
+
+    /* If this allocation is changed, the comment at the beginning
+     * of the function must also be changed. */
+    *property_value = strdup(udev_value);
+    if (*property_value == NULL) {
+        VIR_ERROR(_("Failed to allocate memory for "
+                    "property '%s' on device '%s'"),
+                  property_key, udev_device_get_sysname(udev_device));
+        virReportOOMError(NULL);
+        ret = PROPERTY_ERROR;
+    }
+
+out:
+    return ret;
+}
+
+
+static int udevGetStringProperty(struct udev_device *udev_device,
+                                 const char *property_key,
+                                 char **value)
+{
+    return udevGetDeviceProperty(udev_device, property_key, value);
+}
+
+
+static int udevGetIntProperty(struct udev_device *udev_device,
+                              const char *property_key,
+                              int *value,
+                              int base)
+{
+    char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    ret = udevGetDeviceProperty(udev_device, property_key, &udev_value);
+
+    if (ret == PROPERTY_FOUND) {
+        if (virStrToLong_i(udev_value, NULL, base, value) != 0) {
+            ret = PROPERTY_ERROR;
+        }
+    }
+
+    VIR_FREE(udev_value);
+    return ret;
+}
+
+
+static int udevGetUintProperty(struct udev_device *udev_device,
+                               const char *property_key,
+                               unsigned int *value,
+                               int base)
+{
+    char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    ret = udevGetDeviceProperty(udev_device, property_key, &udev_value);
+
+    if (ret == PROPERTY_FOUND) {
+        if (virStrToLong_ui(udev_value, NULL, base, value) != 0) {
+            ret = PROPERTY_ERROR;
+        }
+    }
+
+    VIR_FREE(udev_value);
+    return ret;
+}
+
+
+/* This function allocates memory from the heap for the attr value.
+ * That memory must be later freed by some other code.   */
+static int udevGetStringSysfsAttr(struct udev_device *udev_device,
+                                  const char *attr_name,
+                                  char **value)
+{
+    const char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    udev_value = udev_device_get_sysattr_value(udev_device, attr_name);
+
+    if (udev_value != NULL) {
+        *value = strdup(udev_value);
+        if (*value == NULL) {
+            VIR_ERROR(_("Failed to allocate memory for "
+                        "attribute '%s' on device '%s'"),
+                      attr_name, udev_device_get_sysname(udev_device));
+            virReportOOMError(NULL);
+            ret = PROPERTY_ERROR;
+        }
+    } else {
+        ret = PROPERTY_MISSING;
+    }
+
+    return ret;
+}
+
+
+static int udevGetIntSysfsAttr(struct udev_device *udev_device,
+                               const char *attr_name,
+                               int *value,
+                               int base)
+{
+    const char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    udev_value = udev_device_get_sysattr_value(udev_device, attr_name);
+
+    if (udev_value != NULL) {
+        if (virStrToLong_i(udev_value, NULL, base, value) != 0) {
+            ret = PROPERTY_ERROR;
+        }
+    } else {
+        ret = PROPERTY_MISSING;
+    }
+
+    return ret;
+}
+
+
+static int udevGetUintSysfsAttr(struct udev_device *udev_device,
+                                const char *attr_name,
+                                unsigned int *value,
+                                int base)
+{
+    const char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    udev_value = udev_device_get_sysattr_value(udev_device, attr_name);
+
+    if (udev_value != NULL) {
+        if (virStrToLong_ui(udev_value, NULL, base, value) != 0) {
+            ret = PROPERTY_ERROR;
+        }
+    } else {
+        ret = PROPERTY_MISSING;
+    }
+
+    return ret;
+}
+
+
+static int udevGetUint64SysfsAttr(struct udev_device *udev_device,
+                                  const char *attr_name,
+                                  uint64_t *value)
+{
+    const char *udev_value = NULL;
+    int ret = PROPERTY_FOUND;
+
+    udev_value = udev_device_get_sysattr_value(udev_device, attr_name);
+
+    if (udev_value != NULL) {
+        if (virStrToLong_ull(udev_value, NULL, 0, value) != 0) {
+            ret = PROPERTY_ERROR;
+        }
+    } else {
+        ret = PROPERTY_MISSING;
+    }
+
+    return ret;
+}
+
+
+static void udevLogFunction(struct udev *udev ATTRIBUTE_UNUSED,
+                            int priority ATTRIBUTE_UNUSED,
+                            const char *file,
+                            int line,
+                            const char *fn,
+                            const char *fmt,
+                            va_list args)
+{
+    VIR_ERROR_INT(file, fn, line, fmt, args);
+}
+
+
+static int udevProcessPCI(struct udev_device *device,
+                          virNodeDeviceDefPtr def)
+{
+    const char *devpath = NULL;
+    union _virNodeDevCapData *data = &def->caps->data;
+    int ret = -1;
+
+    devpath = udev_device_get_devpath(device);
+
+    char *p = strrchr(devpath, '/');
+
+    if ((p == NULL) || (virStrToLong_ui(p+1,
+                                        &p,
+                                        16,
+                                        &data->pci_dev.domain) == -1)) {
+        goto out;
+    }
+
+    if ((p == NULL) || (virStrToLong_ui(p+1,
+                                        &p,
+                                        16,
+                                        &data->pci_dev.bus) == -1)) {
+        goto out;
+    }
+
+    if ((p == NULL) || (virStrToLong_ui(p+1,
+                                        &p,
+                                        16,
+                                        &data->pci_dev.slot) == -1)) {
+        goto out;
+    }
+
+    if ((p == NULL) || (virStrToLong_ui(p+1,
+                                        &p,
+                                        16,
+                                        &data->pci_dev.function) == -1)) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device,
+                             "vendor",
+                             &data->pci_dev.vendor,
+                             0) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device, "product", &data->pci_dev.product, 0)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    /* FIXME: to do the vendor name and product name, we have to
+     * parse /usr/share/hwdata/pci.ids.  Look in hal/hald/ids.c
+     */
+
+    ret = 0;
+
+out:
+    return ret;
+}
+
+
+static int udevProcessUSBDevice(struct udev_device *device,
+                                virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = &def->caps->data;
+    int ret = 0;
+
+    if (udevGetUintProperty(device,
+                            "BUSNUM",
+                            &data->usb_dev.bus,
+                            0) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintProperty(device,
+                            "DEVNUM",
+                            &data->usb_dev.device,
+                            0) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintProperty(device,
+                            "ID_VENDOR_ID",
+                            &data->usb_dev.vendor,
+                            16) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetStringProperty(device,
+                              "ID_VENDOR",
+                              &data->usb_dev.vendor_name) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintProperty(device,
+                            "ID_MODEL_ID",
+                            &data->usb_dev.product,
+                            0) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetStringProperty(device,
+                              "ID_MODEL",
+                              &data->usb_dev.product_name) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+
+/* XXX Is 10 the correct base for the Number/Class/SubClass/Protocol
+ * conversions?  */
+static int udevProcessUSBInterface(struct udev_device *device,
+                                   virNodeDeviceDefPtr def)
+{
+    int ret = 0;
+    union _virNodeDevCapData *data = &def->caps->data;
+
+    if (udevGetStringProperty(device,
+                              "INTERFACE",
+                              &data->usb_if.interface_name) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device,
+                             "bInterfaceNumber",
+                             &data->usb_if.number,
+                             10) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device,
+                             "bInterfaceClass",
+                             &data->usb_if._class,
+                             10) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device,
+                             "bInterfaceSubClass",
+                             &data->usb_if.subclass,
+                             10) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUintSysfsAttr(device,
+                             "bInterfaceProtocol",
+                             &data->usb_if.protocol,
+                             10) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    ret = 0;
+
+out:
+    return ret;
+}
+
+
+static int udevProcessNetworkInterface(struct udev_device *device,
+                                       virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = &def->caps->data;
+    int ret = 0;
+
+    if (udevGetStringSysfsAttr(device,
+                               "address",
+                               &data->net.address) == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetUintSysfsAttr(device,
+                             "addr_len",
+                             &data->net.address_len,
+                             0) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+
+static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
+                               virNodeDeviceDefPtr def)
+{
+    int ret = 0;
+    union _virNodeDevCapData *data = &def->caps->data;
+    char *filename = NULL;
+
+    filename = basename(def->name);
+
+    if (STRPREFIX(filename, "host")) {
+        /* XXX There's really no better way to get the host #? */
+        ret = virStrToLong_ui(filename + strlen("host"),
+                              NULL,
+                              0,
+                              &data->scsi_host.host);
+        check_fc_host(&def->caps->data);
+        check_vport_capable(&def->caps->data);
+    }
+
+    return ret;
+}
+
+
+static int udevProcessSCSIDevice(struct udev_device *device ATTRIBUTE_UNUSED,
+                                 virNodeDeviceDefPtr def)
+{
+    int ret = 0;
+    union _virNodeDevCapData *data = &def->caps->data;
+    char *filename = NULL, *p = NULL;
+
+    filename = basename(def->name);
+
+    virStrToLong_ui(filename, &p, 10, &data->scsi.host);
+    virStrToLong_ui(p+1, &p, 10, &data->scsi.bus);
+    virStrToLong_ui(p+1, &p, 10, &data->scsi.target);
+    virStrToLong_ui(p+1, &p, 10, &data->scsi.lun);
+
+    return ret;
+}
+
+
+static int udevProcessDisk(struct udev_device *device,
+                           virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = &def->caps->data;
+    int ret = 0;
+
+    data->storage.drive_type = strdup("disk");
+    if (data->storage.drive_type == NULL) {
+        ret = -1;
+        goto out;
+    }
+
+    if (udevGetUint64SysfsAttr(device,
+                               "size",
+                               &data->storage.num_blocks) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetUint64SysfsAttr(device,
+                               "queue/logical_block_size",
+                               &data->storage.logical_block_size)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+
+
+    data->storage.size = data->storage.num_blocks *
+        data->storage.logical_block_size;
+
+out:
+    return ret;
+}
+
+
+static int udevProcessCDROM(struct udev_device *device,
+                            virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = &def->caps->data;
+    int tmp_int = 0, ret = 0;
+
+    if ((udevGetIntSysfsAttr(device, "removable", &tmp_int, 0) == PROPERTY_FOUND) &&
+        (tmp_int == 1)) {
+        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;
+    }
+
+    if ((udevGetIntProperty(device, "ID_CDROM_MEDIA", &tmp_int, 0)
+         == PROPERTY_FOUND) && (tmp_int == 1)) {
+
+        def->caps->data.storage.flags |=
+            VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
+
+        if (udevGetUint64SysfsAttr(device,
+                                   "size",
+                                   &data->storage.num_blocks) == PROPERTY_ERROR) {
+            goto out;
+        }
+
+        if (udevGetUint64SysfsAttr(device,
+                                   "queue/logical_block_size",
+                                   &data->storage.logical_block_size) == PROPERTY_ERROR) {
+            goto out;
+        }
+
+        /* XXX This calculation is wrong for the qemu virtual cdrom
+         * which reports the size in 512 byte blocks, but the logical
+         * block size as 2048.  I don't have a physical cdrom on a
+         * devel system to see how they behave. */
+        def->caps->data.storage.removable_media_size =
+            def->caps->data.storage.num_blocks *
+            def->caps->data.storage.logical_block_size;
+    }
+
+out:
+    return ret;
+}
+
+
+/* This function exists to deal with the case in which a driver does
+ * not provide a device type in the usual place, but udev told us it's
+ * a storage device, and we can make a good guess at what kind of
+ * storage device it is from other information that is provided. */
+static int udevKludgeStorageType(virNodeDeviceDefPtr def)
+{
+    int ret = -1;
+
+    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd")) {
+        /* virtio disk */
+        def->caps->data.storage.drive_type = strdup("disk");
+        if (def->caps->data.storage.drive_type != NULL) {
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
+
+static void udevStripSpaces(char *s)
+{
+    if (s == NULL) {
+        return;
+    }
+
+    while (virFileStripSuffix(s, " ")) {
+        /* do nothing */
+        ;
+    }
+
+    return;
+}
+
+
+static int udevProcessStorage(struct udev_device *device,
+                              virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = &def->caps->data;
+    int ret = -1;
+
+    data->storage.block = strdup(udev_device_get_devnode(device));
+    if (udevGetStringProperty(device,
+                              "DEVNAME",
+                              &data->storage.block) == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringProperty(device,
+                              "ID_BUS",
+                              &data->storage.bus) == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringProperty(device,
+                              "ID_SERIAL",
+                              &data->storage.serial) == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "device/vendor",
+                               &data->storage.vendor) == PROPERTY_ERROR) {
+        goto out;
+    }
+    udevStripSpaces(def->caps->data.storage.vendor);
+    if (udevGetStringSysfsAttr(device,
+                               "device/model",
+                               &data->storage.model) == PROPERTY_ERROR) {
+        goto out;
+    }
+    udevStripSpaces(def->caps->data.storage.model);
+    /* There is no equivalent of the hotpluggable property in libudev,
+     * but storage is going toward a world in which hotpluggable is
+     * expected, so I don't see a problem with not having a property
+     * for it. */
+
+    if (udevGetStringProperty(device,
+                              "ID_TYPE",
+                              &data->storage.drive_type) != 0) {
+        /* If udev doesn't have it, perhaps we can guess it. */
+        if (udevKludgeStorageType(def) != 0) {
+            goto out;
+        }
+    }
+
+    /* NB: drive_type has changed from HAL; now it's "cd" instead of "cdrom" */
+    if (STREQ(def->caps->data.storage.drive_type, "cd")) {
+        ret = udevProcessCDROM(device, def);
+    } else if (STREQ(def->caps->data.storage.drive_type, "disk")) {
+        ret = udevProcessDisk(device, def);
+    } else {
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+
+static int udevSetDeviceType(struct udev_device *device,
+                             virNodeDeviceDefPtr def)
+{
+    union _virNodeDevCapData *data = NULL;
+    const char *devtype = NULL;
+    int ret = 0;
+
+    if (VIR_ALLOC(def->caps) != 0) {
+        ret = -1;
+        goto out;
+    }
+
+    data = &def->caps->data;
+
+    devtype = udev_device_get_devtype(device);
+
+    if (udevGetUintProperty(device,
+                            "PCI_CLASS",
+                            &data->pci_dev.class,
+                            0) == PROPERTY_FOUND) {
+        def->caps->type = VIR_NODE_DEV_CAP_PCI_DEV;
+        goto out;
+    }
+
+    if (devtype != NULL && STREQ(devtype, "usb_device")) {
+        def->caps->type = VIR_NODE_DEV_CAP_USB_DEV;
+        goto out;
+    }
+
+    if (devtype != NULL && STREQ(devtype, "usb_interface")) {
+        def->caps->type = VIR_NODE_DEV_CAP_USB_INTERFACE;
+        goto out;
+    }
+
+    /* XXX Do some network interfaces set the device type property? */
+    if (udevGetStringProperty(device,
+                              "INTERFACE",
+                              &data->net.ifname) == PROPERTY_FOUND) {
+        def->caps->type = VIR_NODE_DEV_CAP_NET;
+        goto out;
+    }
+
+    if (devtype != NULL && STREQ(devtype, "scsi_host")) {
+        def->caps->type = VIR_NODE_DEV_CAP_SCSI_HOST;
+        goto out;
+    }
+
+    if (devtype != NULL && STREQ(devtype, "scsi_device")) {
+        def->caps->type = VIR_NODE_DEV_CAP_SCSI;
+        goto out;
+    }
+
+    if (devtype != NULL && STREQ(devtype, "disk")) {
+        def->caps->type = VIR_NODE_DEV_CAP_STORAGE;
+        goto out;
+    }
+
+    ret = -1;
+
+out:
+    return ret;
+}
+
+
+static int udevGetDeviceDetails(struct udev_device *device,
+                                virNodeDeviceDefPtr def)
+{
+    int ret = 0;
+
+    switch (def->caps->type) {
+    case VIR_NODE_DEV_CAP_SYSTEM:
+        /* There's no libudev equivalent of system, so ignore it. */
+        break;
+    case VIR_NODE_DEV_CAP_PCI_DEV:
+        ret = udevProcessPCI(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_USB_DEV:
+        ret = udevProcessUSBDevice(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_USB_INTERFACE:
+        ret = udevProcessUSBInterface(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_NET:
+        ret = udevProcessNetworkInterface(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_SCSI_HOST:
+        ret = udevProcessSCSIHost(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_SCSI:
+        ret = udevProcessSCSIDevice(device, def);
+        break;
+    case VIR_NODE_DEV_CAP_STORAGE:
+        ret = udevProcessStorage(device, def);
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+
+static int udevRemoveOneDevice(struct udev_device *device)
+{
+    virNodeDeviceObjPtr dev = NULL;
+    const char *name = NULL;
+    int ret = 0;
+
+    name = udev_device_get_syspath(device);
+
+    dev = virNodeDeviceFindByName(&driverState->devs, name);
+    if (dev != NULL) {
+        virNodeDeviceObjRemove(&driverState->devs, dev);
+    } else {
+        ret = -1;
+    }
+
+    return ret;
+}
+
+
+static int udevAddOneDevice(struct udev_device *device)
+{
+    virNodeDeviceDefPtr def = NULL;
+    struct udev_device *parent = NULL;
+    virNodeDeviceObjPtr dev = NULL;
+    const char *parent_name = NULL;
+    int ret = -1;
+
+    if (VIR_ALLOC(def) != 0) {
+        goto out;
+    }
+
+    def->name = strdup(udev_device_get_syspath(device));
+    if (udevGetStringProperty(device,
+                              "DRIVER",
+                              &def->driver) == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    parent = udev_device_get_parent(device);
+    if (parent != NULL) {
+        parent_name = udev_device_get_syspath(parent);
+        if (parent_name != NULL) {
+            def->parent = strdup(parent_name);
+        }
+    }
+
+    if (udevSetDeviceType(device, def) == 0) {
+        ret = udevGetDeviceDetails(device, def);
+    }
+
+    if (ret == 0) {
+        dev = virNodeDeviceAssignDef(NULL, &driverState->devs, def);
+        dev->devicePath = strdup(udev_device_get_devpath(device));
+        virNodeDeviceObjUnlock(dev);
+    } else {
+        virNodeDeviceDefFree(def);
+    }
+
+out:
+    return ret;
+}
+
+
+static int udevProcessDeviceListEntry(struct udev *udev,
+                                      struct udev_list_entry *list_entry)
+{
+    struct udev_device *device;
+    const char *name = NULL;
+    int ret = -1;
+
+    name = udev_list_entry_get_name(list_entry);
+
+    device = udev_device_new_from_syspath(udev, name);
+    if (device != NULL) {
+        udevAddOneDevice(device);
+        udev_device_unref(device);
+        ret = 0;
+    }
+
+    return ret;
+}
+
+
+static int udevEnumerateDevices(struct udev *udev)
+{
+    struct udev_enumerate *udev_enumerate = NULL;
+    struct udev_list_entry *list_entry = NULL;
+    const char *name = NULL;
+    int ret = 0;
+
+    udev_enumerate = udev_enumerate_new(udev);
+
+    ret = udev_enumerate_scan_devices(udev_enumerate);
+    if (0 != ret) {
+        VIR_ERROR("udev scan devices returned %d\n", ret);
+        goto out;
+    }
+
+    udev_list_entry_foreach(list_entry,
+                            udev_enumerate_get_list_entry(udev_enumerate)) {
+
+        udevProcessDeviceListEntry(udev, list_entry);
+        name = udev_list_entry_get_name(list_entry);
+    }
+
+out:
+    udev_enumerate_unref(udev_enumerate);
+    return ret;
+}
+
+
+static int udevDeviceMonitorShutdown(void)
+{
+    int ret = 0;
+
+    struct udev_monitor *udev_monitor = NULL;
+    struct udev *udev = NULL;
+
+    if (driverState) {
+
+        nodeDeviceLock(driverState);
+        udev_monitor = DRV_STATE_UDEV_MONITOR(driverState);
+
+        if (udev_monitor != NULL) {
+            udev = udev_monitor_get_udev(udev_monitor);
+            udev_monitor_unref(udev_monitor);
+        }
+
+        if (udev != NULL) {
+            udev_unref(udev);
+        }
+
+        virNodeDeviceObjListFree(&driverState->devs);
+        nodeDeviceUnlock(driverState);
+        virMutexDestroy(&driverState->lock);
+        VIR_FREE(driverState);
+
+    } else {
+        ret = -1;
+    }
+
+    return ret;
+}
+
+
+static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
+                                    int fd,
+                                    int events ATTRIBUTE_UNUSED,
+                                    void *data ATTRIBUTE_UNUSED)
+{
+    struct udev_device *device = NULL;
+    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driverState);
+    const char *action = NULL;
+
+    if (fd != udev_monitor_get_fd(udev_monitor)) {
+        goto out;
+    }
+
+    device = udev_monitor_receive_device(udev_monitor);
+    if (device == NULL) {
+        goto out;
+    }
+
+    action = udev_device_get_action(device);
+
+    if (STREQ(action, "add") || STREQ(action, "change")) {
+        udevAddOneDevice(device);
+        goto out;
+    }
+
+    if (STREQ(action, "remove")) {
+        udevRemoveOneDevice(device);
+        goto out;
+    }
+
+out:
+    return;
+}
+
+
+static int udevSetupSystemDev(void)
+{
+    virNodeDeviceDefPtr def = NULL;
+    virNodeDeviceObjPtr dev = NULL;
+    struct udev *udev = NULL;
+    struct udev_device *device = NULL;
+    union _virNodeDevCapData *data = NULL;
+    char *tmp = NULL;
+    int ret = -1;
+
+    if (VIR_ALLOC(def) != 0) {
+        goto out;
+    }
+
+    def->name = strdup("computer");
+    if (def->name == NULL) {
+        goto out;
+    }
+
+    if (VIR_ALLOC(def->caps) != 0) {
+        goto out;
+    }
+
+    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driverState));
+    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
+    if (device == NULL) {
+        goto out;
+    }
+
+    data = &def->caps->data;
+
+    data->system.dmi_devpath = strdup(DMI_DEVPATH);
+    data->system.description = strdup(SYSTEM_DESCRIPTION);
+
+    if (udevGetStringSysfsAttr(device,
+                               "product_name",
+                               &data->system.product_name) == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "sys_vendor",
+                               &data->system.hardware.vendor_name)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "product_version",
+                               &data->system.hardware.version)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "product_serial",
+                               &data->system.hardware.serial)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    if (udevGetStringSysfsAttr(device,
+                               "product_uuid",
+                               &tmp) == PROPERTY_ERROR) {
+        goto out;
+    }
+    virUUIDParse(tmp, def->caps->data.system.hardware.uuid);
+    VIR_FREE(tmp);
+
+    if (udevGetStringSysfsAttr(device,
+                               "bios_vendor",
+                               &data->system.firmware.vendor_name)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "bios_version",
+                               &data->system.firmware.version)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+    if (udevGetStringSysfsAttr(device,
+                               "bios_date",
+                               &data->system.firmware.release_date)
+        == PROPERTY_ERROR) {
+        goto out;
+    }
+
+    udev_device_unref(device);
+
+    dev = virNodeDeviceAssignDef(NULL, &driverState->devs, def);
+    virNodeDeviceObjUnlock(dev);
+
+    ret = 0;
+
+out:
+    return ret;
+}
+
+static int udevDeviceMonitorStartup(int privileged ATTRIBUTE_UNUSED)
+{
+    struct udev *udev = NULL;
+    struct udev_monitor *udev_monitor = NULL;
+    int ret = 0;
+
+    if (VIR_ALLOC(driverState) < 0) {
+        ret = -1;
+        goto out;
+    }
+
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        ret = -1;
+        goto out;
+    }
+
+    nodeDeviceLock(driverState);
+
+    /*
+     * http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/libudev-udev.html#udev-new
+     *
+     * indicates no return value other than success, so we don't check
+     * its return value.
+     */
+    udev = udev_new();
+    udev_set_log_fn(udev, udevLogFunction);
+
+    udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
+    if (udev_monitor == NULL) {
+        ret = -1;
+        goto out;
+    }
+
+    udev_monitor_enable_receiving(udev_monitor);
+
+    /* udev can be retrieved from udev_monitor */
+    driverState->privateData = udev_monitor;
+    nodeDeviceUnlock(driverState);
+
+    /* We register the monitor with the event callback so we are
+     * notified by udev of device changes before we enumerate existing
+     * devices because libvirt will simply recreate the device if we
+     * try to register it twice, i.e., if the device appears between
+     * the time we register the callback and the time we begin
+     * enumeration.  The alternative is to register the callback after
+     * we enumerate, in which case we will fail to create any devices
+     * that appear while the enumeration is taking place.  */
+    if (virEventAddHandleImpl(udev_monitor_get_fd(udev_monitor),
+                              VIR_EVENT_HANDLE_READABLE,
+                              udevEventHandleCallback,
+                              NULL, NULL) == -1) {
+        ret = -1;
+        goto out;
+    }
+
+    /* Create a fictional 'computer' device to root the device tree. */
+    if (udevSetupSystemDev() != 0) {
+        ret = -1;
+        goto out;
+    }
+
+    /* Populate with known devices */
+
+    if (udevEnumerateDevices(udev) != 0) {
+        ret = -1;
+        goto out;
+    }
+
+out:
+    if (ret == -1) {
+        udevDeviceMonitorShutdown();
+    }
+    return ret;
+}
+
+
+static int udevDeviceMonitorReload(void)
+{
+    return 0;
+}
+
+
+static int udevDeviceMonitorActive(void)
+{
+    /* Always ready to deal with a shutdown */
+    return 0;
+}
+
+
+static virDrvOpenStatus udevNodeDrvOpen(virConnectPtr conn,
+                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                                        int flags ATTRIBUTE_UNUSED)
+{
+    if (driverState == NULL) {
+        return VIR_DRV_OPEN_DECLINED;
+    }
+
+    conn->devMonPrivateData = driverState;
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int udevNodeDrvClose(virConnectPtr conn)
+{
+    conn->devMonPrivateData = NULL;
+    return 0;
+}
+
+static virDeviceMonitor udevDeviceMonitor = {
+    .name = "udevDeviceMonitor",
+    .open = udevNodeDrvOpen,
+    .close = udevNodeDrvClose,
+};
+
+static virStateDriver udevStateDriver = {
+    .initialize = udevDeviceMonitorStartup,
+    .cleanup = udevDeviceMonitorShutdown,
+    .reload = udevDeviceMonitorReload,
+    .active = udevDeviceMonitorActive,
+};
+
+int udevNodeRegister(void)
+{
+    VIR_ERROR0("Registering udev node device backend\n");
+
+    registerCommonNodeFuncs(&udevDeviceMonitor);
+    if (virRegisterDeviceMonitor(&udevDeviceMonitor) < 0) {
+        return -1;
+    }
+
+    return virRegisterStateDriver(&udevStateDriver);
+}
diff --git a/src/node_device/node_device_udev.h b/src/node_device/node_device_udev.h
new file mode 100644
index 0000000..d950106
--- /dev/null
+++ b/src/node_device/node_device_udev.h
@@ -0,0 +1,32 @@
+/*
+ * 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 SYSTEM_DESCRIPTION "fictional device to root the node device tree"
+#define PROPERTY_FOUND 0
+#define PROPERTY_MISSING 1
+#define PROPERTY_ERROR -1
diff --git a/src/util/util.c b/src/util/util.c
index 98f8a14..f63bd39 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2114,3 +2114,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;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 8679636..da410e1 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -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__ */
diff --git a/tools/virsh.c b/tools/virsh.c
index 6b93405..19a2eb1 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -5790,9 +5790,17 @@ cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
         char **parents = vshMalloc(ctl, sizeof(char *) * num_devices);
         for (i = 0; i < num_devices; i++) {
             virNodeDevicePtr dev = virNodeDeviceLookupByName(ctl->conn, devices[i]);
+            virNodeDevicePtr parent_dev = NULL;
+
             if (dev && STRNEQ(devices[i], "computer")) {
                 const char *parent = virNodeDeviceGetParent(dev);
-                parents[i] = parent ? strdup(parent) : NULL;
+                parent_dev = virNodeDeviceLookupByName(ctl->conn, parent);
+                if (parent_dev) {
+                    parents[i] = strdup(parent);
+                } else {
+                    parents[i] = strdup("computer");
+                }
+                virNodeDeviceFree(parent_dev);
             } else {
                 parents[i] = NULL;
             }
-- 
1.6.4.4

>From cc3644b71d042ff394c9540a9f364752484f63a8 Mon Sep 17 00:00:00 2001
From: David Allan <dallan redhat com>
Date: Fri, 16 Oct 2009 14:36:07 -0400
Subject: [PATCH 3/3] Remove DevKit node device backend

---
 configure.in                         |   61 +-----
 src/Makefile.am                      |    9 -
 src/node_device/node_device_devkit.c |  446 ----------------------------------
 src/node_device/node_device_driver.c |    3 -
 src/node_device/node_device_driver.h |    3 -
 5 files changed, 1 insertions(+), 521 deletions(-)
 delete mode 100644 src/node_device/node_device_devkit.c

diff --git a/configure.in b/configure.in
index 25ed55f..3d05d9b 100644
--- a/configure.in
+++ b/configure.in
@@ -1680,60 +1680,6 @@ AM_CONDITIONAL([HAVE_HAL], [test "x$with_hal" = "xyes"])
 AC_SUBST([HAL_CFLAGS])
 AC_SUBST([HAL_LIBS])

-DEVKIT_REQUIRED=0.0
-DEVKIT_CFLAGS=
-DEVKIT_LIBS=
-AC_ARG_WITH([devkit],
-  [  --with-devkit      use DeviceKit for host device enumeration],
-  [],
-  [with_devkit=no])
-
-if test "$with_libvirtd" = "no" ; then
-  with_devkit=no
-fi
-
-dnl Extra check needed while devkit pkg-config info missing glib2 dependency
-PKG_CHECK_MODULES(GLIB2, glib-2.0 >= 0.0,,[
-  if test "x$with_devkit" = "xcheck"; then
-    with_devkit=no
-  elif test "x$with_devkit" = "xyes"; then
-    AC_MSG_ERROR([required package DeviceKit requires package glib-2.0])
-  fi])
-
-if test "x$with_devkit" = "xyes" -o "x$with_devkit" = "xcheck"; then
-  PKG_CHECK_MODULES(DEVKIT, devkit-gobject >= $DEVKIT_REQUIRED,
-    [with_devkit=yes], [
-    if test "x$with_devkit" = "xcheck" ; then
-       with_devkit=no
-    else
-       AC_MSG_ERROR(
-         [You must install DeviceKit-devel >= $DEVKIT_REQUIRED to compile libvirt])
-    fi
-  ])
-  if test "x$with_devkit" = "xyes" ; then
-    AC_DEFINE_UNQUOTED([HAVE_DEVKIT], 1,
-      [use DeviceKit for host device enumeration])
-
-    dnl Add glib2 flags explicitly while devkit pkg-config info missing glib2 dependency
-    DEVKIT_CFLAGS="$GLIB2_CFLAGS $DEVKIT_CFLAGS"
-    DEVKIT_LIBS="$GLIB2_LIBS $DEVKIT_LIBS"
-
-    dnl Add more flags apparently required for devkit to work properly
-    DEVKIT_CFLAGS="$DEVKIT_CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
-
-    old_CFLAGS=$CFLAGS
-    old_LDFLAGS=$LDFLAGS
-    CFLAGS="$CFLAGS $DEVKIT_CFLAGS"
-    LDFLAGS="$LDFLAGS $DEVKIT_LIBS"
-    AC_CHECK_FUNCS([devkit_client_connect],,[with_devkit=no])
-    CFLAGS="$old_CFLAGS"
-    LDFLAGS="$old_LDFLAGS"
-  fi
-fi
-AM_CONDITIONAL([HAVE_DEVKIT], [test "x$with_devkit" = "xyes"])
-AC_SUBST([DEVKIT_CFLAGS])
-AC_SUBST([DEVKIT_LIBS])
-
 UDEV_REQUIRED=143
 UDEV_CFLAGS=
 UDEV_LIBS=
@@ -1773,7 +1719,7 @@ AC_SUBST([UDEV_CFLAGS])
 AC_SUBST([UDEV_LIBS])

 with_nodedev=no;
-if test "$with_devkit" = "yes" -o "$with_hal" = "yes" -o "$with_udev" = "yes";
+if test "$with_hal" = "yes" -o "$with_udev" = "yes";
 then
   with_nodedev=yes
   AC_DEFINE_UNQUOTED([WITH_NODE_DEVICES], 1, [with node device driver])
@@ -1933,11 +1879,6 @@ AC_MSG_NOTICE([     hal: $HAL_CFLAGS $HAL_LIBS])
 else
 AC_MSG_NOTICE([     hal: no])
 fi
-if test "$with_devkit" = "yes" ; then
-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
diff --git a/src/Makefile.am b/src/Makefile.am
index 11da07b..cd05c28 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -262,9 +262,6 @@ NODE_DEVICE_DRIVER_HAL_SOURCES =				\
 		node_device/node_device_hal.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

@@ -641,11 +638,6 @@ libvirt_driver_nodedev_la_SOURCES += $(NODE_DEVICE_DRIVER_HAL_SOURCES)
 libvirt_driver_nodedev_la_CFLAGS += $(HAL_CFLAGS)
 libvirt_driver_nodedev_la_LDFLAGS += $(HAL_LIBS)
 endif
-if HAVE_DEVKIT
-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)
@@ -699,7 +691,6 @@ EXTRA_DIST +=							\
 		$(STORAGE_DRIVER_DISK_SOURCES)			\
 		$(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)		\
diff --git a/src/node_device/node_device_devkit.c b/src/node_device/node_device_devkit.c
deleted file mode 100644
index a6c7941..0000000
--- a/src/node_device/node_device_devkit.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * node_device_devkit.c: node device enumeration - DeviceKit-based implementation
- *
- * Copyright (C) 2008 Virtual Iron Software, Inc.
- * Copyright (C) 2008 David F. Lively
- *
- * 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: David F. Lively <dlively virtualiron com>
- */
-
-#include <config.h>
-#include <devkit-gobject.h>
-
-#include "node_device_conf.h"
-#include "virterror_internal.h"
-#include "driver.h"
-#include "datatypes.h"
-#include "event.h"
-#include "memory.h"
-#include "uuid.h"
-#include "logging.h"
-
-#include "node_device.h"
-
-/*
- * Host device enumeration (DeviceKit implementation)
- */
-
-static virDeviceMonitorStatePtr driverState;
-
-#define CONN_DRV_STATE(conn) \
-        ((virDeviceMonitorStatePtr)((conn)->devMonPrivateData))
-#define DRV_STATE_DKCLIENT(ds) ((DevkitClient *)((ds)->privateData))
-#define CONN_DKCLIENT(conn) DRV_STATE_DKCLIENT(CONN_DRV_STATE(conn))
-
-#define NODE_DEV_DKDEV(obj) ((DevkitDevice *)((obj)->privateData)
-
-static int get_str_prop(DevkitDevice *dkdev, const char *prop, char **val_p)
-{
-    char *val = devkit_device_dup_property_as_str(dkdev, prop);
-
-    if (val) {
-        if (*val) {
-            *val_p = val;
-            return 0;
-        } else {
-            /* Treat empty strings as NULL values */
-            VIR_FREE(val);
-        }
-    }
-
-    return -1;
-}
-
-#if 0
-static int get_int_prop(DevkitDevice *dkdev, const char *prop, int *val_p)
-{
-    if (! devkit_device_has_property(dkdev, prop))
-        return -1;
-    *val_p = devkit_device_get_property_as_int(dkdev, prop);
-    return 0;
-}
-
-static int get_uint64_prop(DevkitDevice *dkdev, const char *prop,
-                           unsigned long long *val_p)
-{
-    if (! devkit_device_has_property(dkdev, prop))
-        return -1;
-    *val_p = devkit_device_get_property_as_uint64(dkdev, prop);
-    return 0;
-}
-#endif
-
-static int gather_pci_cap(DevkitDevice *dkdev,
-                          union _virNodeDevCapData *d)
-{
-    const char *sysfs_path = devkit_device_get_native_path(dkdev);
-
-    if (sysfs_path != NULL) {
-        char *p = strrchr(sysfs_path, '/');
-        if (p) {
-            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.domain);
-            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.bus);
-            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.slot);
-            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.function);
-        }
-    }
-    return 0;
-}
-
-
-static int gather_usb_cap(DevkitDevice *dkdev,
-                          union _virNodeDevCapData *d)
-{
-    (void)get_str_prop(dkdev, "ID_VENDOR", &d->usb_dev.vendor_name);
-    (void)get_str_prop(dkdev, "ID_MODEL", &d->usb_dev.product_name);
-    return 0;
-}
-
-
-static int gather_net_cap(DevkitDevice *dkdev,
-                          union _virNodeDevCapData *d)
-{
-    const char *sysfs_path = devkit_device_get_native_path(dkdev);
-    const char *ifname;
-
-    if (sysfs_path == NULL)
-        return -1;
-    ifname = strrchr(sysfs_path, '/');
-    if (!ifname || !*ifname || !*(++ifname))
-        return -1;
-    if ((d->net.ifname = strdup(ifname)) == NULL)
-        return -1;
-
-    d->net.subtype = VIR_NODE_DEV_CAP_NET_LAST;
-
-    return 0;
-}
-
-
-static int gather_storage_cap(DevkitDevice *dkdev,
-                              union _virNodeDevCapData *d)
-{
-    const char *device = devkit_device_get_device_file(dkdev);
-
-    if (device && ((d->storage.block = strdup(device)) == NULL))
-        return -1;
-
-    return 0;
-}
-
-
-struct _caps_tbl_entry {
-    const char *cap_name;
-    enum virNodeDevCapType type;
-    int (*gather_fn)(DevkitDevice *dkdev,
-                     union _virNodeDevCapData *data);
-};
-
-typedef struct _caps_tbl_entry caps_tbl_entry;
-
-static caps_tbl_entry caps_tbl[] = {
-    { "pci",        VIR_NODE_DEV_CAP_PCI_DEV,   gather_pci_cap },
-    { "usb",        VIR_NODE_DEV_CAP_USB_DEV,   gather_usb_cap },
-    { "net",        VIR_NODE_DEV_CAP_NET,       gather_net_cap },
-    { "block",      VIR_NODE_DEV_CAP_STORAGE,   gather_storage_cap },
-    // TODO: more caps!
-};
-
-
-/* qsort/bsearch string comparator */
-static int cmpstringp(const void *p1, const void *p2)
-{
-    /* from man 3 qsort */
-    return strcmp(* (char * const *) p1, * (char * const *) p2);
-}
-
-
-static int gather_capability(DevkitDevice *dkdev,
-                             const char *cap_name,
-                             virNodeDevCapsDefPtr *caps_p)
-{
-    size_t caps_tbl_len = sizeof(caps_tbl) / sizeof(caps_tbl[0]);
-    caps_tbl_entry *entry;
-
-    entry = bsearch(&cap_name, caps_tbl, caps_tbl_len,
-                    sizeof(caps_tbl[0]), cmpstringp);
-
-    if (entry) {
-        virNodeDevCapsDefPtr caps;
-        if (VIR_ALLOC(caps) < 0)
-            return ENOMEM;
-        caps->type = entry->type;
-        if (entry->gather_fn) {
-            int rv = (*entry->gather_fn)(dkdev, &caps->data);
-            if (rv != 0) {
-                virNodeDevCapsDefFree(caps);
-                return rv;
-            }
-        }
-        caps->next = *caps_p;
-        *caps_p = caps;
-    }
-
-    return 0;
-}
-
-
-static int gather_capabilities(DevkitDevice *dkdev,
-                               virNodeDevCapsDefPtr *caps_p)
-{
-    const char *subsys = devkit_device_get_subsystem(dkdev);
-    const char *bus_name = devkit_device_get_property(dkdev, "ID_BUS");
-    virNodeDevCapsDefPtr caps = NULL;
-    int rv;
-
-    if (subsys) {
-        rv = gather_capability(dkdev, subsys, &caps);
-        if (rv != 0) goto failure;
-    }
-
-    if (bus_name && (subsys == NULL || !STREQ(bus_name, subsys))) {
-        rv = gather_capability(dkdev, bus_name, &caps);
-        if (rv != 0) goto failure;
-    }
-
-    *caps_p = caps;
-    return 0;
-
- failure:
-    while (caps) {
-        virNodeDevCapsDefPtr next = caps->next;
-        virNodeDevCapsDefFree(caps);
-        caps = next;
-    }
-    return rv;
-}
-
-static void dev_create(void *_dkdev, void *_dkclient ATTRIBUTE_UNUSED)
-{
-    DevkitDevice *dkdev = _dkdev;
-    const char *sysfs_path = devkit_device_get_native_path(dkdev);
-    virNodeDeviceObjPtr dev = NULL;
-    virNodeDeviceDefPtr def = NULL;
-    const char *name;
-    int rv;
-
-    if (sysfs_path == NULL)
-        /* Currently using basename(sysfs_path) as device name (key) */
-        return;
-
-    name = strrchr(sysfs_path, '/');
-    if (name == NULL)
-        name = sysfs_path;
-    else
-        ++name;
-
-    if (VIR_ALLOC(def) < 0)
-        goto failure;
-
-    if ((def->name = strdup(name)) == NULL)
-        goto failure;
-
-    // TODO: Find device parent, if any
-
-    rv = gather_capabilities(dkdev, &def->caps);
-    if (rv != 0) goto failure;
-
-    nodeDeviceLock(driverState);
-    dev = virNodeDeviceAssignDef(NULL,
-                                 &driverState->devs,
-                                 def);
-
-    if (!dev) {
-        nodeDeviceUnlock(driverState);
-        goto failure;
-    }
-
-    dev->privateData = dkdev;
-    dev->privateFree = NULL; /* XXX some free func needed ? */
-    virNodeDeviceObjUnlock(dev);
-
-    nodeDeviceUnlock(driverState);
-
-    return;
-
- failure:
-    DEBUG("FAILED TO ADD dev %s", name);
-    if (def)
-        virNodeDeviceDefFree(def);
-}
-
-
-static int devkitDeviceMonitorStartup(int privileged ATTRIBUTE_UNUSED)
-{
-    size_t caps_tbl_len = sizeof(caps_tbl) / sizeof(caps_tbl[0]);
-    DevkitClient *devkit_client = NULL;
-    GError *err = NULL;
-    GList *devs;
-    int i;
-
-    /* Ensure caps_tbl is sorted by capability name */
-    qsort(caps_tbl, caps_tbl_len, sizeof(caps_tbl[0]), cmpstringp);
-
-    if (VIR_ALLOC(driverState) < 0)
-        return -1;
-
-    if (virMutexInit(&driverState->lock) < 0) {
-        VIR_FREE(driverState);
-        return -1;
-    }
-
-    g_type_init();
-
-    /* Get new devkit_client and connect to daemon */
-    devkit_client = devkit_client_new(NULL);
-    if (devkit_client == NULL) {
-        DEBUG0("devkit_client_new returned NULL");
-        goto failure;
-    }
-    if (!devkit_client_connect(devkit_client, &err)) {
-        DEBUG0("devkit_client_connect failed");
-        goto failure;
-    }
-
-    /* Populate with known devices.
-     *
-     * This really should be:
-        devs = devkit_client_enumerate_by_subsystem(devkit_client, NULL, &err);
-        if (err) {
-            DEBUG0("devkit_client_enumerate_by_subsystem failed");
-            devs = NULL;
-            goto failure;
-        }
-        g_list_foreach(devs, dev_create, devkit_client);
-    * but devkit_client_enumerate_by_subsystem currently fails when the second
-    * arg is null (contrary to the API documentation).  So the following code
-    * (from Dan B) works around this by listing devices per handled subsystem.
-    */
-
-    for (i = 0 ; i < ARRAY_CARDINALITY(caps_tbl) ; i++) {
-        const char *caps[] = { caps_tbl[i].cap_name, NULL };
-        devs = devkit_client_enumerate_by_subsystem(devkit_client,
-                                                    caps,
-                                                    &err);
-        if (err) {
-            DEBUG0("devkit_client_enumerate_by_subsystem failed");
-            devs = NULL;
-            goto failure;
-        }
-        g_list_foreach(devs, dev_create, devkit_client);
-    }
-
-    driverState->privateData = devkit_client;
-
-    // TODO: Register to get DeviceKit events on device changes and
-    //       coordinate updates with queries and other operations.
-
-    return 0;
-
- failure:
-    if (err) {
-        DEBUG("\terror[%d]: %s", err->code, err->message);
-        g_error_free(err);
-    }
-    if (devs) {
-        g_list_foreach(devs, (GFunc)g_object_unref, NULL);
-        g_list_free(devs);
-    }
-    if (devkit_client)
-        g_object_unref(devkit_client);
-    VIR_FREE(driverState);
-
-    return -1;
-}
-
-
-static int devkitDeviceMonitorShutdown(void)
-{
-    if (driverState) {
-        DevkitClient *devkit_client;
-
-        nodeDeviceLock(driverState);
-        devkit_client = DRV_STATE_DKCLIENT(driverState);
-        virNodeDeviceObjListFree(&driverState->devs);
-        if (devkit_client)
-            g_object_unref(devkit_client);
-        nodeDeviceUnlock(driverState);
-        virMutexDestroy(&driveState->lock);
-        VIR_FREE(driverState);
-        return 0;
-    }
-    return -1;
-}
-
-
-static int devkitDeviceMonitorReload(void)
-{
-    /* XXX This isn't thread safe because its free'ing the thing
-     * we're locking */
-    (void)devkitDeviceMonitorShutdown();
-    return devkitDeviceMonitorStartup();
-}
-
-
-static int devkitDeviceMonitorActive(void)
-{
-    /* Always ready to deal with a shutdown */
-    return 0;
-}
-
-
-static virDrvOpenStatus
-devkitNodeDrvOpen(virConnectPtr conn,
-                  virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-                  int flags ATTRIBUTE_UNUSED)
-{
-    if (driverState == NULL)
-        return VIR_DRV_OPEN_DECLINED;
-
-    conn->devMonPrivateData = driverState;
-
-    return VIR_DRV_OPEN_SUCCESS;
-}
-
-static int devkitNodeDrvClose(virConnectPtr conn ATTRIBUTE_UNUSED)
-{
-    conn->devMonPrivateData = NULL;
-    return 0;
-}
-
-
-static virDeviceMonitor devkitDeviceMonitor = {
-    .name = "devkitDeviceMonitor",
-    .open = devkitNodeDrvOpen,
-    .close = devkitNodeDrvClose,
-};
-
-
-static virStateDriver devkitStateDriver = {
-    .initialize = devkitDeviceMonitorStartup,
-    .cleanup = devkitDeviceMonitorShutdown,
-    .reload = devkitDeviceMonitorReload,
-    .active = devkitDeviceMonitorActive,
-};
-
-int devkitNodeRegister(void)
-{
-    registerCommonNodeFuncs(&devkitDeviceMonitor);
-    if (virRegisterDeviceMonitor(&devkitDeviceMonitor) < 0)
-        return -1;
-    return virRegisterStateDriver(&devkitStateDriver);
-}
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index c139907..cddd994 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -670,9 +670,6 @@ int nodedevRegister(void) {
 #ifdef HAVE_HAL
     return halNodeRegister();
 #endif
-#ifdef HAVE_DEVKIT
-    return devkitNodeRegister();
-#endif
 #ifdef HAVE_UDEV
     return udevNodeRegister();
 #endif
diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
index 5be0781..4f0822c 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -42,9 +42,6 @@
 #ifdef HAVE_HAL
 int halNodeRegister(void);
 #endif
-#ifdef HAVE_DEVKIT
-int devkitNodeRegister(void);
-#endif
 #ifdef HAVE_UDEV
 int udevNodeRegister(void);
 #endif
-- 
1.6.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]