klibc-bot for Ben Hutchings
2019-Nov-05 22:42 UTC
[klibc] [klibc:master] losetup: Use LOOP_CTL_GET_FREE to find free device
Commit-ID: 333ef3af1dcef61a6bc5dba531453e5e0cb27da1 Gitweb: http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=333ef3af1dcef61a6bc5dba531453e5e0cb27da1 Author: Ben Hutchings <ben at decadent.org.uk> AuthorDate: Tue, 5 Nov 2019 19:52:19 +0000 Committer: Ben Hutchings <ben at decadent.org.uk> CommitDate: Tue, 5 Nov 2019 20:03:26 +0000 [klibc] losetup: Use LOOP_CTL_GET_FREE to find free device Since Linux 3.1, the loop driver creates a /dev/loop-control device node which supports ioctls to allocate and free devices. When the loop driver is modular, udev creates this in advance, and opening it causes the driver to be loaded. (The same is not true for /dev/loop*.) Using the LOOP_CTL_GET_FREE ioctl also allows creating more than the default number of loop devices, and is more efficient than checking a range of possible device names. Signed-off-by: Ben Hutchings <ben at decadent.org.uk> --- usr/utils/losetup.c | 59 +++++++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/usr/utils/losetup.c b/usr/utils/losetup.c index 5d328138..4a85e126 100644 --- a/usr/utils/losetup.c +++ b/usr/utils/losetup.c @@ -95,51 +95,26 @@ is_loop_device (const char *device) { 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, somedev = 0, someloop = 0, permission = 0; - struct stat statbuf; - struct loop_info loopinfo; - - 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)) { - somedev++; - fd = open (dev, O_RDONLY); - if (fd >= 0) { - if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0) - someloop++; /* in use */ - else if (errno == ENXIO) { - close (fd); - return xstrdup(dev);/* probably free */ - } - close (fd); - } else if (errno == EACCES) - permission++; - - continue;/* continue trying as long as devices exist */ - } - break; - } + int fd, rc; + + fd = open("/dev/loop-control", O_RDWR); + if (fd < 0) { + error("%s: could not open /dev/loop-control. Maybe this kernel " + "does not know\n" + " about the loop device? (If so, recompile or " + "`modprobe loop'.)", progname); + return NULL; } - - if (!somedev) - error("%s: could not find any device /dev/loop#", progname); - else if (!someloop && permission) - error("%s: no permission to look at /dev/loop#", progname); - else if (!someloop) - error( - "%s: Could not find any loop device. Maybe this kernel " - "does not know\n" - " about the loop device? (If so, recompile or " - "`modprobe loop'.)", progname); - else + rc = ioctl(fd, LOOP_CTL_GET_FREE, 0); + close(fd); + if (rc < 0) { error("%s: could not find any free loop device", progname); - return 0; + return NULL; + } + + sprintf(dev, "/dev/loop%d", rc); + return xstrdup(dev); } /*