|
|
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
|