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