hal/hald/linux2 blockdev.c, 1.27, 1.28 blockdev.h, 1.5, 1.6 classdev.c, 1.35, 1.36 osspec.c, 1.37, 1.38

Kay Sievers kay at freedesktop.org
Thu Dec 8 11:03:04 PST 2005


Update of /cvs/hal/hal/hald/linux2
In directory gabe:/tmp/cvs-serv3879/hald/linux2

Modified Files:
	blockdev.c blockdev.h classdev.c osspec.c 
Log Message:
2005-12-08  Kay Sievers  <kay.sievers at vrfy.org>

        Kernel 2.6.15 will have a poll()'able /proc/mounts file, which
        tells us about mount tree changes. Kernel 2.6.16 will no longer
        have any netlink event regarding block devices mount/claim.
        We watch only /proc/mounts from now, remove all netlink listening
        and depend on kernel version 2.6.15.

        With every mount event, we update all known devices now, to the
        current state found in /proc/mounts. The device name in /proc/mounts
        is ignored, but the dev_t of the underlying block device is
        looked up to find the hal device. That way, /dev/root and rootdev
        will also be recognized and the current mount state becomes visible.

        * hald/linux2/blockdev.c: (blockdev_refresh_mount_state),
        (add_blockdev_probing_helper_done):
        * hald/linux2/blockdev.h:
        * hald/linux2/classdev.c:
        * hald/linux2/osspec.c: (hald_helper_data),
        (mount_tree_changed_event), (osspec_init):



Index: blockdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/blockdev.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- blockdev.c	2 Nov 2005 15:38:13 -0000	1.27
+++ blockdev.c	8 Dec 2005 19:03:02 -0000	1.28
@@ -160,104 +160,84 @@
 	hotplug_event_end (end_token);
 }
 
-static void 
-update_mount_point (HalDevice *d)
+void
+blockdev_refresh_mount_state (HalDevice *d)
 {
 	FILE *f;
 	struct mntent mnt;
 	struct mntent *mnte;
-	const char *device_file;
-	char buf[512];
-	unsigned int major, minor;
-	gboolean retry = FALSE;
+	char buf[1024];
+	unsigned int major;
+	unsigned int minor;
+	dev_t devt = makedev(0, 0);
+	GSList *volumes = NULL;
+	GSList *volume;
 
-	if ((device_file = hal_device_property_get_string (d, "block.device")) == NULL)
-		goto out;
+	/* open /proc/mounts */
+	g_snprintf (buf, sizeof (buf), "%s/mounts", get_hal_proc_path ());
+	if ((f = setmntent (buf, "r")) == NULL) {
+		HAL_ERROR (("Could not open /proc/mounts"));
+		return;
+	}
 
-	major = hal_device_property_get_int (d, "block.major");
-	minor = hal_device_property_get_int (d, "block.minor");
+	if (d)
+		volumes = g_slist_append (NULL, d);
+	else
+		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
 
-	HAL_INFO (("Update mount point for %s (device_file %s)", d->udi, device_file));
+	if (!volumes)
+		goto exit;
 
+	/* loop over /proc/mounts */
+	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
+		struct stat statbuf;
 
-	do {
-		snprintf (buf, sizeof (buf), "%s/mounts", get_hal_proc_path ());
-		if ((f = setmntent (buf, "r")) == NULL) {
-			HAL_ERROR (("Could not open /proc/mounts"));
-			goto out;
-		}
+		/* check the underlying device of the mount point */
+		if (stat (mnt.mnt_dir, &statbuf) != 0)
+			continue;
+		if (major(statbuf.st_dev) == 0)
+			continue;
 
-		while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
-			struct stat statbuf;
+		HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname, major(statbuf.st_dev), minor(statbuf.st_dev)));
+		/* match against all hal volumes */
+		for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
+			HalDevice *dev;
 
-			if (stat (mnt.mnt_fsname, &statbuf) != 0)
+			dev = HAL_DEVICE (volume->data);
+			major = hal_device_property_get_int (dev, "block.major");
+			if (major == 0)
 				continue;
+			minor = hal_device_property_get_int (dev, "block.minor");
+			devt = makedev(major, minor);
+			HAL_INFO (("  match %s (%i:%i)", hal_device_get_udi (dev), major, minor));
 
-			if ((major (statbuf.st_rdev) == major) && (minor (statbuf.st_rdev) == minor)) {
+			if (statbuf.st_dev == devt) {
+				/* found entry for this device in /proc/mounts */
 				device_property_atomic_update_begin ();
-				hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
-				hal_device_property_set_string (d, "volume.mount_point", mnt.mnt_dir);
+				hal_device_property_set_bool (dev, "volume.is_mounted", TRUE);
+				hal_device_property_set_string (dev, "volume.mount_point", mnt.mnt_dir);
 				device_property_atomic_update_end ();
-				HAL_INFO (("Setting mount point %s for %s", mnt.mnt_dir, device_file));
-				goto found;
+				HAL_INFO (("  set %s to be mounted at %s", hal_device_get_udi (dev), mnt.mnt_dir));
+				volumes = g_slist_delete_link (volumes, volume);
+				break;
 			}
 		}
-
-		/* to workaround http://lists.freedesktop.org/archives/hal/2005-October/003634.html 
-		 * If device is not in proc: sleep 0.3 seconds and retry _one time_ to check again.
-		 * 
-		 * NOTE: This workaround is for voluntary preemption kernel and should be removed if
-		 *       the problem is fixed in the kernel.
-		 */
-		if (retry) {
-			HAL_WARNING (("Could not find %s in %s/mounts, no second retry.", device_file, get_hal_proc_path ()));
-			retry = FALSE;
-		} else {
-			retry = TRUE;
-			usleep (300000);
-			HAL_WARNING (("Could not find %s in %s/mounts retry to find.", device_file, get_hal_proc_path ()));
-		}	
-	} while (retry);
-
-	device_property_atomic_update_begin ();
-	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
-	hal_device_property_set_string (d, "volume.mount_point", "");
-	device_property_atomic_update_end ();
-
-	HAL_INFO (("Clearing mount point for %s", device_file));
-
-found:		
-	endmntent (f);
-out:
-	;
-}
-
-void 
-blockdev_mount_status_changed (const gchar *sysfs_path, gboolean is_mounted)
-{
-	HalDevice *d;
-	HAL_INFO (("mount_status_changed for '%s', is_mounted=%d", sysfs_path, is_mounted));
-
-	if ((d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path)) == NULL)
-		goto error;
-
-	if (!hal_device_has_capability (d, "volume")) {
-		/* may have a fakevolume */
-		d = hal_device_store_match_key_value_string (hald_get_gdl (),
-							     "info.parent",
-							     d->udi);
-		if (d == NULL || !hal_device_has_capability (d, "volume"))
-			goto error;
 	}
 
-	HAL_INFO (("Applies to %s", d->udi));
-
-	update_mount_point (d);
-	return;
+	/* all remaining volumes are not mounted */
+	for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
+		HalDevice *dev;
 
-error:
-	HAL_INFO (("Couldn't find hal volume for %s", sysfs_path));
-	;
+		dev = HAL_DEVICE (volume->data);
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (dev, "volume.is_mounted", FALSE);
+		hal_device_property_set_string (dev, "volume.mount_point", "");
+		device_property_atomic_update_end ();
+		HAL_INFO (("set %s to unmounted", hal_device_get_udi (dev)));
+	}
+	g_slist_free (volumes);
+exit:
+	endmntent (f);
 }
 
 static void
@@ -330,13 +310,13 @@
 		hal_device_copy_property (d, "info.udi", d, "block.storage_device");
 	} else {
 		/* check for mount point */
-		update_mount_point (d);
+		blockdev_refresh_mount_state (d);
 	}
 
 	/* Merge properties from .fdi files */
 	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
 	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
-	
+
 	/* TODO: Merge persistent properties */
 
 	/* Run callouts */

Index: blockdev.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/blockdev.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- blockdev.h	2 Nov 2005 15:38:13 -0000	1.5
+++ blockdev.h	8 Dec 2005 19:03:02 -0000	1.6
@@ -38,6 +38,6 @@
 
 HotplugEvent *blockdev_generate_remove_hotplug_event (HalDevice *d);
 
-void blockdev_mount_status_changed (const gchar *sysfs_path, gboolean is_mounted);
+void blockdev_refresh_mount_state (HalDevice *d);
 
 #endif /* BLOCKDEV_H */

Index: classdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/classdev.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- classdev.c	2 Nov 2005 15:38:13 -0000	1.35
+++ classdev.c	8 Dec 2005 19:03:02 -0000	1.36
@@ -53,8 +53,6 @@
 #include <net/if_arp.h> /* for ARPHRD_... */
 #include <sys/socket.h>
 #include <linux/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 #include <net/if.h>
 
 #include <glib.h>

Index: osspec.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/osspec.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- osspec.c	5 Dec 2005 19:45:34 -0000	1.37
+++ osspec.c	8 Dec 2005 19:03:02 -0000	1.38
@@ -49,16 +49,11 @@
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
-#include <net/if_arp.h> /* for ARPHRD_... */
+#include <net/if_arp.h>
 #include <sys/socket.h>
 #include <linux/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
 
@@ -87,8 +82,8 @@
 
 #include "osspec_linux.h"
 
-char hal_sysfs_path [HAL_PATH_MAX];
-char hal_proc_path [HAL_PATH_MAX];
+static char *hal_sysfs_path;
+static char *hal_proc_path;
 
 const gchar *
 get_hal_sysfs_path (void)
@@ -300,7 +295,6 @@
 		g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path), "%s%s", 
 			    hal_sysfs_path, msg.sysfs_path);
 		g_strlcpy (hotplug_event->sysfs.device_file, msg.device_name, sizeof (hotplug_event->sysfs.device_file));
-		/* TODO: set wait_for_sysfs_path */
 		hotplug_event->sysfs.net_ifindex = msg.net_ifindex;
 
 		/* queue up and process */
@@ -317,7 +311,6 @@
 		g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path), "%s%s", 
 			    hal_sysfs_path, msg.sysfs_path);
 		g_strlcpy (hotplug_event->sysfs.device_file, msg.device_name, sizeof (hotplug_event->sysfs.device_file));
-		/* TODO: set wait_for_sysfs_path */
 		hotplug_event->sysfs.net_ifindex = msg.net_ifindex;
 
 		/* queue up and process */
@@ -329,120 +322,23 @@
 	return TRUE;
 }
 
-#define VALID_NLMSG(h, s) ((NLMSG_OK (h, s) && \
-                           s >= sizeof (struct nlmsghdr) && \
-                           s >= h->nlmsg_len))
-
 static gboolean
-netlink_detection_data_ready (GIOChannel *channel, GIOCondition cond,
-			   gpointer user_data)
+mount_tree_changed_event (GIOChannel *channel, GIOCondition cond,
+		    gpointer user_data)
 {
-	int fd;
-	int bytes_read;
-	struct sockaddr_nl nladdr;
-	socklen_t nladdrlen = sizeof(nladdr);
-	char buf[1024];
-
-	if (cond & ~(G_IO_IN | G_IO_PRI)) {
-		HAL_ERROR (("Error occurred on netlink socket"));
+	if (cond & ~G_IO_ERR)
 		return TRUE;
-	}
 
-	fd = g_io_channel_unix_get_fd (channel);
-
-	do {
-		errno = 0;
-		bytes_read = recvfrom (fd, buf, sizeof (buf),
-				   MSG_DONTWAIT,
-				   (struct sockaddr*)&nladdr, &nladdrlen);
-		if (nladdrlen != sizeof(nladdr)) {
-			HAL_ERROR(("Bad address size reading netlink socket"));
-			return TRUE;
-		}
-		if (nladdr.nl_pid) {
-			HAL_ERROR(("Spoofed packet received on netlink socket"));
-			return TRUE;
-		}
-
-		if (bytes_read < 0 && errno != EAGAIN) {
-			HAL_ERROR (("Error reading data off netlink socket"));
-			return TRUE;
-		} else if ( bytes_read < 0 ) {
-			return TRUE;
-		} else {
-			HAL_INFO (("bytes_read=%d buf='%s'", bytes_read, buf));
-		}
-
-		/* Handle event: "mount@/block/hde" */
-		if (g_str_has_prefix (buf, "mount")) {
-			gchar sysfs_path[HAL_PATH_MAX];
-			g_strlcpy (sysfs_path, get_hal_sysfs_path (), sizeof (sysfs_path));
-			g_strlcat (sysfs_path, ((char *) buf) + sizeof ("mount"), sizeof (sysfs_path));
-			blockdev_mount_status_changed (sysfs_path, TRUE);
-		}
-
-		/* Handle event: "umount@/block/hde" */
-		if (g_str_has_prefix (buf, "umount")) {
-			gchar sysfs_path[HAL_PATH_MAX];
-			g_strlcpy (sysfs_path, get_hal_sysfs_path (), sizeof (sysfs_path));
-			g_strlcat (sysfs_path, ((char *) buf) + sizeof ("umount"), sizeof (sysfs_path));
-			blockdev_mount_status_changed (sysfs_path, FALSE);
-		}
-
-	} while (bytes_read > 0 || errno == EINTR);
+	HAL_INFO (("/proc/mounts tells, that the mount has tree changed"));
+	blockdev_refresh_mount_state (NULL);
 
 	return TRUE;
 }
 
-static gboolean 
-hal_util_get_fs_mnt_path (const gchar *fs_type, gchar *mnt_path, gsize len)
-{
-	FILE *mnt;
-	struct mntent *mntent;
-	gboolean rc;
-	gsize dirlen;
-
-	rc = FALSE;
-	dirlen = 0;
-
-	if (fs_type == NULL || mnt_path == NULL || len == 0) {
-		HAL_ERROR (("Arguments not sane"));
-		return -1;
-	}
-
-	if ((mnt = setmntent ("/proc/mounts", "r")) == NULL) {
-		HAL_ERROR (("Error getting mount information"));
-		return -1;
-	}
-
-	while (rc == FALSE && dirlen == 0 && (mntent = getmntent(mnt)) != NULL) {
-		if (strcmp (mntent->mnt_type, fs_type) == 0) {
-			dirlen = strlen (mntent->mnt_dir);
-			if (dirlen <= (len - 1)) {
-				g_strlcpy (mnt_path, mntent->mnt_dir, len);
-				rc = TRUE;
-			} else {
-				HAL_ERROR (("Error - mount path too long"));
-				rc = FALSE;
-			}
-		}
-	}
-	endmntent (mnt);
-	
-	if (dirlen == 0 && rc == TRUE) {
-		HAL_ERROR (("Filesystem %s not found", fs_type));
-		rc = FALSE;
-	}
-
-	if ((!hal_util_remove_trailing_slash (mnt_path)))
-		rc = FALSE;
-	
-	return rc;
-}
-
 void
 osspec_init (void)
 {
+	gchar path[HAL_PATH_MAX];
 	int udev_socket;
 	int helper_socket;
 	struct sockaddr_un saddr;
@@ -450,9 +346,7 @@
 	GIOChannel *udev_channel;
 	GIOChannel *helper_channel;
 	const int on = 1;
-	static int netlink_fd = -1;
-	struct sockaddr_nl netlink_addr;
-	GIOChannel *netlink_channel;
+	GIOChannel *mounts_channel;
 
 	/*
 	 * setup socket for listening from messages from udev
@@ -505,51 +399,30 @@
 	g_io_channel_unref (helper_channel);
 
 	/*
-	 * get mount points for /proc and /sys
+	 * set mount points for /proc and /sys, possibly overridden for testing
 	 */
-	if (!hal_util_get_fs_mnt_path ("sysfs", hal_sysfs_path, sizeof (hal_sysfs_path))) {
-		HAL_ERROR (("Could not get sysfs mount point"));
-		goto error;
-	}
-	HAL_INFO (("sysfs mount point is '%s'", hal_sysfs_path));
-	if (!hal_util_get_fs_mnt_path ("proc", hal_proc_path, sizeof (hal_proc_path))) {
-		HAL_ERROR (("Could not get proc mount point"));
-		goto error;
-	}
-	HAL_INFO (("proc mount point is '%s'", hal_proc_path));
+	hal_sysfs_path = getenv ("SYSFS_PATH");
+	if (hal_sysfs_path == NULL)
+		hal_sysfs_path = "/sys";
+
+	hal_proc_path = getenv ("PROC_PATH");
+	if (hal_proc_path == NULL)
+		hal_proc_path = "/proc";
 
 	/*
-	 * hook up to netlink socket to receive events from the Kernel Events
-	 * Layer (available since 2.6.10) - TODO: Don't use the constant 15 but
-	 * rather the NETLINK_KOBJECT_UEVENT symbol
+	 * watch /proc/mounts for mount tree changes
+	 * kernel 2.6.15 vfs throws a POLLERR event for every change
 	 */
-	netlink_fd = socket (PF_NETLINK, SOCK_DGRAM, 15/*NETLINK_KOBJECT_UEVENT*/);
-
-	if (netlink_fd < 0) {
-		DIE (("Unable to create netlink socket"));
-	}
-
-	memset (&netlink_addr, 0, sizeof (netlink_addr));
-	netlink_addr.nl_family = AF_NETLINK;
-	netlink_addr.nl_pid = getpid ();
-	netlink_addr.nl_groups = 0xffffffff;//RTMGRP_LINK;//1 << 15 /*NETLINK_KOBJECT_UEVENT*/;
-
-	if (bind (netlink_fd, (struct sockaddr *) &netlink_addr, sizeof (netlink_addr)) < 0) {
-		DIE (("Unable to bind to netlink socket"));
-	}
-
-	netlink_channel = g_io_channel_unix_new (netlink_fd);
-
-	g_io_add_watch (netlink_channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_NVAL,
-			netlink_detection_data_ready, NULL);
+	g_snprintf (path, sizeof (path), "%s/mounts", get_hal_proc_path ());
+	mounts_channel = g_io_channel_new_file (path, "r", NULL);
+	if (mounts_channel == NULL)
+		DIE (("Unable to read /proc/mounts"));
+	g_io_add_watch (mounts_channel, G_IO_ERR, mount_tree_changed_event, NULL);
 
 	/*
 	 *Load various hardware id databases
 	 */
 	ids_init ();
-
-error:
-	;
 }
 
 static void 




More information about the hal-commit mailing list