[lvm-devel] LVM2/lib/device device.c

snitzer at sourceware.org snitzer at sourceware.org
Sat Aug 1 17:09:48 UTC 2009


CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	snitzer at sourceware.org	2009-08-01 17:09:48

Modified files:
	lib/device     : device.c 

Log message:
	Improve ability to lookup primary device associated with a partition
	
	Improve lib/device/device.c:_primary_dev()'s ability to look up the
	primary device associated with all partitions; including blkext
	(e.g. partitions directly on MD).  The same will also work for obscure
	sysfs paths; e.g.: paths with mangled names like the HP cciss driver
	uses: /sys/block/cciss!c0d0/cciss!c0d0p1/
	
	Signed-off-by: Mike Snitzer <snitzer at redhat.com>

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/device.c.diff?cvsroot=lvm2&r1=1.29&r2=1.30

--- LVM2/lib/device/device.c	2009/08/01 17:08:44	1.29
+++ LVM2/lib/device/device.c	2009/08/01 17:09:48	1.30
@@ -13,6 +13,7 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <libgen.h> /* dirname, basename */
 #include "lib.h"
 #include "lvm-types.h"
 #include "device.h"
@@ -289,21 +290,71 @@
 			struct device *dev, dev_t *result)
 {
 	char path[PATH_MAX+1];
+	char temp_path[PATH_MAX+1];
+	char buffer[64];
 	struct stat info;
+	FILE *fp;
+	uint32_t pri_maj, pri_min;
+	int ret = 0;
 
 	/* check if dev is a partition */
 	if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
 			sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
 		log_error("dm_snprintf partition failed");
-		return 0;
+		return ret;
 	}
 
 	if (stat(path, &info) < 0)
-		return 0;
+		return ret;
 
-	*result = dev->dev -
-		(MINOR(dev->dev) % max_partitions(MAJOR(dev->dev)));
-	return 1;
+	/*
+	 * extract parent's path from the partition's symlink, e.g.:
+	 * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
+	 * - dirname ../../block/md0/md0p1 = ../../block/md0
+	 * - basename ../../block/md0/md0  = md0
+	 * Parent's 'dev' sysfs attribute  = /sys/block/md0/dev
+	 */
+	if (readlink(dirname(path), temp_path, PATH_MAX) < 0) {
+		log_sys_error("readlink", path);
+		return ret;
+	}
+
+	if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
+			sysfs_dir, basename(dirname(temp_path))) < 0) {
+		log_error("dm_snprintf dev failed");
+		return ret;
+	}
+
+	/* finally, parse 'dev' attribute and create corresponding dev_t */
+	if (stat(path, &info) < 0) {
+		log_error("sysfs file %s does not exist", path);
+		return ret;
+	}
+
+	fp = fopen(path, "r");
+	if (!fp) {
+		log_sys_error("fopen", path);
+		return ret;
+	}
+
+	if (!fgets(buffer, sizeof(buffer), fp)) {
+		log_sys_error("fgets", path);
+		goto out;
+	}
+
+	if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
+		log_error("sysfs file %s not in expected MAJ:MIN format: %s",
+			  path, buffer);
+		goto out;
+	}
+	*result = MKDEV(pri_maj, pri_min);
+	ret = 1;
+
+out:
+	if (fclose(fp))
+		log_sys_error("fclose", path);
+
+	return ret;
 }
 
 static unsigned long _dev_topology_attribute(const char *attribute,




More information about the lvm-devel mailing list