First try at improving hal's device mapper support
Sjoerd Simons
sjoerd at luon.net
Wed Dec 22 12:22:14 PST 2004
Hi,
I've been playing around to get hal to recognize dm devices in a somewhat
nicer way. For this i've patched device mapper itself to put links in sysfs
to the backend device.
So for example the encrypted partition on my usbstick looks like this:
$ ls -l /sys/block/dm-0
-r--r--r-- 1 root root 4096 Dec 22 19:01 dev
lrwxrwxrwx 1 root root 0 Dec 22 19:01 device0 -> ../../block/sdb/sdb2/
-r--r--r-- 1 root root 4096 Dec 22 19:01 range
-r--r--r-- 1 root root 4096 Dec 22 19:01 removable
-r--r--r-- 1 root root 4096 Dec 22 19:01 size
-r--r--r-- 1 root root 4096 Dec 22 19:01 stat
And when merging various partitions on it together
$ ls -l /sys/block/dm-1
-r--r--r-- 1 root root 4096 Dec 22 20:30 dev
lrwxrwxrwx 1 root root 0 Dec 22 20:30 device0 -> ../../block/sdb/sdb4/
lrwxrwxrwx 1 root root 0 Dec 22 20:30 device1 -> ../../block/sdb/sdb3/
lrwxrwxrwx 1 root root 0 Dec 22 20:30 device2 -> ../../block/sdb/sdb2/
lrwxrwxrwx 1 root root 0 Dec 22 20:30 device3 -> ../../block/sdb/sdb1/
-r--r--r-- 1 root root 4096 Dec 22 20:30 range
-r--r--r-- 1 root root 4096 Dec 22 20:30 removable
-r--r--r-- 1 root root 4096 Dec 22 20:30 size
-r--r--r-- 1 root root 4096 Dec 22 20:30 stat
So we have most of the needed info for hal. The only that is really still
needed is the name of the dm device (as tools need that to configure it).
Now for the bad things. As can be seen in the second example, a dm device can
have multiple backing device. But there is no way to express multiple parents
in hal.
Furthermore when setting up a dm device, first the device itself is created.
Which causes the hotplug event. After that a mapping from the dm device to
the target device(s) is created (and thus the deviceX symlinks), but that
doesn't generate any events. And also the mapping can change during the dm
device's lifetime (again without kernel events). Maybe this would fall inside
the kernel-userspace event stuff that has been added for kernel 2.6.10? Any
kernel people around that know about that :)
Attached are a patch for the kernel to create the symlinks in sysfs and one
for hal to use that to get the parent. The hal patch sleeps for 2 seconds
which i long enough to have the mapping setup when using cryptsetup, but
that's ofcourse not the right way to do it(tm).
Sjoerd
--
After years of research, scientists recently reported that there is,
indeed, arroz in Spanish Harlem.
-------------- next part --------------
--- linux-2.6.9.vanilla/drivers/md/dm.c 2004-10-18 23:54:55.000000000 +0200
+++ linux-2.6.9/drivers/md/dm.c 2004-12-22 18:06:52.000000000 +0100
@@ -827,6 +827,9 @@
{
request_queue_t *q = md->queue;
sector_t size;
+ struct dm_dev *dd;
+ int i = 0;
+ char name[] = "deviceXXX";
size = dm_table_get_size(t);
__set_size(md->disk, size);
@@ -837,6 +840,16 @@
md->map = t;
write_unlock(&md->map_lock);
+ list_for_each_entry(dd, dm_table_get_devices(t), list) {
+ snprintf(name, sizeof(name), "device%d", i);
+ if (dd->bdev->bd_part == NULL) {
+ /* whole disk */
+ sysfs_create_link(&(md->disk->kobj), &(dd->bdev->bd_disk->kobj), name);
+ } else {
+ sysfs_create_link(&(md->disk->kobj), &(dd->bdev->bd_part->kobj), name);
+ }
+ i++;
+ }
dm_table_get(t);
dm_table_event_callback(md->map, event_callback, md);
dm_table_set_restrictions(t, q);
@@ -846,11 +859,19 @@
static void __unbind(struct mapped_device *md)
{
struct dm_table *map = md->map;
+ struct dm_dev *dd;
+ char name[] = "deviceXXX";
+ int i = 0;
if (!map)
return;
dm_table_event_callback(map, NULL, NULL);
+ list_for_each_entry(dd, dm_table_get_devices(map), list) {
+ snprintf(name, sizeof(name), "device%d", i);
+ sysfs_remove_link(&(md->disk->kobj), name);
+ i++;
+ }
write_lock(&md->map_lock);
md->map = NULL;
write_unlock(&md->map_lock);
@@ -923,6 +944,7 @@
int dm_swap_table(struct mapped_device *md, struct dm_table *table)
{
int r;
+ struct dm_dev *dd;
down_write(&md->lock);
-------------- next part --------------
Index: hald/linux/block_class_device.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/block_class_device.c,v
retrieving revision 1.88
diff -u -r1.88 block_class_device.c
--- hald/linux/block_class_device.c 16 Dec 2004 16:13:08 -0000 1.88
+++ hald/linux/block_class_device.c 22 Dec 2004 20:15:25 -0000
@@ -201,6 +201,25 @@
return FALSE;
}
+static HalDevice *
+dm_device_get_parent(struct sysfs_class_device *class_device) {
+ struct sysfs_directory *dir;
+ struct sysfs_link *link;
+ HalDevice *result = NULL;
+
+ /* The way dm works is that first the device is created and after that the
+ * table is loaded.. So we wait here and hope the table is loaded within
+ * two seconds */
+ sleep(2);
+ dir = sysfs_open_directory(class_device->path);
+ link = sysfs_get_directory_link(dir, "device0");
+ if (link != NULL) {
+ result = hal_device_store_match_key_value_string(hald_get_gdl(),
+ "linux.sysfs_path", link->target);
+ }
+ sysfs_close_directory(dir);
+ return result;
+}
static HalDevice *
block_class_visit (ClassDeviceHandler *self,
@@ -231,6 +250,9 @@
if (sysdevice == NULL) {
parent = find_closest_ancestor (path);
+ if (parent == NULL) {
+ parent = dm_device_get_parent(class_device);
+ }
hal_device_property_set_bool (d, "block.is_volume", TRUE);
} else {
parent = hal_device_store_match_key_value_string (hald_get_gdl (),
@@ -239,6 +261,18 @@
hal_device_property_set_bool (d, "block.is_volume", FALSE);
}
+ /* Find parent; this can happen synchronously as our parent is
+ * sure to be added before us (we probe devices in the right order
+ * and we reorder hotplug events)
+ */
+ if (parent == NULL) {
+ HAL_WARNING(("Couldn't find parent device for %s", path));
+ hal_device_store_remove (hald_get_tdl (), d);
+ d = NULL;
+ goto out;
+ }
+
+
/* temporary property used for _udev_event() */
hal_device_property_set_string (d, ".target_dev", "block.device");
hal_device_property_set_string (d, ".udev.class_name", "block");
@@ -260,96 +294,6 @@
self->udev_event (self, d, dev_file);
}
- cad = g_new0 (ClassAsyncData, 1);
- cad->device = d;
- cad->handler = self;
-
- /* Find parent; this can happen synchronously as our parent is
- * sure to be added before us (we probe devices in the right order
- * and we reorder hotplug events)
- */
- if (parent == NULL) {
- unsigned int major;
- unsigned int minor;
- const char *last_elem;
-
- major = 253; /* TODO: replace by devmapper constant */
-
- last_elem = get_last_element (path);
- if (sscanf (last_elem, "dm-%d", &minor) == 1) {
- GDir *dir;
-
-
- HAL_INFO (("path=%s is a device mapper dev, major/minor=%d/%d", path, major, minor));
-
- /* Ugly hack to see if we're a sesame crypto device; should
- * be replaced by some ioctl or libdevmapper stuff by where
- * we can ask about the name for /dev/dm-0; as e.g. given by
- * 'dmsetup info'
- *
- * Our assumption is that sesame-setup have invoked
- * dmsetup; e.g. the naming convention is
- *
- * sesame_crypto_<sesame_uuid>
- *
- * where <sesame_uuid> is the UUID encoded in the sesame
- * metadata.
- */
-
- /* Ugly sleep of 0.5s here as well to allow dmsetup to do the mknod */
- usleep (1000 * 1000 * 5 / 10);
-
- if ((dir = g_dir_open ("/dev/mapper", 0, NULL)) != NULL) {
- const gchar *f;
- char devpath[256];
- struct stat statbuf;
-
- while ((f = g_dir_read_name (dir)) != NULL) {
- char sesame_prefix[] = "sesame_crypto_";
- const char *sesame_uuid;
-
- HAL_INFO (("looking at /dev/mapper/%s", f));
-
- g_snprintf (devpath, sizeof (devpath), "/dev/mapper/%s", f);
- if (stat (devpath, &statbuf) == 0) {
- if (S_ISBLK (statbuf.st_mode) &&
- MAJOR(statbuf.st_rdev) == major &&
- MINOR(statbuf.st_rdev) == minor &&
- strncmp (f, sesame_prefix, sizeof (sesame_prefix) - 1) == 0) {
- HalDevice *backing_volume;
-
- sesame_uuid = f + sizeof (sesame_prefix) - 1;
- HAL_INFO (("found %s; sesame_uuid='%s'!",
- devpath, sesame_uuid));
-
- backing_volume = hal_device_store_match_key_value_string (
- hald_get_gdl (),
- "volume.crypto_sesame.uuid",
- sesame_uuid);
- if (backing_volume != NULL) {
- const char *backing_volume_stordev_udi;
- backing_volume_stordev_udi = hal_device_property_get_string (backing_volume, "block.storage_device");
- if (backing_volume_stordev_udi != NULL) {
- parent = hal_device_store_find (hald_get_gdl (), backing_volume_stordev_udi);
- if (parent != NULL) {
- hal_device_property_set_string (d, "volume.crypto_sesame.clear.backing_volume", backing_volume->udi);
- goto got_parent;
- }
- }
- }
-
- }
- }
- }
- g_dir_close (dir);
- }
- }
-
- hal_device_store_remove (hald_get_tdl (), d);
- d = NULL;
- goto out;
- }
-
/* Never add e.g. /dev/hdd4 as child of /dev/hdd if /dev/hdd is without partitions (e.g. zip disks) */
if (hal_device_has_property (parent, "storage.no_partitions_hint")) {
if (hal_device_property_get_bool (parent, "storage.no_partitions_hint")) {
@@ -358,8 +302,9 @@
goto out;
}
}
-
-got_parent:
+ cad = g_new0 (ClassAsyncData, 1);
+ cad->device = d;
+ cad->handler = self;
class_device_got_parent_device (hald_get_tdl (), parent, cad);
-------------- next part --------------
_______________________________________________
hal mailing list
hal at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/hal
More information about the Hal
mailing list