Update the loop handling code to support more than 256 devices. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- kpartx/lopart.c | 106 ++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/kpartx/lopart.c b/kpartx/lopart.c index 26f3011..ffde6d9 100644 --- a/kpartx/lopart.c +++ b/kpartx/lopart.c @@ -25,8 +25,9 @@ #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/mman.h> +#include <sys/types.h> +#include <dirent.h> #include <sysmacros.h> -#include <asm/posix_types.h> #include <linux/loop.h> #include "lopart.h" @@ -98,78 +99,71 @@ is_loop_device (const char *device) extern char * find_loop_by_file (const char * filename) { - char dev[64]; - char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; - int i, j, fd; + DIR *dir; + struct dirent *dent; + char dev[64], *found = NULL; + int fd; struct stat statbuf; struct loop_info loopinfo; - dev_t file_dev; - ino_t file_ino; - if (stat (filename, &statbuf) != 0) { + dir = opendir("/dev"); + if (!dir) return NULL; - } - file_dev = statbuf.st_dev; - file_ino = statbuf.st_ino; - - for (j = 0; j < SIZE(loop_formats); j++) { - - for (i = 0; i < 256; i++) { - sprintf (dev, loop_formats[j], i); - - if (stat (dev, &statbuf) != 0 || - !S_ISBLK(statbuf.st_mode)) - continue; - - fd = open (dev, O_RDONLY); - if (fd < 0) - break; + while ((dent = readdir(dir)) != NULL) { + if (strncmp(dent->d_name,"loop",4)) + continue; + if (!strcmp(dent->d_name, "loop-control")) + continue; + sprintf(dev, "/dev/%s", dent->d_name); - if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) { - close (fd); - continue; - } + if (stat (dev, &statbuf) != 0 || + !S_ISBLK(statbuf.st_mode)) + continue; - if (loopinfo.lo_device == file_dev && loopinfo.lo_inode == file_ino) { - close (fd); - return xstrdup(dev); /*found */ - } + fd = open (dev, O_RDONLY); + if (fd < 0) + break; + if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) { close (fd); continue; } + + if (0 == strcmp(filename, loopinfo.lo_name)) { + close (fd); + found = xstrdup(dev); + break; + } + + close (fd); } - return NULL; + closedir(dir); + return found; } extern char * find_unused_loop_device (void) { - /* Just creating a device, say in /tmp, is probably a bad idea - - people might have problems with backup or so. - So, we just try /dev/loop[0-7]. */ - - char dev[20]; - char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; - int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0; + char dev[20], *next_loop_dev = NULL;; + int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0; struct stat statbuf; struct loop_info loopinfo; FILE *procdev; - if (stat("/dev/loop-control", &statbuf) == 0 && - S_ISCHR(statbuf.st_mode)) { - fd = open("/dev/loop-control", O_RDWR); - if (fd >= 0) - first = ioctl(fd, LOOP_CTL_GET_FREE); - close(fd); - if (first < 0) - first = 0; - } - for (j = 0; j < SIZE(loop_formats); j++) { + while (next_loop_dev == NULL) { + if (stat("/dev/loop-control", &statbuf) == 0 && + S_ISCHR(statbuf.st_mode)) { + fd = open("/dev/loop-control", O_RDWR); + if (fd < 0) + return NULL; + next_loop = ioctl(fd, LOOP_CTL_GET_FREE); + if (next_loop < 0) + return NULL; + close(fd); + } - for(i = first; i < 256; i++) { - sprintf(dev, loop_formats[j], i); + sprintf(dev, "/dev/loop%d", next_loop); if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { somedev++; @@ -182,18 +176,19 @@ find_unused_loop_device (void) else if (errno == ENXIO) { close (fd); - return xstrdup(dev);/* probably free */ + next_loop_dev = xstrdup(dev); } close (fd); } - + /* continue trying as long as devices exist */ continue; } break; - } } + if (next_loop_dev) + return next_loop_dev; /* Nothing found. Why not? */ if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) { @@ -216,12 +211,10 @@ find_unused_loop_device (void) fprintf(stderr, "mount: could not find any device /dev/loop#"); else if (!someloop) { - if (loop_known == 1) fprintf(stderr, "mount: Could not find any loop device.\n" " Maybe /dev/loop# has a wrong major number?"); - else if (loop_known == -1) fprintf(stderr, "mount: Could not find any loop device, and, according to %s,\n" @@ -237,7 +230,6 @@ find_unused_loop_device (void) } else fprintf(stderr, "mount: could not find any free loop device"); - return 0; } -- 2.6.6 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel