[klibc] [klibc:master] losetup: Use LOOP_CTL_GET_FREE to find free device

klibc-bot for Ben Hutchings ben at decadent.org.uk
Tue Nov 5 14:42:11 PST 2019


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);
 }
 
 /*


More information about the klibc mailing list