diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-09 23:20:49 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-09 23:20:49 +0200 |
commit | 3b69ba799fd302a781f2ec760909f340e3b90236 (patch) | |
tree | 37f2545a39600dcbc45a65903ef8b0ca7679a5d6 | |
parent | 7b6d4f50c97b4f375687e8216313b10598b44b49 (diff) | |
download | busybox-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.h | 7 | ||||
-rw-r--r-- | libbb/loop.c | 42 | ||||
-rw-r--r-- | util-linux/losetup.c | 8 |
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 | ||
1462 | extern int get_linux_version_code(void) FAST_FUNC; | 1462 | extern int get_linux_version_code(void) FAST_FUNC; |
1463 | 1463 | ||
1464 | extern char *query_loop(const char *device) FAST_FUNC; | 1464 | char *query_loop(const char *device) FAST_FUNC; |
1465 | extern int del_loop(const char *device) FAST_FUNC; | 1465 | int get_free_loop(void) FAST_FUNC; |
1466 | int 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 | */ |
1471 | extern int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC; | 1472 | int 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 */ | ||
82 | int 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"); |