Hi,

The root problem of my prior patch was due to the sketchy probing of
partitions in linux, using /proc/partitions and attempting to understand
the names.  Linux 2.6 now includes /sys/block, which contains all block
devices on the system (and their partitions underneath that).  The
attached patch makes parted attempt to probe devices via /sys/block, and
fall back to /proc/partitions if /sys isn't mounted.

This is against some cvs version of parted, but applies to 1.6.25.1.
There are probably additional entries that should be ignored (currently
I've got just dm-*, loop*, and ram*).  Those can be added as necessary.

Partitions can also be probed via /sys/block as well, if it's desirable
to do that instead of reading the partition table from the block device;
I didn't bother to write any code to do it, since I didn't see the
necessity.
------------------------------------------------------------
revno: 3
committer: Andres Salomon <[EMAIL PROTECTED]>
timestamp: Tue 2005-11-08 19:24:51 -0500
message:
  Instead of using block devices from /proc/partitions (which tends to be
  unreliable), if /sys/block is available (>= linux 2.6.x), use that instead.
  We're guaranteed that all block devices within this directory are complete
  devices, not just partitions.
  
=== modified file 'libparted/linux.c'
--- libparted/linux.c
+++ libparted/linux.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <syscall.h>
 #include <unistd.h>
+#include <dirent.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -1463,6 +1464,64 @@
 }
 
 static int
+_skip_entry (const char *name)
+{
+	unsigned int i;
+	static const char *entries[] = {
+		".",
+		"..",
+		"dm-",
+		"loop",
+		"ram",
+	};
+
+	for (i = 0; i < sizeof(entries)/sizeof(*entries); i++) {
+		if (strncmp (name, entries[i], sizeof (entries[i]) - 1) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int
+_probe_sys_block ()
+{
+	DIR *blockdir;
+	struct dirent *dirent;
+	char dev_name [256];
+	char *ptr;
+
+#if 0
+	struct stat buf;
+	if ((stat ("/sys/block", &buf) != 0)
+	    || !S_ISDIR (buf.st_mode))
+		return 0;
+#endif
+
+	if (!(blockdir = opendir ("/sys/block")))
+		return 0;
+	while ((dirent = readdir (blockdir))) {
+		if (_skip_entry (dirent->d_name))
+			continue;
+
+		if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
+			continue; /* device name too long! */
+
+		strcpy (dev_name, "/dev/");
+		strcat (dev_name, dirent->d_name);
+		/* in /sys/block, '/'s are replaced with '!' or '.' */
+		for (ptr = dev_name; *ptr != '\0'; ptr++) {
+			if (*ptr == '!' || *ptr == '.')
+				*ptr = '/';
+		}
+		_ped_device_probe (dev_name);
+	}
+	
+	closedir (blockdir);
+	return 1;
+}
+
+static int
 _probe_standard_devices ()
 {
 	_ped_device_probe ("/dev/sda");
@@ -1487,7 +1546,11 @@
 static void
 linux_probe_all ()
 {
-	_probe_proc_partitions ();
+	/* /sys/block is more reliable and consistent; fall back to using
+	 * /proc/partitions if the former is unavailable, however.
+	 */
+	if (!_probe_sys_block ())
+		_probe_proc_partitions ();
 
 	/* we should probe the standard devs too, even with /proc/partitions,
 	 * because /proc/partitions might return devfs stuff, and we might not

_______________________________________________
Bug-parted mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-parted

Reply via email to