LOOP_CONFIGURE is added to Linux 5.8 This allows userspace to completely setup a loop device with a single ioctl, removing the in-between state where the device can be partially configured - eg the loop device has a backing file associated with it, but is reading from the wrong offset.
https://lwn.net/Articles/820408/ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3448914e8cc5 Builders can use config to choose which algorithm to build into their busybox binary kernel version >= 5.8, choice CONFIG_LOOP_CONFIGURE function old new delta set_loop 716 639 -77 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-77) Total: -77 bytes kernel version < 5.8, choice CONFIG_NO_LOOP_CONFIGURE function old new delta ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0) Total: 0 bytes kernel version is unknown, choice CONFIG_TRY_LOOP_CONFIGURE function old new delta set_loop 716 832 +116 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 116/0) Total: 116 bytes Signed-off-by: Xiaoming Ni <nixiaom...@huawei.com> --- libbb/Config.src | 22 ++++++++++++++++++++++ libbb/loop.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/libbb/Config.src b/libbb/Config.src index 66a3ffa23..b7f9ddab4 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -369,3 +369,25 @@ config UNICODE_PRESERVE_BROKEN For example, this means that entering 'l', 's', ' ', 0xff, [Enter] at shell prompt will list file named 0xff (single char name with char value 255), not file named '?'. + +choice + prompt "LOOP_CONFIGURE or LOOP_SET_FD + LOOP_SET_STATUS" + default TRY_LOOP_CONFIGURE + help + LOOP_CONFIGURE is added to Linux 5.8 + https://lwn.net/Articles/820408/ + This allows userspace to completely setup a loop device with a single + ioctl, removing the in-between state where the device can be partially + configured - eg the loop device has a backing file associated with it, + but is reading from the wrong offset. + +config LOOP_CONFIGURE + bool "always uses LOOP_CONFIGURE, kernel version >= 5.8" + +config NO_LOOP_CONFIGURE + bool "never uses LOOP_CONFIGURE, kernel version < 5.8" + +config TRY_LOOP_CONFIGURE + bool "try LOOP_CONFIGURE, kernel version is unknown" + +endchoice diff --git a/libbb/loop.c b/libbb/loop.c index 799936765..14919b318 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -126,7 +126,8 @@ static int open_file(const char *file, unsigned flags, int *mode) return ffd; } -static int set_loop_configure(int ffd, int lfd, bb_loop_info *loopinfo) +#ifndef CONFIG_LOOP_CONFIGURE +static int set_loop_fd_and_status(int ffd, int lfd, bb_loop_info *loopinfo) { int rc; bb_loop_info loopinfo2; @@ -149,6 +150,46 @@ static int set_loop_configure(int ffd, int lfd, bb_loop_info *loopinfo) ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary return -1; } +#endif + +#ifndef CONFIG_NO_LOOP_CONFIGURE + +#ifndef LOOP_CONFIGURE +#define LOOP_CONFIGURE 0x4C0A +struct loop_config { + uint32_t fd; + uint32_t block_size; + struct loop_info64 info; + uint64_t __reserved[8]; +}; +#endif + +/* + * linux v5.8.0 + * loop: Add LOOP_CONFIGURE ioctl + * https://lwn.net/Articles/820408/ + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3448914e8cc5 + */ +static int set_loop_configure(int ffd, int lfd, bb_loop_info *loopinfo) +{ + int rc; + struct loop_config config; + + memset(&config, 0, sizeof(config)); + config.fd = ffd; + memcpy(&config.info, loopinfo, sizeof(config.info)); + + rc = ioctl(lfd, LOOP_CONFIGURE, &config); + if (rc == 0) { + return lfd; + } +#ifdef CONFIG_TRY_LOOP_CONFIGURE + if (rc == -1 && errno == EINVAL) /* The system may not support LOOP_CONFIGURE. */ + return set_loop_fd_and_status(ffd, lfd, loopinfo); +#endif + return -1; +} +#endif static int set_loop_info(int ffd, int lfd, bb_loop_info *loopinfo) { @@ -159,7 +200,11 @@ static int set_loop_info(int ffd, int lfd, bb_loop_info *loopinfo) /* If device is free, try to claim it */ if (rc && errno == ENXIO) { +#ifdef CONFIG_NO_LOOP_CONFIGURE + return set_loop_fd_and_status(ffd, lfd, loopinfo); +#else return set_loop_configure(ffd, lfd, loopinfo); +#endif } return -1; } -- 2.27.0 _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox