summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--hald/hald_dbus.c7
-rw-r--r--hald/linux2/blockdev.c48
-rw-r--r--hald/linux2/blockdev.h2
-rw-r--r--hald/linux2/osspec.c78
5 files changed, 69 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 994be8eb..52b666c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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*/);