diff options
author | David Zeuthen <david@fubar.dk> | 2005-02-23 03:03:12 +0000 |
---|---|---|
committer | David Zeuthen <david@fubar.dk> | 2005-02-23 03:03:12 +0000 |
commit | e88994938b4290d6d81047e0cb714fb71850cb2a (patch) | |
tree | b5563ee7bcedc9a4afe8bcb0e2881fc53a513598 /hald/linux2/osspec.c | |
parent | 6175fda075fa91cab0e10c107aceaa4a01b514e9 (diff) |
Use kernel events layer instead of D_NOTIFY on /etc/mtab. Yay!
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.
Yikes, append to the right iterator; fixes segfault
Diffstat (limited to 'hald/linux2/osspec.c')
-rw-r--r-- | hald/linux2/osspec.c | 78 |
1 files changed, 18 insertions, 60 deletions
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*/); |