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>
This commit is contained in:
parent
7b6d4f50c9
commit
3b69ba799f
@ -1461,14 +1461,15 @@ extern void bb_warn_ignoring_args(char *arg) FAST_FUNC;
|
|||||||
|
|
||||||
extern int get_linux_version_code(void) FAST_FUNC;
|
extern int get_linux_version_code(void) FAST_FUNC;
|
||||||
|
|
||||||
extern char *query_loop(const char *device) FAST_FUNC;
|
char *query_loop(const char *device) FAST_FUNC;
|
||||||
extern int del_loop(const char *device) FAST_FUNC;
|
int get_free_loop(void) FAST_FUNC;
|
||||||
|
int del_loop(const char *device) FAST_FUNC;
|
||||||
/*
|
/*
|
||||||
* If *devname is not NULL, use that name, otherwise try to find free one,
|
* If *devname is not NULL, use that name, otherwise try to find free one,
|
||||||
* malloc and return it in *devname.
|
* malloc and return it in *devname.
|
||||||
* return value is the opened fd to the loop device, or < on error
|
* return value is the opened fd to the loop device, or < on error
|
||||||
*/
|
*/
|
||||||
extern int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC;
|
int set_loop(char **devname, const char *file, unsigned long long offset, unsigned flags) FAST_FUNC;
|
||||||
/* These constants match linux/loop.h (without BB_ prefix): */
|
/* These constants match linux/loop.h (without BB_ prefix): */
|
||||||
#define BB_LO_FLAGS_READ_ONLY 1
|
#define BB_LO_FLAGS_READ_ONLY 1
|
||||||
#define BB_LO_FLAGS_AUTOCLEAR 4
|
#define BB_LO_FLAGS_AUTOCLEAR 4
|
||||||
|
42
libbb/loop.c
42
libbb/loop.c
@ -78,6 +78,24 @@ int FAST_FUNC del_loop(const char *device)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Obtain an unused loop device number */
|
||||||
|
int FAST_FUNC get_free_loop(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int loopdevno;
|
||||||
|
|
||||||
|
fd = open("/dev/loop-control", O_RDWR | O_CLOEXEC);
|
||||||
|
if (fd == -1)
|
||||||
|
return fd - 1; /* -2: "no /dev/loop-control" */
|
||||||
|
|
||||||
|
#ifndef LOOP_CTL_GET_FREE
|
||||||
|
# define LOOP_CTL_GET_FREE 0x4C82
|
||||||
|
#endif
|
||||||
|
loopdevno = ioctl(fd, LOOP_CTL_GET_FREE);
|
||||||
|
close(fd);
|
||||||
|
return loopdevno; /* can be -1 if error */
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns opened fd to the loop device, <0 on error.
|
/* Returns opened fd to the loop device, <0 on error.
|
||||||
* *device is loop device to use, or if *device==NULL finds a loop device to
|
* *device is loop device to use, or if *device==NULL finds a loop device to
|
||||||
* mount it on and sets *device to a strdup of that loop device name. This
|
* 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
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: use LOOP_CTL_GET_FREE instead of trying every loopN in sequence? a-la:
|
try = *device;
|
||||||
// fd = open("/dev/loop-control", O_RDWR);
|
if (!try) {
|
||||||
// loopN = ioctl(fd, LOOP_CTL_GET_FREE);
|
i = get_free_loop();
|
||||||
//
|
if (i == -2) { /* no /dev/loop-control */
|
||||||
|
i = 0;
|
||||||
|
try = dev;
|
||||||
|
goto old_style;
|
||||||
|
}
|
||||||
|
if (i == -1) {
|
||||||
|
close(ffd);
|
||||||
|
return -1; /* no free loop devices */
|
||||||
|
}
|
||||||
|
try = *device = xasprintf(LOOP_FORMAT, i);
|
||||||
|
goto try_to_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_style:
|
||||||
/* Find a loop device. */
|
/* Find a loop device. */
|
||||||
try = *device ? *device : dev;
|
|
||||||
/* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */
|
/* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */
|
||||||
for (i = 0; rc && i < 1048576; i++) {
|
for (i = 0; rc && i < 1048576; i++) {
|
||||||
sprintf(dev, LOOP_FORMAT, i);
|
sprintf(dev, LOOP_FORMAT, i);
|
||||||
@ -170,7 +200,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
|
|||||||
rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
|
rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
ioctl(dfd, LOOP_CLR_FD, 0);
|
ioctl(dfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,8 +114,14 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* contains -f */
|
/* contains -f */
|
||||||
if (opt & OPT_f) {
|
if (opt & OPT_f) {
|
||||||
char *s;
|
char *s;
|
||||||
int n = 0;
|
int n;
|
||||||
|
|
||||||
|
n = get_free_loop();
|
||||||
|
if (n == -1)
|
||||||
|
bb_error_msg_and_die("no free loop devices");
|
||||||
|
if (n < 0) /* n == -2: no /dev/loop-control, use legacy method */
|
||||||
|
n = 0;
|
||||||
|
/* or: n >= 0: the number of next free loopdev, just verify it */
|
||||||
do {
|
do {
|
||||||
if (n > MAX_LOOP_NUM)
|
if (n > MAX_LOOP_NUM)
|
||||||
bb_error_msg_and_die("no free loop devices");
|
bb_error_msg_and_die("no free loop devices");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user