67
67
if (hal_device_property_get_bool (d, "block.is_volume")) {
71
72
label = hal_device_property_get_string (d, "volume.label");
73
/* replace '/' to avoid trouble if the string get part of the UDI see fd.o #11401 */
74
volumelabel = g_strdup(label);
75
volumelabel = g_strdelimit (volumelabel, "/", '_');
72
77
uuid = hal_device_property_get_string (d, "volume.uuid");
74
79
if (uuid != NULL && strlen (uuid) > 0) {
75
80
hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
76
81
"/org/freedesktop/Hal/devices/volume_uuid_%s", uuid);
77
} else if (label != NULL && strlen (label) > 0) {
82
} else if (volumelabel != NULL && strlen (volumelabel) > 0) {
78
83
hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
79
"/org/freedesktop/Hal/devices/volume_label_%s", label);
84
"/org/freedesktop/Hal/devices/volume_label_%s", volumelabel);
80
85
} else if (hal_device_property_get_bool(d, "volume.is_disc") &&
81
86
hal_device_property_get_bool(d, "volume.disc.is_blank")) {
82
87
/* this should be a empty CD/DVD */
189
192
/* loop over /proc/mounts */
190
193
while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
191
194
struct stat statbuf;
192
gboolean use_device_name_for_match;
194
/*HAL_INFO ((" * /proc/mounts contain dev %s - type %s", mnt.mnt_fsname, mnt.mnt_type));*/
196
/* If this is a nfs mount (fstype == 'nfs') ignore the mount. Reason:
197
* 1. we don't list nfs devices in HAL
198
* 2. more problematic: stat on mountpoints with 'stale nfs handle' never come
199
* back and block complete HAL and all applications using HAL fail.
197
/* HAL_INFO ((" * /proc/mounts contain dev %s - type %s", mnt.mnt_fsname, mnt.mnt_type)); */
199
/* We don't handle nfs mounts in HAL and stat() on mountpoints,
200
* and we would block on 'stale nfs handle'.
201
202
if (strcmp(mnt.mnt_type, "nfs") == 0)
204
use_device_name_for_match = FALSE;
205
/* get major:minor of special device file */
206
if (stat (mnt.mnt_fsname, &statbuf) != 0) {
207
/* DING DING DING... device node may have been deleted by udev
208
* but device is still mounted and we haven't processed the uevent
209
* for that deletion from udev..
211
* So in this case... fall back to comparing on device names
212
* rather than pretending the device is not mounted as that's
213
* what will happen if we just skip this /proc/mounts entry.
215
* The reason it's nicer to compare on major:minor is that
216
* /proc/mounts is broken - it contains the *device name*
217
* passed to mount(2) which in some cases may be a symlink
218
* (on many distros it's common to see /proc/mounts contain
219
* /dev/root as the device for /). Sigh...
221
use_device_name_for_match = TRUE;
205
/* skip plain names, we look for device nodes */
206
if (mnt.mnt_fsname[0] != '/')
210
* We can't just stat() the mountpoint, because it breaks all sorts
211
* non-disk filesystems. So assume, that the names in /proc/mounts
212
* are existing device-files used to mount the filesystem.
214
devt = makedev(0, 0);
215
if (stat (mnt.mnt_fsname, &statbuf) == 0) {
216
/* not a device node */
223
217
if (major (statbuf.st_rdev) == 0)
220
/* found major/minor */
221
devt = statbuf.st_rdev;
223
/* The root filesystem may be mounted by a device name that doesn't
224
* exist in the real root, like /dev/root, which the kernel uses
225
* internally, when no initramfs image is used. For "/", it is safe
226
* to get the major/minor by stat()'ing the mount-point.
228
if (strcmp (mnt.mnt_dir, "/") == 0 && stat ("/", &statbuf) == 0)
229
devt = statbuf.st_dev;
231
/* DING DING DING... the device-node may not exist, or is
232
* already deleted, but the device may be still mounted.
234
* We will fall back to looking up the device-name, instead
235
* of using major/minor.
227
/*HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname, major (statbuf.st_rdev), minor (statbuf.st_rdev)));*/
228
/* match against all hal volumes */
239
/* HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname,
240
major (devt), minor (devt))); */
229
242
for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
231
244
gboolean is_match;
645
refresh_md_state (HalDevice *d);
648
md_check_sync_timeout (gpointer user_data)
651
char *sysfs_path = (char *) user_data;
653
HAL_INFO (("In md_check_sync_timeout for sysfs path %s", sysfs_path));
655
d = hal_device_store_match_key_value_string (hald_get_gdl (),
656
"storage.linux_raid.sysfs_path",
659
d = hal_device_store_match_key_value_string (hald_get_tdl (),
660
"storage.linux_raid.sysfs_path",
663
HAL_WARNING (("Cannot find md device with sysfs path '%s'", sysfs_path));
667
refresh_md_state (d);
675
refresh_md_state (HalDevice *d)
681
const char *sysfs_path;
685
sysfs_path = hal_device_property_get_string (d, "storage.linux_raid.sysfs_path");
686
if (sysfs_path == NULL) {
687
HAL_WARNING (("Cannot get sysfs_path for udi %s", hal_device_get_udi (d)));
691
HAL_INFO (("In refresh_md_state() for '%s'", sysfs_path));
693
sync_action = hal_util_get_string_from_file (sysfs_path, "md/sync_action");
694
if (sync_action == NULL) {
695
HAL_WARNING (("Cannot get sync_action for %s", sysfs_path));
698
if (strcmp (sync_action, "idle") == 0) {
699
hal_device_property_set_bool (d, "storage.linux_raid.is_syncing", FALSE);
700
hal_device_property_remove (d, "storage.linux_raid.sync.action");
701
hal_device_property_remove (d, "storage.linux_raid.sync.speed");
702
hal_device_property_remove (d, "storage.linux_raid.sync.progress");
707
hal_device_property_set_bool (d, "storage.linux_raid.is_syncing", TRUE);
709
hal_device_property_set_string (d, "storage.linux_raid.sync.action", sync_action);
711
if (!hal_util_get_int_from_file (sysfs_path, "md/sync_speed", &speed, 10)) {
712
HAL_WARNING (("Cannot get sync_speed for %s", sysfs_path));
714
hal_device_property_set_uint64 (d, "storage.linux_raid.sync.speed", speed);
718
if ((str_completed = hal_util_get_string_from_file (sysfs_path, "md/sync_completed")) == NULL) {
719
HAL_WARNING (("Cannot get sync_completed for %s", sysfs_path));
721
long long int sync_pos, sync_total;
723
if (sscanf (str_completed, "%lld / %lld", &sync_pos, &sync_total) != 2) {
724
HAL_WARNING (("Malformed sync_completed '%s'", str_completed));
726
double sync_progress;
727
sync_progress = ((double) sync_pos) / ((double) sync_total);
728
hal_device_property_set_double (d, "storage.linux_raid.sync.progress", sync_progress);
732
/* check again in two seconds */
733
g_timeout_add (2000, md_check_sync_timeout, g_strdup (sysfs_path));
736
if (!hal_util_get_int_from_file (sysfs_path, "md/raid_disks", &num_components, 0)) {
737
HAL_WARNING (("Cannot get number of RAID components"));
740
hal_device_property_set_int (d, "storage.linux_raid.num_components", num_components);
742
/* add all components */
743
for (n = 0; n < num_components; n++) {
747
HalDevice *slave_volume;
748
const char *slave_volume_stordev_udi;
749
HalDevice *slave_volume_stordev;
751
s = g_strdup_printf ("%s/md/rd%d", sysfs_path, n);
752
if (!g_file_test (s, G_FILE_TEST_IS_SYMLINK)) {
758
link = g_strdup_printf ("%s/md/rd%d/block", sysfs_path, n);
759
target = resolve_symlink (link);
760
if (target == NULL) {
761
HAL_WARNING (("Cannot resolve %s", link));
765
HAL_INFO (("link->target: '%s' -> '%s'", link, target));
767
slave_volume = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", target);
768
if (slave_volume == NULL) {
769
HAL_WARNING (("No volume for sysfs path %s", target));
776
slave_volume_stordev_udi = hal_device_property_get_string (slave_volume, "block.storage_device");
777
if (slave_volume_stordev_udi == NULL) {
778
HAL_WARNING (("No storage device for slave"));
783
slave_volume_stordev = hal_device_store_find (hald_get_gdl (), slave_volume_stordev_udi);
784
if (slave_volume_stordev == NULL) {
785
HAL_WARNING (("No storage device for slave"));
792
hal_device_property_strlist_add (d, "storage.linux_raid.components", hal_device_get_udi (slave_volume));
796
* - hotpluggability (is that a word?)
799
* Hmm.. every raid member (PV) get the array UUID. That's
800
* probably.. wrong. TODO: check with Kay.
807
hal_device_property_set_bool (
808
d, "storage.hotpluggable",
809
hal_device_property_get_bool (slave_volume_stordev, "storage.hotpluggable"));
812
uuid = hal_device_property_get_string (
813
slave_volume, "volume.uuid");
815
hal_device_property_set_string (
816
d, "storage.serial", uuid);
823
} /* for all components */
825
hal_device_property_set_int (d, "storage.linux_raid.num_components_active", n);
827
/* TODO: add more state here */
630
837
hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const gchar *device_file, gboolean is_partition,
631
838
HalDevice *parent, void *end_token)
1077
if (strcmp (udi_it, "/org/freedesktop/Hal/devices/computer") == 0) {
1079
physdev_udi = udi_it;
1084
hal_device_property_set_string (d, "storage.bus", "linux_raid");
1086
level = hal_util_get_string_from_file (sysfs_path_real, "md/level");
1089
hal_device_property_set_string (d, "storage.linux_raid.level", level);
1091
hal_device_property_set_string (d, "storage.linux_raid.sysfs_path", sysfs_path_real);
1093
hal_device_property_set_string (d, "storage.vendor", "Linux");
1094
if (strcmp (level, "linear") == 0) {
1095
model_name = g_strdup ("Software RAID (Linear)");
1096
} else if (strcmp (level, "raid0") == 0) {
1097
model_name = g_strdup ("Software RAID-0 (Stripe)");
1098
} else if (strcmp (level, "raid1") == 0) {
1099
model_name = g_strdup ("Software RAID-1 (Mirror)");
1100
} else if (strcmp (level, "raid5") == 0) {
1101
model_name = g_strdup ("Software RAID-5");
1103
model_name = g_strdup_printf ("Software RAID (%s)", level);
1105
hal_device_property_set_string (d, "storage.model", model_name);
1106
g_free (model_name);
1108
hal_util_set_string_from_file (
1109
d, "storage.firmware_version",
1110
sysfs_path_real, "md/metadata_version");
1112
hal_device_add_capability (d, "storage.linux_raid");
1114
if (!refresh_md_state (d))
1117
is_hotpluggable = hal_device_property_get_bool (
1118
d, "storage.hotpluggable");
859
1124
/* Check info.subsystem */
860
1125
if ((bus = hal_device_property_get_string (d_it, "info.subsystem")) != NULL) {
861
1126
if (strcmp (bus, "scsi") == 0) {
1404
1703
return hotplug_event;
1706
static GSList *md_devs = NULL;
1709
udev_get_device_file_for_sysfs_path (const char *sysfs_path)
1714
const char *argv[] = {"/usr/bin/udevinfo", "--root", "--query", "name", "--path", NULL, NULL};
1718
argv[5] = sysfs_path;
1722
if (!g_spawn_sync("/",
1726
NULL, /* child_setup */
1727
NULL, /* user_data */
1732
HAL_ERROR (("Error spawning udevinfo: %s", g_error->message));
1733
g_error_free (g_error);
1737
if (u_exit_status != 0) {
1738
HAL_ERROR (("udevinfo returned exit code %d", u_exit_status));
1745
HAL_INFO (("Got '%s'", ret));
1753
blockdev_process_mdstat (void)
1755
HotplugEvent *hotplug_event;
1756
GIOChannel *channel;
1757
GSList *read_md_devs;
1762
channel = get_mdstat_channel ();
1763
if (channel == NULL)
1766
if (g_io_channel_seek (channel, 0, G_SEEK_SET) != G_IO_ERROR_NONE) {
1767
HAL_ERROR (("Cannot seek in /proc/mdstat"));
1771
read_md_devs = NULL;
1776
if (g_io_channel_read_line (channel, &line, NULL, NULL, NULL) != G_IO_STATUS_NORMAL)
1779
if (sscanf (line, "md%d : ", &num) == 1) {
1781
sysfs_path = g_strdup_printf ("/sys/block/md%d", num);
1782
read_md_devs = g_slist_prepend (read_md_devs, sysfs_path);
1788
/* now compute the delta */
1791
for (i = read_md_devs; i != NULL; i = i->next) {
1792
gboolean should_add = TRUE;
1794
for (j = md_devs; j != NULL && should_add; j = j->next) {
1795
if (strcmp (i->data, j->data) == 0) {
1801
char *sysfs_path = i->data;
1807
device_file = udev_get_device_file_for_sysfs_path (sysfs_path);
1808
if (device_file == NULL) {
1809
if (num_tries <= 6) {
1811
num_ms = 10 * (1<<num_tries);
1812
HAL_INFO (("spinning %d ms waiting for device file for sysfs path %s",
1813
num_ms, sysfs_path));
1814
usleep (1000 * num_ms);
1818
HAL_ERROR (("Cannot get device file for sysfs path %s", sysfs_path));
1821
HAL_INFO (("Adding md device at '%s' ('%s')", sysfs_path, device_file));
1823
hotplug_event = g_new0 (HotplugEvent, 1);
1824
hotplug_event->action = HOTPLUG_ACTION_ADD;
1825
hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
1826
g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
1827
g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
1828
g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
1829
hotplug_event->sysfs.net_ifindex = -1;
1830
hotplug_event_enqueue (hotplug_event);
1832
md_devs = g_slist_prepend (md_devs, g_strdup (sysfs_path));
1834
g_free (device_file);
1840
/* remove devices */
1841
for (i = md_devs; i != NULL; i = k) {
1842
gboolean should_remove = TRUE;
1846
for (j = read_md_devs; j != NULL && should_remove; j = j->next) {
1847
if (strcmp (i->data, j->data) == 0) {
1848
should_remove = FALSE;
1852
if (should_remove) {
1853
char *sysfs_path = i->data;
1859
device_file = udev_get_device_file_for_sysfs_path (sysfs_path);
1860
if (device_file == NULL) {
1861
if (num_tries <= 6) {
1863
num_ms = 10 * (1<<num_tries);
1864
HAL_INFO (("spinning %d ms waiting for device file for sysfs path %s",
1865
num_ms, sysfs_path));
1866
usleep (1000 * num_ms);
1870
HAL_ERROR (("Cannot get device file for sysfs path %s", sysfs_path));
1874
HAL_INFO (("Removing md device at '%s' ('%s')", sysfs_path, device_file));
1876
hotplug_event = g_new0 (HotplugEvent, 1);
1877
hotplug_event->action = HOTPLUG_ACTION_REMOVE;
1878
hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
1879
g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
1880
g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
1881
g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
1882
hotplug_event->sysfs.net_ifindex = -1;
1883
hotplug_event_enqueue (hotplug_event);
1885
md_devs = g_slist_remove_link (md_devs, i);
1889
g_free (device_file);
1895
g_slist_foreach (read_md_devs, (GFunc) g_free, NULL);
1896
g_slist_free (read_md_devs);
1898
/* finally, refresh all md devices */
1899
for (i = md_devs; i != NULL; i = i->next) {
1900
char *sysfs_path = i->data;
1903
d = hal_device_store_match_key_value_string (hald_get_gdl (),
1904
"storage.linux_raid.sysfs_path",
1907
d = hal_device_store_match_key_value_string (hald_get_tdl (),
1908
"storage.linux_raid.sysfs_path",
1911
refresh_md_state (d);
1915
hotplug_event_process_queue ();