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