aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-06-09 23:20:49 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-06-09 23:20:49 +0200
commit3b69ba799fd302a781f2ec760909f340e3b90236 (patch)
tree37f2545a39600dcbc45a65903ef8b0ca7679a5d6
parent7b6d4f50c97b4f375687e8216313b10598b44b49 (diff)
downloadbusybox-w32-3b69ba799fd302a781f2ec760909f340e3b90236.tar.gz
busybox-w32-3b69ba799fd302a781f2ec760909f340e3b90236.tar.bz2
busybox-w32-3b69ba799fd302a781f2ec760909f340e3b90236.zip
mount,losetup: use /dev/loop-control is it exists
function old new delta get_free_loop - 58 +58 set_loop 597 649 +52 losetup_main 482 476 -6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 110/-6) Total: 104 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h7
-rw-r--r--libbb/loop.c42
-rw-r--r--util-linux/losetup.c8
3 files changed, 47 insertions, 10 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 100d6b606..021100db1 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1461,14 +1461,15 @@ extern void bb_warn_ignoring_args(char *arg) FAST_FUNC;
1461 1461
1462extern int get_linux_version_code(void) FAST_FUNC; 1462extern int get_linux_version_code(void) FAST_FUNC;
1463 1463
1464extern char *query_loop(const char *device) FAST_FUNC; 1464char *query_loop(const char *device) FAST_FUNC;
1465extern int del_loop(const char *device) FAST_FUNC; 1465int get_free_loop(void) FAST_FUNC;
1466int del_loop(const char *device) FAST_FUNC;
1466/* 1467/*
1467 * If *devname is not NULL, use that name, otherwise try to find free one, 1468 * If *devname is not NULL, use that name, otherwise try to find free one,
1468 * malloc and return it in *devname. 1469 * malloc and return it in *devname.
1469 * return value is the opened fd to the loop device, or < on error 1470 * return value is the opened fd to the loop device, or < on error
1470 */ 1471 */
1471extern int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC; 1472int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC;
1472/* These constants match linux/loop.h (without BB_ prefix): */ 1473/* These constants match linux/loop.h (without BB_ prefix): */
1473#define BB_LO_FLAGS_READ_ONLY 1 1474#define BB_LO_FLAGS_READ_ONLY 1
1474#define BB_LO_FLAGS_AUTOCLEAR 4 1475#define BB_LO_FLAGS_AUTOCLEAR 4
diff --git a/libbb/loop.c b/libbb/loop.c
index c78535a20..ada0c7638 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -78,6 +78,24 @@ int FAST_FUNC del_loop(const char *device)
78 return rc; 78 return rc;
79} 79}
80 80
81/* Obtain an unused loop device number */
82int FAST_FUNC get_free_loop(void)
83{
84 int fd;
85 int loopdevno;
86
87 fd = open("/dev/loop-control", O_RDWR | O_CLOEXEC);
88 if (fd == -1)
89 return fd - 1; /* -2: "no /dev/loop-control" */
90
91#ifndef LOOP_CTL_GET_FREE
92# define LOOP_CTL_GET_FREE 0x4C82
93#endif
94 loopdevno = ioctl(fd, LOOP_CTL_GET_FREE);
95 close(fd);
96 return loopdevno; /* can be -1 if error */
97}
98
81/* Returns opened fd to the loop device, <0 on error. 99/* Returns opened fd to the loop device, <0 on error.
82 * *device is loop device to use, or if *device==NULL finds a loop device to 100 * *device is loop device to use, or if *device==NULL finds a loop device to
83 * mount it on and sets *device to a strdup of that loop device name. This 101 * mount it on and sets *device to a strdup of that loop device name. This
@@ -106,12 +124,24 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
106 return -errno; 124 return -errno;
107 } 125 }
108 126
109//TODO: use LOOP_CTL_GET_FREE instead of trying every loopN in sequence? a-la: 127 try = *device;
110// fd = open("/dev/loop-control", O_RDWR); 128 if (!try) {
111// loopN = ioctl(fd, LOOP_CTL_GET_FREE); 129 i = get_free_loop();
112// 130 if (i == -2) { /* no /dev/loop-control */
131 i = 0;
132 try = dev;
133 goto old_style;
134 }
135 if (i == -1) {
136 close(ffd);
137 return -1; /* no free loop devices */
138 }
139 try = *device = xasprintf(LOOP_FORMAT, i);
140 goto try_to_open;
141 }
142
143 old_style:
113 /* Find a loop device. */ 144 /* Find a loop device. */
114 try = *device ? *device : dev;
115 /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ 145 /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */
116 for (i = 0; rc && i < 1048576; i++) { 146 for (i = 0; rc && i < 1048576; i++) {
117 sprintf(dev, LOOP_FORMAT, i); 147 sprintf(dev, LOOP_FORMAT, i);
@@ -170,7 +200,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
170 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo); 200 rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
171 } 201 }
172 if (rc != 0) { 202 if (rc != 0) {
173 ioctl(dfd, LOOP_CLR_FD, 0); 203 ioctl(dfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
174 } 204 }
175 } 205 }
176 } else { 206 } else {
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index b52d693ec..5dc757074 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -114,8 +114,14 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
114 /* contains -f */ 114 /* contains -f */
115 if (opt & OPT_f) { 115 if (opt & OPT_f) {
116 char *s; 116 char *s;
117 int n = 0; 117 int n;
118 118
119 n = get_free_loop();
120 if (n == -1)
121 bb_error_msg_and_die("no free loop devices");
122 if (n < 0) /* n == -2: no /dev/loop-control, use legacy method */
123 n = 0;
124 /* or: n >= 0: the number of next free loopdev, just verify it */
119 do { 125 do {
120 if (n > MAX_LOOP_NUM) 126 if (n > MAX_LOOP_NUM)
121 bb_error_msg_and_die("no free loop devices"); 127 bb_error_msg_and_die("no free loop devices");