Blame SOURCES/0269-RHBZ-1804420-remove-kpartx-limit.patch

cdd025
---
cdd025
 kpartx/lopart.c |  206 ++++++++++++++++++++++++++++++++++----------------------
cdd025
 1 file changed, 127 insertions(+), 79 deletions(-)
cdd025
cdd025
Index: multipath-tools-130222/kpartx/lopart.c
cdd025
===================================================================
cdd025
--- multipath-tools-130222.orig/kpartx/lopart.c
cdd025
+++ multipath-tools-130222/kpartx/lopart.c
cdd025
@@ -25,8 +25,9 @@
cdd025
 #include <sys/ioctl.h>
cdd025
 #include <sys/stat.h>
cdd025
 #include <sys/mman.h>
cdd025
+#include <sys/types.h>
cdd025
+#include <dirent.h>
cdd025
 #include <sysmacros.h>
cdd025
-#include <asm/posix_types.h>
cdd025
 #include <linux/loop.h>
cdd025
 
cdd025
 #include "lopart.h"
cdd025
@@ -96,97 +97,149 @@ is_loop_device (const char *device)
cdd025
 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
cdd025
 
cdd025
 extern char *
cdd025
-find_loop_by_file (const char * filename)
cdd025
+find_loop_by_file(const char *filename)
cdd025
 {
cdd025
-	char dev[64];
cdd025
-	char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
cdd025
-	int i, j, fd;
cdd025
+	DIR *dir;
cdd025
+	struct dirent *dent;
cdd025
+	char dev[64], *found = NULL, *p;
cdd025
+	int fd, bytes_read;
cdd025
 	struct stat statbuf;
cdd025
 	struct loop_info loopinfo;
cdd025
+	const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
cdd025
+	char path[PATH_MAX];
cdd025
+	char bf_path[PATH_MAX];
cdd025
+	char backing_file[PATH_MAX];
cdd025
 
cdd025
-	for (j = 0; j < SIZE(loop_formats); j++) {
cdd025
+	dir = opendir(VIRT_BLOCK);
cdd025
+	if (!dir)
cdd025
+		return NULL;
cdd025
 
cdd025
-		for (i = 0; i < 256; i++) {
cdd025
-			sprintf (dev, loop_formats[j], i);
cdd025
+	while ((dent = readdir(dir)) != NULL) {
cdd025
+		if (strncmp(dent->d_name,"loop",4))
cdd025
+			continue;
cdd025
 
cdd025
-			if (stat (dev, &statbuf) != 0 ||
cdd025
-			    !S_ISBLK(statbuf.st_mode))
cdd025
-				continue;
cdd025
+		if (snprintf(path, PATH_MAX, "%s/%s/dev", VIRT_BLOCK,
cdd025
+					dent->d_name) >= PATH_MAX)
cdd025
+			continue;
cdd025
 
cdd025
-			fd = open (dev, O_RDONLY);
cdd025
+		fd = open(path, O_RDONLY);
cdd025
+		if (fd < 0)
cdd025
+			continue;
cdd025
 
cdd025
-			if (fd < 0)
cdd025
-				break;
cdd025
+		bytes_read = read(fd, dev, sizeof(dev) - 1);
cdd025
+		if (bytes_read <= 0) {
cdd025
+			close(fd);
cdd025
+			continue;
cdd025
+		}
cdd025
 
cdd025
-			if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
cdd025
-				close (fd);
cdd025
-				continue;
cdd025
-			}
cdd025
+		close(fd);
cdd025
 
cdd025
-			if (0 == strcmp(filename, loopinfo.lo_name)) {
cdd025
-				close (fd);
cdd025
-				return xstrdup(dev); /*found */
cdd025
-			}
cdd025
+		dev[bytes_read] = '\0';
cdd025
+		p = strchr(dev, '\n');
cdd025
+		if (p != NULL)
cdd025
+			*p = '\0';
cdd025
+		if (snprintf(path, PATH_MAX, "/dev/block/%s", dev) >= PATH_MAX)
cdd025
+			continue;
cdd025
 
cdd025
+		fd = open (path, O_RDONLY);
cdd025
+		if (fd < 0)
cdd025
+			continue;
cdd025
+
cdd025
+		if (fstat (fd, &statbuf) != 0 ||
cdd025
+		    !S_ISBLK(statbuf.st_mode)) {
cdd025
+			close (fd);
cdd025
+			continue;
cdd025
+		}
cdd025
+
cdd025
+		if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
cdd025
 			close (fd);
cdd025
 			continue;
cdd025
 		}
cdd025
+
cdd025
+		close (fd);
cdd025
+
cdd025
+		if (0 == strcmp(filename, loopinfo.lo_name)) {
cdd025
+			found = realpath(path, NULL);
cdd025
+			break;
cdd025
+		}
cdd025
+
cdd025
+		/*
cdd025
+		 * filename is a realpath, while loopinfo.lo_name may hold just the
cdd025
+		 * basename.  If that's the case, try to match filename against the
cdd025
+		 * backing_file entry for this loop entry
cdd025
+		 */
cdd025
+		if (snprintf(bf_path, PATH_MAX, "%s/%s/loop/backing_file",
cdd025
+			     VIRT_BLOCK, dent->d_name) >= PATH_MAX)
cdd025
+			continue;
cdd025
+
cdd025
+		fd = open(bf_path, O_RDONLY);
cdd025
+		if (fd < 0)
cdd025
+			continue;
cdd025
+
cdd025
+		bytes_read = read(fd, backing_file, sizeof(backing_file) - 1);
cdd025
+		if (bytes_read <= 0) {
cdd025
+			close(fd);
cdd025
+			continue;
cdd025
+		}
cdd025
+
cdd025
+		close(fd);
cdd025
+
cdd025
+		backing_file[bytes_read-1] = '\0';
cdd025
+
cdd025
+		if (0 == strcmp(filename, backing_file)) {
cdd025
+			found = realpath(path, NULL);
cdd025
+			break;
cdd025
+		}
cdd025
 	}
cdd025
-	return NULL;
cdd025
+	closedir(dir);
cdd025
+	return found;
cdd025
 }
cdd025
 
cdd025
 extern char *
cdd025
-find_unused_loop_device (void)
cdd025
+find_unused_loop_device(void)
cdd025
 {
cdd025
-	/* Just creating a device, say in /tmp, is probably a bad idea -
cdd025
-	   people might have problems with backup or so.
cdd025
-	   So, we just try /dev/loop[0-7]. */
cdd025
-
cdd025
-	char dev[20];
cdd025
-	char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
cdd025
-	int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0;
cdd025
+	char dev[20], *next_loop_dev = NULL;
cdd025
+	int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
cdd025
 	struct stat statbuf;
cdd025
 	struct loop_info loopinfo;
cdd025
 	FILE *procdev;
cdd025
 
cdd025
-	if (stat("/dev/loop-control", &statbuf) == 0 &&
cdd025
-	    S_ISCHR(statbuf.st_mode)) {
cdd025
-		fd = open("/dev/loop-control", O_RDWR);
cdd025
-		if (fd >= 0) {
cdd025
-			first = ioctl(fd, LOOP_CTL_GET_FREE);
cdd025
-			close(fd);
cdd025
+	while (next_loop_dev == NULL) {
cdd025
+		if (stat("/dev/loop-control", &statbuf) == 0 &&
cdd025
+		    S_ISCHR(statbuf.st_mode)) {
cdd025
+			int next_loop_fd;
cdd025
+
cdd025
+			next_loop_fd = open("/dev/loop-control", O_RDWR);
cdd025
+			if (next_loop_fd < 0)
cdd025
+				return NULL;
cdd025
+			next_loop = ioctl(next_loop_fd, LOOP_CTL_GET_FREE);
cdd025
+			close(next_loop_fd);
cdd025
+			if (next_loop < 0)
cdd025
+				return NULL;
cdd025
 		}
cdd025
-		if (first < 0)
cdd025
-			first = 0;
cdd025
-	}
cdd025
-	for (j = 0; j < SIZE(loop_formats); j++) {
cdd025
-
cdd025
-	    for(i = first; i < 256; i++) {
cdd025
-		sprintf(dev, loop_formats[j], i);
cdd025
-
cdd025
-		if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
cdd025
-			somedev++;
cdd025
-			fd = open (dev, O_RDONLY);
cdd025
 
cdd025
-			if (fd >= 0) {
cdd025
+		sprintf(dev, "/dev/loop%d", next_loop);
cdd025
 
cdd025
+		fd = open (dev, O_RDONLY);
cdd025
+		if (fd >= 0) {
cdd025
+			if (fstat (fd, &statbuf) == 0 &&
cdd025
+			    S_ISBLK(statbuf.st_mode)) {
cdd025
+				somedev++;
cdd025
 				if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
cdd025
-					someloop++;		/* in use */
cdd025
-
cdd025
-				else if (errno == ENXIO) {
cdd025
-					close (fd);
cdd025
-					return xstrdup(dev);/* probably free */
cdd025
-				}
cdd025
+					someloop++;             /* in use */
cdd025
+				else if (errno == ENXIO)
cdd025
+					next_loop_dev = xstrdup(dev);
cdd025
 
cdd025
-				close (fd);
cdd025
 			}
cdd025
-			
cdd025
+			close (fd);
cdd025
+
cdd025
 			/* continue trying as long as devices exist */
cdd025
 			continue;
cdd025
 		}
cdd025
 		break;
cdd025
-	    }
cdd025
 	}
cdd025
+	if (next_loop_dev)
cdd025
+		return next_loop_dev;
cdd025
 
cdd025
 	/* Nothing found. Why not? */
cdd025
 	if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
cdd025
@@ -209,29 +262,24 @@ find_unused_loop_device (void)
cdd025
 		fprintf(stderr, "mount: could not find any device /dev/loop#");
cdd025
 
cdd025
 	else if (!someloop) {
cdd025
-
cdd025
-	    if (loop_known == 1)
cdd025
-		fprintf(stderr,
cdd025
-		    "mount: Could not find any loop device.\n"
cdd025
-		    "       Maybe /dev/loop# has a wrong major number?");
cdd025
-	    
cdd025
-	    else if (loop_known == -1)
cdd025
-		fprintf(stderr,
cdd025
-		    "mount: Could not find any loop device, and, according to %s,\n"
cdd025
-		    "       this kernel does not know about the loop device.\n"
cdd025
-		    "       (If so, then recompile or `modprobe loop'.)",
cdd025
-		      PROC_DEVICES);
cdd025
-
cdd025
-	    else
cdd025
-		fprintf(stderr,
cdd025
-		    "mount: Could not find any loop device. Maybe this kernel does not know\n"
cdd025
-		    "       about the loop device (then recompile or `modprobe loop'), or\n"
cdd025
-		    "       maybe /dev/loop# has the wrong major number?");
cdd025
-
cdd025
+		if (loop_known == 1)
cdd025
+			fprintf(stderr,
cdd025
+				"mount: Could not find any loop device.\n"
cdd025
+				"       Maybe /dev/loop# has a wrong major number?");
cdd025
+		else if (loop_known == -1)
cdd025
+			fprintf(stderr,
cdd025
+				"mount: Could not find any loop device, and, according to %s,\n"
cdd025
+				"       this kernel does not know about the loop device.\n"
cdd025
+				"       (If so, then recompile or `modprobe loop'.)",
cdd025
+				PROC_DEVICES);
cdd025
+		else
cdd025
+			fprintf(stderr,
cdd025
+				"mount: Could not find any loop device. Maybe this kernel does not know\n"
cdd025
+				"       about the loop device (then recompile or `modprobe loop'), or\n"
cdd025
+				"       maybe /dev/loop# has the wrong major number?");
cdd025
 	} else
cdd025
 		fprintf(stderr, "mount: could not find any free loop device");
cdd025
-	
cdd025
-	return 0;
cdd025
+	return NULL;
cdd025
 }
cdd025
 
cdd025
 extern int