From 2b26bdf97334edad834000a35aa03bcc3bc218f3 Mon Sep 17 00:00:00 2001 From: tangjie1 Date: Thu, 13 Apr 2023 17:15:23 +0800 Subject: [PATCH] init: automatically add a new loop device when there are no idle loop devices Signed-off-by: tangjie1 Change-Id: I5fe6df9b733c4932334097aff6b7781dcb34027e --- init/builtins.cpp | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/init/builtins.cpp b/init/builtins.cpp index bc23972a2..585eca25d 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -60,6 +60,8 @@ #include #include #include +#include +#include #include #include #include @@ -506,29 +508,29 @@ static Result do_mount(const BuiltinArguments& args) { if (android::base::StartsWith(source, "loop@")) { int mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; - unique_fd fd(TEMP_FAILURE_RETRY(open(source + 5, mode | O_CLOEXEC))); - if (fd < 0) return ErrnoError() << "open(" << source + 5 << ", " << mode << ") failed"; + const char* file_path = source + strlen("loop@"); - for (size_t n = 0;; n++) { - std::string tmp = android::base::StringPrintf("/dev/block/loop%zu", n); - unique_fd loop(TEMP_FAILURE_RETRY(open(tmp.c_str(), mode | O_CLOEXEC))); - if (loop < 0) return ErrnoError() << "open(" << tmp << ", " << mode << ") failed"; - - loop_info info; - /* if it is a blank loop device */ - if (ioctl(loop.get(), LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { - /* if it becomes our loop device */ - if (ioctl(loop.get(), LOOP_SET_FD, fd.get()) >= 0) { - if (mount(tmp.c_str(), target, system, flags, options) < 0) { - ioctl(loop.get(), LOOP_CLR_FD, 0); - return ErrnoError() << "mount() failed"; - } - return {}; - } - } + // Open source file + if (wait) { + wait_for_file(file_path, kCommandRetryTimeout); } - return Error() << "out of loopback devices"; + unique_fd fd(TEMP_FAILURE_RETRY(open(file_path, mode | O_CLOEXEC))); + if (fd < 0) { + return ErrnoError() << "open(" << file_path << ", " << mode << ") failed"; + } + + // Allocate loop device and attach it to file_path. + android::dm::LoopControl loop_control; + std::string loop_device; + if (!loop_control.Attach(fd.get(), 5s, &loop_device)) { + return ErrnoError() << "loop_control.Attach " << file_path << " failed"; + } + + if (mount(loop_device.c_str(), target, system, flags, options) < 0) { + loop_control.Detach(loop_device); + return ErrnoError() << "mount() failed"; + } } else { if (wait) wait_for_file(source, kCommandRetryTimeout);