Add a new "virtual disk" feature. It's extremely difficult to test storage related logic on devices that don't have physical SD card slots. So to support better debugging and testing, add a new "virtual disk" feature which mounts a 512MB file through loop device. It relies on the kernel having the "loop.max_part" value set to something other than 0 via the boot command line, since that allows all the existing partition logic to fall into place. Bug: 34903607 Test: builds, boots, virtual disk works Change-Id: I04c5b33e37319d867542985a56b7999a9b7cf35d
diff --git a/Loop.cpp b/Loop.cpp index 1127817..7e243de 100644 --- a/Loop.cpp +++ b/Loop.cpp
@@ -32,12 +32,19 @@ #include <cutils/log.h> +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <android-base/unique_fd.h> + #include <sysutils/SocketClient.h> #include "Loop.h" #include "Asec.h" #include "VoldUtil.h" #include "sehandle.h" +using android::base::StringPrintf; +using android::base::unique_fd; + int Loop::dumpState(SocketClient *c) { int i; int fd; @@ -229,6 +236,40 @@ return 0; } +int Loop::create(const std::string& target, std::string& out_device) { + unique_fd ctl_fd(open("/dev/loop-control", O_RDWR)); + if (ctl_fd.get() == -1) { + PLOG(ERROR) << "Failed to open loop-control"; + return -errno; + } + + int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE); + if (num == -1) { + PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE"; + return -errno; + } + + out_device = StringPrintf("/dev/block/loop%d", num); + + unique_fd target_fd(open(target.c_str(), O_RDWR)); + if (target_fd.get() == -1) { + PLOG(ERROR) << "Failed to open " << target; + return -errno; + } + unique_fd device_fd(open(out_device.c_str(), O_RDWR)); + if (device_fd.get() == -1) { + PLOG(ERROR) << "Failed to open " << out_device; + return -errno; + } + + if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) { + PLOG(ERROR) << "Failed to LOOP_SET_FD"; + return -errno; + } + + return 0; +} + int Loop::destroyByDevice(const char *loopDevice) { int device_fd; @@ -254,20 +295,37 @@ } int Loop::createImageFile(const char *file, unsigned long numSectors) { - int fd; + int res = 0; - if ((fd = creat(file, 0600)) < 0) { - SLOGE("Error creating imagefile (%s)", strerror(errno)); - return -1; + char* secontext = nullptr; + if (sehandle) { + if (!selabel_lookup(sehandle, &secontext, file, S_IFREG)) { + setfscreatecon(secontext); + } } - if (ftruncate(fd, numSectors * 512) < 0) { - SLOGE("Error truncating imagefile (%s)", strerror(errno)); - close(fd); - return -1; + unique_fd fd(creat(file, 0600)); + if (fd.get() == -1) { + PLOG(ERROR) << "Failed to create image " << file; + res = -errno; + goto done; } - close(fd); - return 0; + + if (fallocate(fd.get(), 0, 0, numSectors * 512) == -1) { + PLOG(WARNING) << "Failed to fallocate; falling back to ftruncate"; + if (ftruncate(fd, numSectors * 512) == -1) { + PLOG(ERROR) << "Failed to ftruncate"; + res = -errno; + } + } + +done: + if (secontext) { + setfscreatecon(nullptr); + freecon(secontext); + } + + return res; } int Loop::resizeImageFile(const char *file, unsigned long numSectors) {