diff options
Diffstat (limited to 'hald/linux')
-rw-r--r-- | hald/linux/block_class_device.c | 298 | ||||
-rw-r--r-- | hald/linux/bus_device.c | 25 | ||||
-rw-r--r-- | hald/linux/class_device.c | 55 | ||||
-rw-r--r-- | hald/linux/ide_bus_device.c | 22 | ||||
-rw-r--r-- | hald/linux/ide_host_bus_device.c | 10 |
5 files changed, 258 insertions, 152 deletions
diff --git a/hald/linux/block_class_device.c b/hald/linux/block_class_device.c index 42892c94..00099dc8 100644 --- a/hald/linux/block_class_device.c +++ b/hald/linux/block_class_device.c @@ -74,6 +74,8 @@ static void etc_mtab_process_all_block_devices (dbus_bool_t force); static char *block_class_compute_udi (HalDevice * d, int append_num); +static gboolean deferred_check_for_non_partition_media (gpointer data); + static void set_volume_id_values(HalDevice *d, struct volume_id *vid) @@ -211,7 +213,19 @@ block_class_visit (ClassDeviceHandler *self, /*hal_device_print (d);*/ - return d; + /* Now that a) hotplug happens in the right order; and b) the device + * from a hotplug event is completely added to the GDL before the + * next event is processed; the aysnc call above is actually + * synchronous so we can test immediately whether we want to + * proceed + */ + if (hal_device_store_match_key_value_string ( + hald_get_gdl (), + "linux.sysfs_path_device", + parent_sysfs_path) == NULL) + return NULL; + else + return d; } @@ -659,9 +673,14 @@ detect_media (HalDevice * d, dbus_bool_t force_poll) got_media = FALSE; device_file = hal_device_property_get_string (d, "block.device"); + if (device_file == NULL) return FALSE; + if (force_poll) { + HAL_INFO (("Forcing check for media check on device %s", device_file)); + } + if (is_cdrom) fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL); else @@ -1099,12 +1118,26 @@ block_class_pre_process (ClassDeviceHandler *self, hal_device_property_set_bool (d, "volume.is_disc", FALSE); hal_device_property_set_bool (d, "volume.is_mounted", FALSE); - vid = volume_id_open_node(device_file); - if (vid != NULL) { - if (volume_id_probe(vid, VOLUME_ID_ALL, 0) == 0) { - set_volume_id_values(d, vid); + /* only check for volume_id if we are allowed to poll, otherwise we may + * cause inifite loops of hotplug events, cf. broken ide-cs driver and + * broken zip drives. Merely accessing the top-level block device if it + * or any of it partitions are not mounted causes the loop. + */ + if (hal_device_property_get_bool (stordev, "storage.media_check_enabled")) { + vid = volume_id_open_node(device_file); + if (vid != NULL) { + if (volume_id_probe(vid, VOLUME_ID_ALL, 0) == 0) { + set_volume_id_values(d, vid); + } + volume_id_close(vid); } - volume_id_close(vid); + } else { + /* gee, so at least set volume.fstype vfat,msdos,auto so + * mount(1) doesn't screw up and causes hotplug events + * + * GRRRR!!! + */ + hal_device_property_set_string (d, "volume.fstype", "vfat,msdos,auto"); } return; @@ -1129,10 +1162,28 @@ block_class_pre_process (ClassDeviceHandler *self, "ide") == 0) { const char *ide_name; char *model; - const char *device_file; - struct drive_id *did; char *media; + + /* blacklist the broken ide-cs driver */ + if (physdev != NULL) { + size_t len; + char buf[256]; + const char *physdev_sysfs_path; + + snprintf (buf, 256, "%s/devices/ide", sysfs_mount_path); + len = strlen (buf); + + physdev_sysfs_path = hal_device_property_get_string (physdev, "linux.sysfs_path"); + + if (strncmp (physdev_sysfs_path, buf, len) == 0) { + hal_device_property_set_bool (stordev, "storage.media_check_enabled", FALSE); + } + + HAL_INFO (("Working around broken ide-cs driver for %s", physdev->udi)); + } + + ide_name = get_last_element (hal_device_property_get_string (d, "linux.sysfs_path")); @@ -1146,20 +1197,6 @@ block_class_pre_process (ClassDeviceHandler *self, model); } - device_file = hal_device_property_get_string (d, "block.device"); - did = drive_id_open_node(device_file); - if (drive_id_probe(did, DRIVE_ID_ATA) == 0) { - if (did->serial[0] != '\0') - hal_device_property_set_string (stordev, - "storage.serial", - did->serial); - if (did->firmware[0] != '\0') - hal_device_property_set_string (stordev, - "storage.firmware_version", - did->firmware); - } - drive_id_close(did); - /* According to the function proc_ide_read_media() in * drivers/ide/ide-proc.c in the Linux sources, media * can only assume "disk", "cdrom", "tape", "floppy", @@ -1198,9 +1235,33 @@ block_class_pre_process (ClassDeviceHandler *self, has_removable_media = TRUE; /* TODO: Someone test with tape drives! */ + } + } + + /* only check for drive_id if we are allowed to poll, otherwise we may + * cause inifite loops of hotplug events, cf. broken ide-cs driver and + * broken zip drives. Merely accessing the top-level block device if it + * or any of it partitions are not mounted causes the loop. + */ + if (hal_device_property_get_bool (stordev, "storage.media_check_enabled")) { + const char *device_file; + struct drive_id *did; + + device_file = hal_device_property_get_string (d, "block.device"); + did = drive_id_open_node(device_file); + if (drive_id_probe(did, DRIVE_ID_ATA) == 0) { + if (did->serial[0] != '\0') + hal_device_property_set_string (stordev, + "storage.serial", + did->serial); + if (did->firmware[0] != '\0') + hal_device_property_set_string (stordev, + "storage.firmware_version", + did->firmware); } - + drive_id_close(did); } + } else if (strcmp (hal_device_property_get_string (parent, "info.bus"), @@ -1367,6 +1428,7 @@ block_class_pre_process (ClassDeviceHandler *self, hal_device_property_get_bool ( stordev, "storage.no_partitions_hint")); + /* FINALLY, merge information derived from a .fdi file, from the * physical device that is backing this block device. * @@ -1384,21 +1446,21 @@ block_class_pre_process (ClassDeviceHandler *self, /* Merge storage.* from physdev to stordev */ hal_device_merge_with_rewrite (stordev, physdev, "storage.", "storage."); - + /* If there's a scsi device inbetween merge all - * storage.lun%d.* properties */ + * storage_lun%d.* properties */ if (scsidev != NULL) { int lun; char propname[64]; - + lun = hal_device_property_get_int ( scsidev, "scsi.lun"); /* See 6in1-card-reader.fdi for an example */ - + snprintf (propname, sizeof (propname), "storage_lun%d.", lun); - + hal_device_merge_with_rewrite (stordev, physdev, "storage.", propname); } @@ -1415,8 +1477,63 @@ block_class_in_gdl (ClassDeviceHandler *self, /* Check the mtab to see if the device is mounted */ etc_mtab_process_all_block_devices (TRUE); + + if (!hal_device_property_get_bool (d, "block.is_volume") && + !hal_device_property_get_bool (d, "storage.media_check_enabled")) { + /* Right, if we don't have media_check_enabled we don't really know + * if the storage device contains media without partition + * tables. This is because of the hotplug infinite loops if trying + * to access the top-level block device. + * + * (man, if only the kernel could tell us that it didn't find + * any partition tables!) + * + * We could try to setup a timer that fires in a few seconds to + * see whether we got any childs added and, if not, then resort + * to actually doing a detect_media on the top-level block device. + * + * This works on the ide-cs driver, but there are many other drivers + * it might not work on, so I've commented it out. Oh well. + */ + /*g_timeout_add (3000, deferred_check_for_non_partition_media, g_strdup(udi));*/ + } } +static gboolean +deferred_check_for_non_partition_media (gpointer data) +{ + gchar *stordev_udi = (gchar *) data; + HalDevice *d; + HalDevice *child; + + HAL_INFO (("Entering, udi %s", stordev_udi)); + + /* See if device is still there */ + d = hal_device_store_find (hald_get_gdl (), stordev_udi); + if (d == NULL) + goto out; + + /* See if we already got children (check both TDL and GDL) */ + child = hal_device_store_match_key_value_string (hald_get_gdl (), "info.parent", + stordev_udi); + if (child == NULL) + child = hal_device_store_match_key_value_string (hald_get_tdl (), "info.parent", + stordev_udi); + + if (child != NULL) + goto out; + + HAL_INFO (("Forcing check for media check on udi %s", stordev_udi)); + + /* no children so force this check */ + detect_media (d, TRUE); + +out: + g_free (stordev_udi); + return FALSE; +} + + static char * block_class_compute_udi (HalDevice * d, int append_num) { @@ -1708,10 +1825,6 @@ mtab_handle_storage (HalDevice *d) /* Search all mount points */ found_mount_point = FALSE; for (i = 0; i < num_mount_points; i++) { - char udi[256]; - const char *device_file; - struct volume_id *vid; - ClassAsyncData *cad; mp = &mount_points[i]; @@ -1724,102 +1837,15 @@ mtab_handle_storage (HalDevice *d) } /* is now mounted, and we didn't have a child.. */ - HAL_INFO (("%s now mounted at %s, " - "major:minor=%d:%d, " "fstype=%s, udi=%s", - mp->device, mp->mount_point, - mp->major, mp->minor, mp->fs_type, d->udi)); - - child = hal_device_new (); - hal_device_store_add (hald_get_tdl (), child); - g_object_unref (child); - - /* copy from parent */ - hal_device_merge (child, d); - - /* modify some properties */ - hal_device_property_set_string (child, "info.parent", d->udi); - hal_device_property_set_bool (child, "block.is_volume", TRUE); - hal_device_property_set_string (child, - "info.capabilities", - "block volume"); - hal_device_property_set_string (child, - "info.category", - "volume"); - hal_device_property_set_string (child, - "info.product", - "Volume"); - /* clear these otherwise we'll - * imposter the parent on hotplug - * remove - */ - hal_device_property_set_string (child, "linux.sysfs_path", ""); - hal_device_property_set_string (child, - "linux.sysfs_path_device", ""); - - /* set defaults */ - hal_device_property_set_string ( - child, "volume.label", ""); - hal_device_property_set_string ( - child, "volume.uuid", ""); - hal_device_property_set_string ( - child, "volume.fstype", mp->fs_type); - hal_device_property_set_string ( - child, "volume.mount_point", mp->mount_point); - hal_device_property_set_bool ( - child, "volume.is_mounted", TRUE); - hal_device_property_set_bool ( - child, "volume.is_disc", FALSE); - - /* set UDI as appropriate */ - strncpy (udi, hal_device_property_get_string ( - d, "info.udi"), 256); - strncat (udi, "-volume", 256); - hal_device_property_set_string (child, "info.udi", udi); - hal_device_set_udi (child, udi); - - device_file = hal_device_property_get_string (d, - "block.device"); - vid = volume_id_open_node(device_file); - if (vid != NULL) { - if (volume_id_probe(vid, VOLUME_ID_ALL, 0) == 0) - set_volume_id_values(d, vid); - volume_id_close(vid); - } + HAL_INFO (("%s now mounted at %s, fstype=%s, udi=%s", + mp->device, mp->mount_point, mp->fs_type, d->udi)); - cad = g_new0 (ClassAsyncData, 1); - cad->device = child; - cad->handler = &block_class_handler; - cad->merge_or_add = block_class_handler.merge_or_add; - - /* add new device */ - g_signal_connect ( - child, "callouts_finished", - G_CALLBACK (class_device_move_from_tdl_to_gdl), cad); - hal_callout_device (child, TRUE); + /* detect the media and do indeed force this check */ + detect_media (d, TRUE); return TRUE; } - /* No mount point found */ - if (!found_mount_point) { - if (child != NULL ) { - /* We had a child, but is no longer mounted, go - * remove the child */ - HAL_INFO (("%s not mounted anymore at %s, " - "major:minor=%d:%d, " - "fstype=%s, udi=%s", - mp->device, mp->mount_point, - mp->major, mp->minor, - mp->fs_type, d->udi)); - - g_signal_connect (child, "callouts_finished", - G_CALLBACK (volume_remove_from_gdl), NULL); - hal_callout_device (child, FALSE); - - return TRUE; - } - } - return TRUE; } @@ -1935,6 +1961,32 @@ mtab_handle_volume (HalDevice *d) DBUS_TYPE_STRING, device_mount_point, DBUS_TYPE_INVALID); + + /* Alrighty, we were unmounted and we are some media without + * partition tables and we don't like to be polled. So now + * the user could actually remove the media and insert some + * other media and we wouldn't notice. Ever. + * + * So, remove the hal device object to be on the safe side. + */ + if ( strcmp (hal_device_property_get_string (d, "block.device"), + hal_device_property_get_string (stor, "block.device")) == 0 && + !hal_device_property_get_bool (stor, "storage.media_check_enabled")) { + + HAL_INFO (("Removing hal device object %s since it was unmounted", d->udi)); + + /* remove device */ + g_signal_connect (d, "callouts_finished", + G_CALLBACK (volume_remove_from_gdl), NULL); + hal_callout_device (d, FALSE); + + /* allow to scan again */ + hal_device_property_set_bool (stor, "block.have_scanned", FALSE); + + g_free (device_mount_point); + return FALSE; + } + } g_free (device_mount_point); diff --git a/hald/linux/bus_device.c b/hald/linux/bus_device.c index de2f98f1..91c1fd0c 100644 --- a/hald/linux/bus_device.c +++ b/hald/linux/bus_device.c @@ -79,7 +79,9 @@ bus_device_accept (BusDeviceHandler *self, const char *path, * @param self Pointer to class members * @param path Sysfs-path for device * @param device libsysfs object for device - * @return A pointer to the HalDevice* object created + * @return A pointer to the HalDevice* object + * or NULL if the devices isn't going + * to be added anyway */ HalDevice * bus_device_visit (BusDeviceHandler *self, const char *path, @@ -130,9 +132,23 @@ bus_device_visit (BusDeviceHandler *self, const char *path, HAL_LINUX_HOTPLUG_TIMEOUT); } - free (parent_sysfs_path); - - return d; + /* Now that a) hotplug happens in the right order; and b) the device + * from a hotplug event is completely added to the GDL before the + * next event is processed; the aysnc call above is actually + * synchronous so we can test immediately whether we want to + * proceed + */ + if (hal_device_store_match_key_value_string ( + hald_get_gdl (), + "linux.sysfs_path_device", + parent_sysfs_path) == NULL) { + + free (parent_sysfs_path); + return NULL; + } else { + free (parent_sysfs_path); + return d; + } } @@ -142,7 +158,6 @@ bus_device_visit (BusDeviceHandler *self, const char *path, * * @param device The device being moved * @param user_data User data provided when connecting the signal - * */ static void bus_device_move_from_tdl_to_gdl (HalDevice *device, gpointer user_data) diff --git a/hald/linux/class_device.c b/hald/linux/class_device.c index 6a78f10b..7c870df9 100644 --- a/hald/linux/class_device.c +++ b/hald/linux/class_device.c @@ -103,11 +103,13 @@ class_device_visit (ClassDeviceHandler *self, const char *path, struct sysfs_class_device *class_device) { + ClassAsyncData *cad; HalDevice *d; char dev_file[SYSFS_PATH_MAX]; char dev_file_prop_name[SYSFS_PATH_MAX]; gboolean merge_or_add; struct sysfs_device *sysdevice; + char *what_to_find; sysdevice = sysfs_get_classdev_device (class_device); @@ -181,48 +183,57 @@ class_device_visit (ClassDeviceHandler *self, } } + cad = g_new0 (ClassAsyncData, 1); + cad->device = d; + cad->handler = self; + cad->merge_or_add = merge_or_add; + /* Now find the physical device; this happens asynchronously as it * might be added later. */ if (merge_or_add) { - ClassAsyncData *cad = g_new0 (ClassAsyncData, 1); - cad->device = d; - cad->handler = self; - cad->merge_or_add = merge_or_add; + what_to_find = sysdevice->path; /* find the sysdevice */ hal_device_store_match_key_value_string_async ( hald_get_gdl (), "linux.sysfs_path_device", - sysdevice->path, + what_to_find, class_device_got_sysdevice, cad, - HAL_LINUX_HOTPLUG_TIMEOUT); - } else { - char *parent_sysfs_path; - ClassAsyncData *cad = g_new0 (ClassAsyncData, 1); + HAL_LINUX_HOTPLUG_TIMEOUT); + } else { if (sysdevice != NULL) { - parent_sysfs_path = - get_parent_sysfs_path (sysdevice->path); + what_to_find = get_parent_sysfs_path (sysdevice->path); } else { - parent_sysfs_path = "(none)"; + what_to_find = "(none)"; } - cad->device = d; - cad->handler = self; - cad->merge_or_add = merge_or_add; - - /* find the parent */ + /* find the sysdevice */ hal_device_store_match_key_value_string_async ( hald_get_gdl (), "linux.sysfs_path_device", - parent_sysfs_path, + what_to_find, class_device_got_parent_device, cad, HAL_LINUX_HOTPLUG_TIMEOUT); } - if (!merge_or_add) - return d; - else + + if (!merge_or_add) { + /* Now that a) hotplug happens in the right order; and b) the device + * from a hotplug event is completely added to the GDL before the + * next event is processed; the aysnc call above is actually + * synchronous so we can test immediately whether we want to + * proceed + */ + if (hal_device_store_match_key_value_string ( + hald_get_gdl (), + "linux.sysfs_path_device", + what_to_find) == NULL) + return NULL; + else + return d; + + } else return NULL; } @@ -290,7 +301,7 @@ class_device_got_parent_device (HalDeviceStore *store, HalDevice *parent, if (parent == NULL) { HAL_WARNING (("No parent for class device at sysfs path %s", - d->udi)); + hal_device_property_get_string (d, "linux.sysfs_path"))); /* get rid of temporary device */ hal_device_store_remove (hald_get_tdl (), d); return; diff --git a/hald/linux/ide_bus_device.c b/hald/linux/ide_bus_device.c index f3912d18..c9e1fe1d 100644 --- a/hald/linux/ide_bus_device.c +++ b/hald/linux/ide_bus_device.c @@ -48,6 +48,24 @@ * @{ */ +static dbus_bool_t +ide_device_accept (BusDeviceHandler *self, const char *path, + struct sysfs_device *device) +{ + +/* Uncomment this to test that we can ignore a device + * (specifically, in this case, a PCMCIA card reader on a + * normal system + */ +/* + if (strcmp (device->path, "/sys/devices/ide2/2.0") == 0) + return FALSE; +*/ + + /* only care about given bus name */ + return strcmp (device->bus, self->sysfs_bus_name) == 0; +} + static char * ide_device_compute_udi (HalDevice *d, int append_num) @@ -94,13 +112,13 @@ BusDeviceHandler ide_bus_handler = { bus_device_init, /**< init function */ bus_device_shutdown, /**< shutdown function */ bus_device_tick, /**< timer function */ - bus_device_accept, /**< accept function */ + ide_device_accept, /**< accept function */ bus_device_visit, /**< visitor function */ bus_device_removed, /**< device is removed */ ide_device_compute_udi, /**< UDI computing function */ ide_device_pre_process, /**< add more properties */ bus_device_got_udi, /**< got UDI */ - bus_device_in_gdl, /**< in GDL */ + bus_device_in_gdl, /**< in GDL */ "ide", /**< sysfs bus name */ "ide" /**< namespace */ }; diff --git a/hald/linux/ide_host_bus_device.c b/hald/linux/ide_host_bus_device.c index 13a16d8d..cf966b37 100644 --- a/hald/linux/ide_host_bus_device.c +++ b/hald/linux/ide_host_bus_device.c @@ -54,11 +54,21 @@ ide_host_device_accept (BusDeviceHandler *self, const char *path, struct sysfs_device *device) { int ide_host_number; + char buf[256]; + size_t len; if (sscanf (device->bus_id, "ide%d", &ide_host_number) != 1) { return FALSE; } + /* Don't pickup toplevel ide_host objects */ + snprintf (buf, 256, "%s/devices/ide", sysfs_mount_path); + len = strlen (buf); + if (strncmp (buf, device->path, len) == 0) + return FALSE; + + + return TRUE; } |