hal: Branch 'master' - 2 commits

David Zeuthen david at kemper.freedesktop.org
Sun Feb 25 22:03:18 PST 2007


 hald/device_info.c  |   23 ++++++++-
 hald/linux/osspec.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 hald/mmap_cache.c   |   25 ++++++++--
 hald/mmap_cache.h   |    5 +-
 hald/osspec.h       |    3 +
 5 files changed, 172 insertions(+), 7 deletions(-)

New commits:
diff-tree a00027944e46cfe9b29e6c9c820fc3ee0f1b4a03 (from 15f69a58d5f9ee26bacb705f71fdbb9b6aeeea63)
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon Feb 26 01:03:07 2007 -0500

    map new fdi cache file post regeneration

diff --git a/hald/device_info.c b/hald/device_info.c
index 50ca143..9af22b6 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -56,7 +56,7 @@
 #include "rule.h"
 #include "osspec.h"
 
-void	*rules_ptr = NULL;
+void *rules_ptr = NULL;
 
 #ifdef DUMP_RULES
 static char *
@@ -963,7 +963,8 @@ di_search_and_merge (HalDevice *d, Devic
 
 	if (fdi_cache_invalidated) {
 		/* make sure our fdi rule cache is up to date */
-		di_cache_coherency_check ();
+		if (di_cache_coherency_check ())
+			di_rules_init ();
 		fdi_cache_invalidated = FALSE;
 	}
 
diff --git a/hald/mmap_cache.c b/hald/mmap_cache.c
index 45e0ebe..db0d811 100644
--- a/hald/mmap_cache.c
+++ b/hald/mmap_cache.c
@@ -46,8 +46,11 @@
 #include "hald_runner.h"
 
 extern void *rules_ptr;
+static int rules_fd = -1;
+size_t rules_size = 0;
 
-void di_rules_init(void){
+void di_rules_init(void)
+{
 	struct cache_header	*header;
 	char 			*cachename;
 	int			fd;
@@ -57,12 +60,19 @@ void di_rules_init(void){
 	if(cachename == NULL) 
 		cachename = HALD_CACHE_FILE;
 
-	if((fd = open(cachename, O_RDONLY)) < 0)
+	if (rules_ptr != NULL) {
+		HAL_INFO (("Unmapping old cache file"));
+		munmap (rules_ptr, rules_size);
+	}
+
+	if((fd = open (cachename, O_RDONLY)) < 0)
 		DIE(("Unable to open cache %s\n", cachename));
 
-	if(fstat(fd,&statbuf) < 0)
+	if(fstat (fd,&statbuf) < 0)
 		DIE(("Unable to stat cache %s\n", cachename));
 
+	rules_size = statbuf.st_size;
+
 	rules_ptr = mmap (NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
 	if(rules_ptr == MAP_FAILED)
 		DIE (("Couldn't mmap file '%s', errno=%d: %s", cachename, errno, strerror (errno)));
@@ -185,7 +195,7 @@ regen_cache (void)
 	HAL_INFO (("fdi cache generation done"));
 }
 
-void 
+gboolean
 di_cache_coherency_check (void)
 {
 	char *hal_fdi_source_preprobe;
@@ -194,6 +204,9 @@ di_cache_coherency_check (void)
 	char *cachename;
 	time_t mt;
 	struct stat st;
+	gboolean did_regen;
+
+	did_regen = FALSE;
 
 	mt = 0;
 
@@ -230,10 +243,14 @@ di_cache_coherency_check (void)
 		if(st.st_mtime < mt) {
 			HAL_INFO(("Cache needs update"));
 			regen_cache();
+			did_regen = TRUE;
 		}
 	} else {
 		regen_cache();
+		did_regen = TRUE;
 	}
 	
 	HAL_INFO(("cache mtime is %d",mt));
+
+	return did_regen;
 }
diff --git a/hald/mmap_cache.h b/hald/mmap_cache.h
index bfafeb4..2206076 100644
--- a/hald/mmap_cache.h
+++ b/hald/mmap_cache.h
@@ -29,9 +29,12 @@
 
 
 #ifndef __MMAP_CACHE_H__
+#define __MMAP_CACHE_H__
+
+#include <glib.h>
 
 void di_rules_init(void);
-void di_cache_coherency_check(void);
+gboolean di_cache_coherency_check(void);
 
 #define RULES_PTR(x) ((void *)((unsigned char *) rules_ptr + x))
 #endif
diff-tree 15f69a58d5f9ee26bacb705f71fdbb9b6aeeea63 (from 10834e4474c21c2b474b4760e48ff809dd717df9)
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon Feb 26 00:46:42 2007 -0500

    use inotify to watch fdi directories
    
    When we see activity in the fdi file directories we call a method to
    invalidate the cache. The next time fdi files are needed, the cache
    will be regenerated. Currently it takes around 93 ms on my Core Duo
    2GHz to regenerate the cache (it's roughly 170kb).
    
    Solaris and FreeBSD backends should implement a similar mechanism and
    call osspec_fdi_cache_invalid() when changes are seen.

diff --git a/hald/device_info.c b/hald/device_info.c
index 5d68f17..50ca143 100644
--- a/hald/device_info.c
+++ b/hald/device_info.c
@@ -54,6 +54,7 @@
 #include "device_store.h"
 #include "util.h"
 #include "rule.h"
+#include "osspec.h"
 
 void	*rules_ptr = NULL;
 
@@ -952,11 +953,19 @@ rules_match_and_merge_device (void *fdi_
 	}
 }
 
+static gboolean fdi_cache_invalidated = FALSE;
+
 
 /* merge the device info type, either preprobe, info or policy */
 gboolean
 di_search_and_merge (HalDevice *d, DeviceInfoType type){
-	struct cache_header	*header = (struct cache_header*) RULES_PTR(0);
+	struct cache_header *header = (struct cache_header*) RULES_PTR(0);
+
+	if (fdi_cache_invalidated) {
+		/* make sure our fdi rule cache is up to date */
+		di_cache_coherency_check ();
+		fdi_cache_invalidated = FALSE;
+	}
 
 	switch (type) {
 	case DEVICE_INFO_TYPE_PREPROBE:
@@ -998,3 +1007,12 @@ di_search_and_merge (HalDevice *d, Devic
 
 	return TRUE;
 }
+
+/* Called by OS specific code to tell that the fdi cache is invalid */
+void 
+osspec_fdi_cache_invalid (void)
+{
+	HAL_INFO (("invalidating fdi cache"));
+	fdi_cache_invalidated = TRUE;
+}
+
diff --git a/hald/linux/osspec.c b/hald/linux/osspec.c
index c7eceb1..52c66d3 100644
--- a/hald/linux/osspec.c
+++ b/hald/linux/osspec.c
@@ -43,6 +43,7 @@
 #include <sys/un.h>
 #include <sys/utsname.h>
 #include <unistd.h>
+#include <sys/inotify.h>
 
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
@@ -264,6 +265,125 @@ osspec_privileged_init (void)
 {
 }
 
+static gboolean
+inotify_data (GIOChannel *source, GIOCondition condition, gpointer user_data)
+{
+	int fd;
+	char buf[256];
+
+	fd = g_io_channel_unix_get_fd (source);
+again:
+	if (read (fd, buf, sizeof (buf)) < 0) {
+		if (errno == EINTR) {
+			goto again;
+		} else {
+			HAL_ERROR (("read: %s", strerror (errno)));
+		}
+	}
+
+	/* TODO: OK, so the right thing to do would be to add watches
+	 * for directories that appear 
+	 */
+
+	osspec_fdi_cache_invalid ();
+	return TRUE;
+}
+
+static gboolean
+add_fdi_watch (int inotify_fd, const char *fdi_dir)
+{
+	int wd;
+	gboolean ret;
+	GDir *dir;
+	GError *error = NULL;
+	const char *name;
+
+	ret = FALSE;
+
+	wd = inotify_add_watch (inotify_fd, fdi_dir, IN_MODIFY | IN_CREATE | IN_DELETE);
+	if (wd < 0) {
+		HAL_ERROR (("Unable to inotify_add_watch() for '%s': %s", fdi_dir, strerror (errno)));
+		goto out;
+	}
+
+	/* watch sub dirs */
+	dir = g_dir_open (fdi_dir, 0, &error);
+	if (dir == NULL)
+		goto out;
+	while ((name = g_dir_read_name (dir)) != NULL) {
+		char *sub_dir;
+
+		sub_dir = g_strdup_printf ("%s/%s", fdi_dir, name);
+		if (g_file_test (sub_dir, G_FILE_TEST_IS_DIR)) {
+			add_fdi_watch (inotify_fd, sub_dir);
+		}
+		g_free (sub_dir);
+	}
+	g_dir_close (dir);
+
+	ret = TRUE;
+out:
+	return ret;
+}
+
+static void
+watch_fdi_files (void)
+{
+	int inotify_fd;
+	char *hal_fdi_source_preprobe;
+	char *hal_fdi_source_information;
+	char *hal_fdi_source_policy;
+	GIOChannel *inotify_channel;
+
+	hal_fdi_source_preprobe = getenv ("HAL_FDI_SOURCE_PREPROBE");
+	hal_fdi_source_information = getenv ("HAL_FDI_SOURCE_INFORMATION");
+	hal_fdi_source_policy = getenv ("HAL_FDI_SOURCE_POLICY");
+
+	inotify_fd = inotify_init ();
+	if (inotify_fd < 0) {
+		DIE (("Unable to initialize inotify: %s ", strerror (errno)));
+		goto out;
+	}
+	inotify_channel = g_io_channel_unix_new (inotify_fd);
+	g_io_add_watch (inotify_channel, G_IO_IN, inotify_data, NULL);
+	g_io_channel_unref (inotify_channel);
+
+
+	if (hal_fdi_source_preprobe != NULL) {
+		if (!add_fdi_watch (inotify_fd, hal_fdi_source_preprobe))
+			goto out;
+	} else {
+		if (!add_fdi_watch (inotify_fd, PACKAGE_DATA_DIR "/hal/fdi/preprobe"))
+			goto out;
+		if (!add_fdi_watch (inotify_fd, PACKAGE_SYSCONF_DIR "/hal/fdi/preprobe"))
+			goto out;
+	}
+
+	if (hal_fdi_source_information != NULL) {
+		if (!add_fdi_watch (inotify_fd, hal_fdi_source_information))
+			goto out;
+	} else {
+		if (!add_fdi_watch (inotify_fd, PACKAGE_DATA_DIR "/hal/fdi/information"))
+			goto out;
+		if (!add_fdi_watch (inotify_fd, PACKAGE_SYSCONF_DIR "/hal/fdi/information"))
+			goto out;
+	}
+
+	if (hal_fdi_source_policy != NULL) {
+		if (!add_fdi_watch (inotify_fd, hal_fdi_source_policy))
+			goto out;
+	} else {
+		if (!add_fdi_watch (inotify_fd, PACKAGE_DATA_DIR "/hal/fdi/policy"))
+			goto out;
+		if (!add_fdi_watch (inotify_fd, PACKAGE_SYSCONF_DIR "/hal/fdi/policy"))
+			goto out;
+	}
+
+	return;
+out:
+	DIE (("Error watching fdi files"));
+}
+
 void
 osspec_init (void)
 {
@@ -325,6 +445,9 @@ osspec_init (void)
 	 *Load various hardware id databases
 	 */
 	ids_init ();
+
+	/* watch fdi directories */
+	watch_fdi_files ();	
 }
 
 static void 
diff --git a/hald/osspec.h b/hald/osspec.h
index 3f2096a..66f9550 100644
--- a/hald/osspec.h
+++ b/hald/osspec.h
@@ -51,6 +51,9 @@ gboolean osspec_device_reprobe (HalDevic
 /* Called to refresh mount state for a device object of capability volume */
 void osspec_refresh_mount_state_for_block_device (HalDevice *d);
 
+/* Called by OS specific code to tell that the fdi cache is invalid */
+void osspec_fdi_cache_invalid (void);
+
 /** Called when the org.freedesktop.Hal service receives a messaged that the generic daemon 
  *  doesn't handle. Can be used for intercepting messages from kernel or core OS components.
  *


More information about the hal-commit mailing list