diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | hald/hald_dbus.c | 7 | ||||
-rw-r--r-- | hald/linux2/blockdev.c | 48 | ||||
-rw-r--r-- | hald/linux2/blockdev.h | 2 | ||||
-rw-r--r-- | hald/linux2/osspec.c | 78 |
5 files changed, 69 insertions, 80 deletions
@@ -1,5 +1,19 @@ 2005-02-22 David Zeuthen <davidz@redhat.com> + * hald/linux2/osspec.c: Use kernel events layer instead of D_NOTIFY + on /etc/mtab. Yay! + + * hald/linux2/blockdev.c (update_mount_point): Use /proc/mounts as + we're now using the kernel events layer to get mount/umount signals + rather than waiting for /etc/mtab to be changed. Otherwise we've + would have a race with mount(1). Add some usable debug information. + (blockdev_mount_status_changed): Renamed from blockdev_mtab_changed. + + * hald/hald_dbus.c (device_send_signal_property_modified): Yikes, + append to the right iterator; fixes segfault + +2005-02-22 David Zeuthen <davidz@redhat.com> + * libhal/libhal.c: Patch from John (J5) Palmieri <johnp@redhat.com>. Most libhal methods now require an additional DBusError pointer to be passed into the method. Sometimes errors diff --git a/hald/hald_dbus.c b/hald/hald_dbus.c index 875f6ca3..be29ce91 100644 --- a/hald/hald_dbus.c +++ b/hald/hald_dbus.c @@ -2000,14 +2000,13 @@ device_send_signal_property_modified (HalDevice *device, const char *key, NULL, &iter_struct); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &removed); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &added); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &removed); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &added); dbus_message_iter_close_container (&iter_array, &iter_struct); dbus_message_iter_close_container (&iter, &iter_array); - if (!dbus_connection_send (dbus_connection, message, NULL)) DIE (("error broadcasting message")); diff --git a/hald/linux2/blockdev.c b/hald/linux2/blockdev.c index 65d911c8..91a64fdf 100644 --- a/hald/linux2/blockdev.c +++ b/hald/linux2/blockdev.c @@ -161,21 +161,26 @@ update_mount_point (HalDevice *d) struct mntent *mnte; const char *device_file; char buf[512]; - + if ((device_file = hal_device_property_get_string (d, "block.device")) == NULL) goto out; - - if ((f = setmntent ("/etc/mtab", "r")) == NULL) { - HAL_ERROR (("Could not open /etc/mtab")); + + HAL_INFO (("Update mount point for %s (device_file %s)", d->udi, device_file)); + + 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; } - + + /* TODO: should use major:minor numbers to catch /dev/root */ while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) { if (strcmp (mnt.mnt_fsname, device_file) == 0) { 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); device_property_atomic_update_end (); + HAL_INFO (("Setting mount point %s for %s", mnt.mnt_dir, device_file)); goto found; } } @@ -185,6 +190,8 @@ update_mount_point (HalDevice *d) 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: @@ -192,20 +199,31 @@ out: } void -blockdev_mtab_changed (void) +blockdev_mount_status_changed (const gchar *sysfs_path, gboolean is_mounted) { - GSList *i; - GSList *volumes; + HalDevice *d; + HAL_INFO (("mount_status_changed for '%s', is_mounted=%d", sysfs_path, is_mounted)); - volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), - "volume.fsusage", - "filesystem"); - for (i = volumes; i != NULL; i = g_slist_next (i)) { - HalDevice *d; + if ((d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path)) == NULL) + goto error; - d = HAL_DEVICE (i->data); - update_mount_point (d); + 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; + +error: + HAL_INFO (("Couldn't find hal volume for %s", d->udi)); + ; } static void diff --git a/hald/linux2/blockdev.h b/hald/linux2/blockdev.h index 80244523..8a8876c3 100644 --- a/hald/linux2/blockdev.h +++ b/hald/linux2/blockdev.h @@ -38,6 +38,6 @@ HotplugEvent *blockdev_generate_add_hotplug_event (HalDevice *d); HotplugEvent *blockdev_generate_remove_hotplug_event (HalDevice *d); -void blockdev_mtab_changed (void); +void blockdev_mount_status_changed (const gchar *sysfs_path, gboolean is_mounted); #endif /* BLOCKDEV_H */ diff --git a/hald/linux2/osspec.c b/hald/linux2/osspec.c index 4d76aa4f..23dea3db 100644 --- a/hald/linux2/osspec.c +++ b/hald/linux2/osspec.c @@ -194,46 +194,6 @@ out: return TRUE; } -static int sigio_unix_signal_pipe_fds[2]; -static GIOChannel *sigio_iochn; - -static void -sigio_handler (int sig) -{ - static char marker[1] = {'S'}; - - /* write a 'S' character to the other end to tell about - * the signal. Note that 'the other end' is a GIOChannel thingy - * that is only called from the mainloop - thus this is how we - * defer this since UNIX signal handlers are evil - * - * Oh, and write(2) is indeed reentrant */ - write (sigio_unix_signal_pipe_fds[1], marker, 1); -} - -static gboolean -sigio_iochn_data (GIOChannel *source, GIOCondition condition, gpointer user_data) -{ - GError *err = NULL; - gchar data[1]; - gsize bytes_read; - - /* Empty the pipe */ - if (G_IO_STATUS_NORMAL != g_io_channel_read_chars (source, data, 1, &bytes_read, &err)) { - HAL_ERROR (("Error emptying callout notify pipe: %s", err->message)); - g_error_free (err); - goto out; - } - - /* TODO: check mtime on /etc/mtab file */ - HAL_INFO (("/etc/mtab changed")); - blockdev_mtab_changed (); - -out: - return TRUE; -} - - #define VALID_NLMSG(h, s) ((NLMSG_OK (h, s) && \ s >= sizeof (struct nlmsghdr) && \ s >= h->nlmsg_len)) @@ -249,8 +209,6 @@ netlink_detection_data_ready (GIOChannel *channel, GIOCondition cond, socklen_t nladdrlen = sizeof(nladdr); char buf[1024]; - HAL_INFO (("data!", buf)); - if (cond & ~(G_IO_IN | G_IO_PRI)) { HAL_ERROR (("Error occurred on netlink socket")); return TRUE; @@ -286,19 +244,33 @@ netlink_detection_data_ready (GIOChannel *channel, GIOCondition cond, HAL_INFO (("total_read=%d buf='%s'", total_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); + } + return TRUE; } void osspec_init (void) { - int etcfd; int socketfd; struct sockaddr_un saddr; socklen_t addrlen; GIOChannel *channel; const int on = 1; - guint sigio_iochn_listener_source_id; static int netlink_fd = -1; struct sockaddr_nl netlink_addr; GIOChannel *netlink_channel; @@ -326,7 +298,6 @@ osspec_init (void) g_io_add_watch (channel, G_IO_IN, hald_helper_data, NULL); g_io_channel_unref (channel); - /* Get mount points for /proc and /sys */ if (!hal_util_get_fs_mnt_path ("sysfs", hal_sysfs_path, sizeof (hal_sysfs_path))) { HAL_ERROR (("Could not get sysfs mount point")); @@ -339,22 +310,9 @@ osspec_init (void) } HAL_INFO (("proc mount point is '%s'", hal_proc_path)); - /* start watching /etc so we know when mtab is updated */ - etcfd = open ("/etc", O_RDONLY); - if (etcfd < 0) - DIE (("Could not open /etc")); - fcntl (etcfd, F_NOTIFY, DN_MODIFY | DN_MULTISHOT); - - if (pipe (sigio_unix_signal_pipe_fds) != 0) { - DIE (("Could not setup pipe: %s", strerror (errno))); - } - if ((sigio_iochn = g_io_channel_unix_new (sigio_unix_signal_pipe_fds[0])) == NULL) - DIE (("Could not create GIOChannel")); - sigio_iochn_listener_source_id = g_io_add_watch (sigio_iochn, G_IO_IN, sigio_iochn_data, NULL); - signal (SIGIO, sigio_handler); - /* 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 + * Layer (available since 2.6.10) - TODO: Don't use the constant 15 but + * rather the NETLINK_KOBJECT_UEVENT symbol */ netlink_fd = socket (PF_NETLINK, SOCK_DGRAM, 15/*NETLINK_KOBJECT_UEVENT*/); |