[PATCH 4/8] rework handling of data from udevinfo for more efficient memory usage
Rob Taylor
rob.taylor at codethink.co.uk
Thu Mar 6 15:42:21 PST 2008
This patch reworks the handling of the output of udevinfo so that the
output is
parsed into an intermediatary form (with a hash table of sysfpath to
structures
pointing directly into the output as captured). This is converted into
HotplugEvents one at a time when needed by coldplug_get_hotplug_event.
---
hald/linux/coldplug.c | 175
++++++++++++++++++++++++++++++++-----------------
1 files changed, 115 insertions(+), 60 deletions(-)
diff --git a/hald/linux/coldplug.c b/hald/linux/coldplug.c
index 3ad7199..dbc1830 100644
--- a/hald/linux/coldplug.c
+++ b/hald/linux/coldplug.c
@@ -55,23 +55,107 @@ struct sysfs_device {
static GHashTable *sysfs_to_udev_map;
static GSList *device_list;
static char dev_root[HAL_PATH_MAX];
+static gchar *udevinfo_stdout = NULL;
-static void hotplug_event_free (HotplugEvent *ev)
+typedef struct _UdevInfo UdevInfo;
+
+struct _UdevInfo
+{
+ const char *sysfs_path;
+ const char *device_file;
+ const char *vendor;
+ const char *model;
+ const char *revision;
+ const char *serial;
+ const char *fsusage;
+ const char *fstype;
+ const char *fsversion;
+ const char *fsuuid;
+ const char *fslabel;
+};
+
+static void udev_info_free (gpointer data)
+{
+ g_slice_free(UdevInfo, data);
+}
+
+
+static HotplugEvent*
+udev_info_to_hotplug_event (const UdevInfo *info)
{
- g_slice_free(HotplugEvent, ev);
+ HotplugEvent *hotplug_event;
+ gchar *str;
+
+ hotplug_event = g_slice_new0 (HotplugEvent);
+ g_strlcpy (hotplug_event->sysfs.sysfs_path, "/sys",
sizeof(hotplug_event->sysfs.sysfs_path));
+ g_strlcat (hotplug_event->sysfs.sysfs_path, info->sysfs_path,
sizeof(hotplug_event->sysfs.sysfs_path));
+
+ HAL_INFO(("creating HotplugEvent for %s",
hotplug_event->sysfs.sysfs_path));
+
+ if (info->device_file) {
+ g_snprintf (hotplug_event->sysfs.device_file,
sizeof(hotplug_event->sysfs.device_file),
+ "%s/%s", dev_root, info->device_file);
+ HAL_INFO(("with device file %s", hotplug_event->sysfs.device_file));
+ }
+ if ((str = hal_util_strdup_valid_utf8(info->vendor)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.vendor, str,
sizeof(hotplug_event->sysfs.vendor));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->model)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.model, str,
sizeof(hotplug_event->sysfs.model));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->revision)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.revision, str,
sizeof(hotplug_event->sysfs.revision));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->serial)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.serial, str,
sizeof(hotplug_event->sysfs.serial));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->fsusage)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.fsusage, str,
sizeof(hotplug_event->sysfs.fsusage));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->fstype)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.fstype, str,
sizeof(hotplug_event->sysfs.fstype));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->fsversion)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.fsversion, str,
sizeof(hotplug_event->sysfs.fsversion));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->fsuuid)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.fsuuid, str,
sizeof(hotplug_event->sysfs.fsuuid));
+ g_free (str);
+ }
+
+ if ((str = hal_util_strdup_valid_utf8(info->fslabel)) != NULL) {
+ g_strlcpy (hotplug_event->sysfs.fslabel, str,
sizeof(hotplug_event->sysfs.fslabel));
+ g_free (str);
+ }
+
+ return hotplug_event;
}
+
static gboolean
hal_util_init_sysfs_to_udev_map (void)
{
char *udevdb_export_argv[] = { "/usr/bin/udevinfo", "-e", NULL };
char *udevroot_argv[] = { "/usr/bin/udevinfo", "-r", NULL };
- char *udevinfo_stdout;
int udevinfo_exitcode;
- HotplugEvent *hotplug_event = NULL;
+ UdevInfo *info = NULL;
char *p;
- sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, hotplug_event_free);
+ sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, udev_info_free);
/* get udevroot */
if (g_spawn_sync ("/", udevroot_argv, NULL, 0, NULL, NULL,
@@ -114,7 +198,6 @@ hal_util_init_sysfs_to_udev_map (void)
p = udevinfo_stdout;
while (p[0] != '\0') {
char *line, *end;
- gchar *str;
/* get line, terminate and move to next line */
line = p;
@@ -126,79 +209,49 @@ hal_util_init_sysfs_to_udev_map (void)
/* insert device */
if (line[0] == '\0') {
- if (hotplug_event != NULL) {
- g_hash_table_insert (sysfs_to_udev_map, g_strdup
(hotplug_event->sysfs.sysfs_path), hotplug_event);
- HAL_INFO (("found (udevdb export) '%s' -> '%s'",
- hotplug_event->sysfs.sysfs_path,
hotplug_event->sysfs.device_file));
- hotplug_event = NULL;
+ if (info != NULL) {
+ g_hash_table_insert (sysfs_to_udev_map, g_strdup_printf ("/sys%s",
info->sysfs_path), info);
+ HAL_INFO (("found (udevdb export) '/sys%s' -> '%s/%s'",
+ info->sysfs_path, dev_root, info->device_file));
+ info = NULL;
}
continue;
}
/* new device */
if (strncmp(line, "P: ", 3) == 0) {
- hotplug_event = g_slice_new0 (HotplugEvent);
- g_strlcpy (hotplug_event->sysfs.sysfs_path, "/sys",
sizeof(hotplug_event->sysfs.sysfs_path));
- g_strlcat (hotplug_event->sysfs.sysfs_path, &line[3],
sizeof(hotplug_event->sysfs.sysfs_path));
+ info = g_slice_new0 (UdevInfo);
+ info->sysfs_path = &line[3];
continue;
}
/* only valid if we have an actual device */
- if (hotplug_event == NULL)
+ if (info == NULL)
continue;
if (strncmp(line, "N: ", 3) == 0) {
- g_snprintf (hotplug_event->sysfs.device_file,
sizeof(hotplug_event->sysfs.device_file),
- "%s/%s", dev_root, &line[3]);
+ info->device_file = &line[3];
} else if (strncmp(line, "E: ID_VENDOR=", 13) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[13])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.vendor, str,
sizeof(hotplug_event->sysfs.vendor));
- g_free (str);
- }
+ info->vendor = &line[13];
} else if (strncmp(line, "E: ID_MODEL=", 12) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[12])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.model, str,
sizeof(hotplug_event->sysfs.model));
- g_free (str);
- }
+ info->model = &line[12];
} else if (strncmp(line, "E: ID_REVISION=", 15) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[15])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.revision, str,
sizeof(hotplug_event->sysfs.revision));
- g_free (str);
- }
+ info->revision = &line[15];
} else if (strncmp(line, "E: ID_SERIAL=", 13) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[13])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.serial, str,
sizeof(hotplug_event->sysfs.serial));
- g_free (str);
- }
+ info->serial = &line[13];
} else if (strncmp(line, "E: ID_FS_USAGE=", 15) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[15])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.fsusage, str,
sizeof(hotplug_event->sysfs.fsusage));
- g_free (str);
- }
+ info->fsusage = &line[15];
} else if (strncmp(line, "E: ID_FS_TYPE=", 14) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[14])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.fstype, str,
sizeof(hotplug_event->sysfs.fstype));
- g_free (str);
- }
+ info->fstype = &line[14];
} else if (strncmp(line, "E: ID_FS_VERSION=", 17) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[17])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.fsversion, str,
sizeof(hotplug_event->sysfs.fsversion));
- g_free (str);
- }
+ info->fsversion = &line[17];
} else if (strncmp(line, "E: ID_FS_UUID=", 14) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[14])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.fsuuid, str,
sizeof(hotplug_event->sysfs.fsuuid));
- g_free (str);
- }
+ info->fsuuid = &line[14];
} else if (strncmp(line, "E: ID_FS_LABEL=", 15) == 0) {
- if ((str = hal_util_strdup_valid_utf8(&line[15])) != NULL) {
- g_strlcpy (hotplug_event->sysfs.fslabel, str,
sizeof(hotplug_event->sysfs.fslabel));
- g_free (str);
- }
+ info->fslabel = &line[15];
}
}
- g_free(udevinfo_stdout);
return TRUE;
error:
@@ -211,19 +264,20 @@ error:
static HotplugEvent
*coldplug_get_hotplug_event(const gchar *sysfs_path, const gchar
*subsystem, HotplugEventType type)
{
- HotplugEvent *hotplug_event, *hotplug_event_udev;
+ HotplugEvent *hotplug_event;
const char *pos;
gchar path[HAL_PATH_MAX];
struct stat statbuf;
-
- hotplug_event = g_slice_new0 (HotplugEvent);
+ UdevInfo *info;
/* lookup if udev has something stored in its database */
- hotplug_event_udev = (HotplugEvent *) g_hash_table_lookup
(sysfs_to_udev_map, sysfs_path);
- if (hotplug_event_udev != NULL) {
- memcpy(hotplug_event, hotplug_event_udev, sizeof(HotplugEvent));
+ info = (UdevInfo*) g_hash_table_lookup (sysfs_to_udev_map, sysfs_path);
+ if (info) {
+ hotplug_event = udev_info_to_hotplug_event (info);
HAL_INFO (("new event (dev node from udev) '%s' '%s'",
hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file));
} else {
+ hotplug_event = g_slice_new0 (HotplugEvent);
+
/* device is not in udev database */
g_strlcpy(hotplug_event->sysfs.sysfs_path, sysfs_path,
sizeof(hotplug_event->sysfs.sysfs_path));
@@ -543,6 +597,7 @@ coldplug_synthesize_events (void)
}
g_hash_table_destroy (sysfs_to_udev_map);
+ g_free (udevinfo_stdout);
return TRUE;
error:
More information about the hal
mailing list