aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaoming Ni <nixiaoming@huawei.com>2022-12-12 18:41:02 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2022-12-12 18:57:09 +0100
commitddccf6cd2f519c46a6286a43ceaf680eb367301c (patch)
treece53166de2e8bc5fa2a9459dbc0e99bc970d2634
parent90456a6aa3a039ac1b16a09e64d13cc9589b55ee (diff)
downloadbusybox-w32-ddccf6cd2f519c46a6286a43ceaf680eb367301c.tar.gz
busybox-w32-ddccf6cd2f519c46a6286a43ceaf680eb367301c.tar.bz2
busybox-w32-ddccf6cd2f519c46a6286a43ceaf680eb367301c.zip
loop: refactor: extract subfunction get_next_free_loop()
Extract subfunction get_next_free_loop() from set_loop() Also fix miss free(try) when stat(try) and mknod fail function old new delta set_loop 807 790 -17 Fixes: 3448914e8cc5 ("mount,losetup: use /dev/loop-control is it exists") Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libbb/loop.c56
1 files changed, 26 insertions, 30 deletions
diff --git a/libbb/loop.c b/libbb/loop.c
index 750642ade..8e5c915fc 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -96,6 +96,20 @@ int FAST_FUNC get_free_loop(void)
96 return loopdevno; /* can be -1 if error */ 96 return loopdevno; /* can be -1 if error */
97} 97}
98 98
99static int get_next_free_loop(char *dev, int id)
100{
101 int loopdevno;
102
103 loopdevno = get_free_loop();
104 if (loopdevno != -1) {
105 /* loopdevno is -2 (use id) or >= 0 (use id = loopdevno): */
106 if (loopdevno >= 0)
107 id = loopdevno;
108 sprintf(dev, LOOP_FORMAT, id);
109 }
110 return loopdevno;
111}
112
99/* Returns opened fd to the loop device, <0 on error. 113/* Returns opened fd to the loop device, <0 on error.
100 * *device is loop device to use, or if *device==NULL finds a loop device to 114 * *device is loop device to use, or if *device==NULL finds a loop device to
101 * mount it on and sets *device to a strdup of that loop device name. 115 * mount it on and sets *device to a strdup of that loop device name.
@@ -123,30 +137,27 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
123 137
124 try = *device; 138 try = *device;
125 if (!try) { 139 if (!try) {
126 get_free_loopN:
127 i = get_free_loop();
128 if (i == -1) {
129 close(ffd);
130 return -1; /* no free loop devices */
131 }
132 if (i >= 0) {
133 try = xasprintf(LOOP_FORMAT, i);
134 goto open_lfd;
135 }
136 /* i == -2: no /dev/loop-control. Do an old-style search for a free device */
137 try = dev; 140 try = dev;
138 } 141 }
139 142
140 /* Find a loop device */ 143 /* Find a loop device */
141 /* 0xfffff is a max possible minor number in Linux circa 2010 */ 144 /* 0xfffff is a max possible minor number in Linux circa 2010 */
142 for (i = 0; i <= 0xfffff; i++) { 145 for (i = 0; i <= 0xfffff; i++) {
143 sprintf(dev, LOOP_FORMAT, i); 146 if (!*device) {
147 rc = get_next_free_loop(dev, i);
148 if (rc == -1)
149 break; /* no free loop devices (or other error in LOOP_CTL_GET_FREE) */
150 if (rc >= 0)
151 /* /dev/loop-control gave us the next free /dev/loopN */
152 goto open_lfd;
153 /* else: sequential /dev/loopN, needs to be tested/maybe_created */
154 }
144 155
145 IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) 156 IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;)
146 if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) { 157 if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) {
147 if (ENABLE_FEATURE_MOUNT_LOOP_CREATE 158 if (ENABLE_FEATURE_MOUNT_LOOP_CREATE
148 && errno == ENOENT 159 && errno == ENOENT
149 && try == dev 160 && (!*device)
150 ) { 161 ) {
151 /* Node doesn't exist, try to create it */ 162 /* Node doesn't exist, try to create it */
152 if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) 163 if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0)
@@ -179,13 +190,10 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
179 /* Associate free loop device with file */ 190 /* Associate free loop device with file */
180 if (ioctl(lfd, LOOP_SET_FD, ffd)) { 191 if (ioctl(lfd, LOOP_SET_FD, ffd)) {
181 /* Ouch. Are we racing with other mount? */ 192 /* Ouch. Are we racing with other mount? */
182 if (!*device /* yes */ 193 if (!*device) {
183 && try != dev /* tried a _kernel-offered_ loopN? */
184 ) {
185 free(try);
186 close(lfd); 194 close(lfd);
187//TODO: add "if (--failcount != 0) ..."? 195//TODO: add "if (--failcount != 0) ..."?
188 goto get_free_loopN; 196 continue;
189 } 197 }
190 goto close_and_try_next_loopN; 198 goto close_and_try_next_loopN;
191 } 199 }
@@ -209,8 +217,6 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
209 } 217 }
210 if (rc == 0) { 218 if (rc == 0) {
211 /* SUCCESS! */ 219 /* SUCCESS! */
212 if (try != dev) /* tried a kernel-offered free loopN? */
213 *device = try; /* malloced */
214 if (!*device) /* was looping in search of free "/dev/loopN"? */ 220 if (!*device) /* was looping in search of free "/dev/loopN"? */
215 *device = xstrdup(dev); 221 *device = xstrdup(dev);
216 rc = lfd; /* return this */ 222 rc = lfd; /* return this */
@@ -218,16 +224,6 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
218 } 224 }
219 /* failure, undo LOOP_SET_FD */ 225 /* failure, undo LOOP_SET_FD */
220 ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary 226 ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
221 } else {
222 /* device is not free (rc == 0), or error other than ENXIO */
223 if (rc == 0 /* device is not free? */
224 && !*device /* racing with other mount? */
225 && try != dev /* tried a _kernel-offered_ loopN? */
226 ) {
227 free(try);
228 close(lfd);
229 goto get_free_loopN;
230 }
231 } 227 }
232 close_and_try_next_loopN: 228 close_and_try_next_loopN:
233 close(lfd); 229 close(lfd);