diff options
author | Jim Kaye <jameskaye@google.com> | 2015-07-31 23:58:37 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2015-07-31 23:58:37 +0000 |
commit | 7fbbbcf1ac6946c5ab944c1b739a9468a86e1378 (patch) | |
tree | fb5a7d03fe0ac90322bea7de18536e8d1e913bc9 | |
parent | 599aa6763471e2816d49b115ad7d60f918e2c5a2 (diff) | |
parent | dd6391c5eb6f0773de608800517d324c120f3a3d (diff) | |
download | qemu-7fbbbcf1ac6946c5ab944c1b739a9468a86e1378.tar.gz |
Merge "Making the emulator respect user-specified data partition size for API 19+" into studio-1.4-dev
automerge: dd6391c
* commit 'dd6391c5eb6f0773de608800517d324c120f3a3d':
Making the emulator respect user-specified data partition size for API 19+
-rw-r--r-- | Makefile.common | 1 | ||||
-rw-r--r-- | android/ext4_resize.cpp | 164 | ||||
-rw-r--r-- | android/ext4_resize.h | 51 | ||||
-rw-r--r-- | vl-android.c | 53 |
4 files changed, 253 insertions, 16 deletions
diff --git a/Makefile.common b/Makefile.common index 791ac7f035..becf3a5321 100644 --- a/Makefile.common +++ b/Makefile.common @@ -492,6 +492,7 @@ CORE_MISC_SOURCES = \ android/cbuffer.c \ android/charpipe.c \ android/core-init-utils.c \ + android/ext4_resize.cpp \ android/gps.c \ android/hw-kmsg.c \ android/hw-lcd.c \ diff --git a/android/ext4_resize.cpp b/android/ext4_resize.cpp new file mode 100644 index 0000000000..cbeb206be9 --- /dev/null +++ b/android/ext4_resize.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef _WIN32 +#include "android/base/system/Win32Utils.h" +#include "android/utils/win32_cmdline_quote.h" +#include <windows.h> + +using android::base::Win32Utils; +#else +#include <sys/wait.h> +#endif + +#include "android/base/String.h" +#include "android/ext4_resize.h" +#include "android/utils/path.h" +#include "base/system/System.h" +#include "main-common.h" + +using android::base::String; +using android::base::System; + +// Convenience function for formatting and printing system call/library +// function errors that show up regardless of host platform. Equivalent +// to printing the stringified error code from errno or GetLastError() +// (for windows). +void explainSystemErrors (const char * msg) { +#ifdef _WIN32 + char *pstr = NULL; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + GetLastError(), + 0, + (LPTSTR) &pstr, + 2, + NULL); + fprintf(stderr, "ERROR: %s - %s\n", msg, pstr); + LocalFree(pstr); +#else + fprintf(stderr, "ERROR: %s - %s\n", msg, strerror(errno)); +#endif +} + +int resizeExt4Partition (const char * partitionPath, int64_t newByteSize) { + // sanity checks + if (partitionPath == NULL || !checkExt4PartitionSize(newByteSize)) { + return -1; + } + + // format common arguments once + String executable = System::get()->findBundledExecutable("resize2fs"); + if(executable.empty()) { + fprintf(stderr, "ERROR: couldn't get path to resize2fs binary\n"); + return -1; + } + + char size_in_MB[50]; + int copied = snprintf(size_in_MB, sizeof(size_in_MB), + "%uM", convertBytesToMB(newByteSize)); + size_in_MB[sizeof(size_in_MB) - 1] = '\0'; + if (copied < 0 || copied >= sizeof(size_in_MB)) { + fprintf(stderr, "ERROR: failed to format size in resize2fs command\n"); + return -1; + } + + +#ifdef _WIN32 + STARTUPINFO startup; + PROCESS_INFORMATION pinfo; + DWORD exitCode; + + ZeroMemory(&startup, sizeof(startup)); + ZeroMemory(&pinfo, sizeof(pinfo)); + startup.cb = sizeof(startup); + + char args[PATH_MAX * 2 + 1]; + copied = snprintf(args, sizeof(args), "resize2fs.exe -f %s %s", + Win32Utils::quoteCommandLine(partitionPath).c_str(), + size_in_MB); + args[sizeof(args) - 1] = '\0'; + if (copied < 0 || copied >= sizeof(args)) { + fprintf(stderr, "ERROR: failed to format resize2fs command\n"); + return -1; + } + + BOOL success = CreateProcess( + Win32Utils::quoteCommandLine(executable.c_str()).c_str(), /* program path */ + args, /* command line args */ + NULL, /* process handle is not inheritable */ + NULL, /* thread handle is not inheritable */ + FALSE, /* no, don't inherit any handles */ + CREATE_NO_WINDOW, /* the new process doesn't have a console */ + NULL, /* use parent's environment block */ + NULL, /* use parent's starting directory */ + &startup, /* startup info, i.e. std handles */ + &pinfo); + if (!success) { + explainSystemErrors("failed to create process while resizing partition"); + return -2; + } + + WaitForSingleObject(pinfo.hProcess, INFINITE); + if (!GetExitCodeProcess(pinfo.hProcess, &exitCode)) { + explainSystemErrors("couldn't get exit code from resizing partition process"); + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + return -2; + } + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + +#else + int32_t exitCode = 0; + pid_t pid; + pid_t child = fork(); + + if (child < 0) { + explainSystemErrors("couldn't create a child process to resize the partition"); + return -2; + }else if (child == 0) { + execlp(executable.c_str(), executable.c_str(), "-f", partitionPath, + size_in_MB, NULL); + exit(-1); + } + + while ((pid = waitpid(-1, &exitCode, 0)) != child) { + if (pid == -1) { + explainSystemErrors("resizing partition waitpid failed"); + return -2; + } + } +#endif + if(exitCode != 0) { + fprintf(stderr, "ERROR: resizing partition failed with exit code %d\n", + exitCode); + return exitCode; + } + return 0; +} + +bool checkExt4PartitionSize (int64_t byteSize) { + uint64_t maxSizeMB = 16 * 1024 * 1024; // (16 TiB) * (1024 GiB / TiB) * (1024 MiB / GiB) + uint64_t minSizeMB = 128; + uint64_t sizeMB = convertBytesToMB(byteSize); + + //compiler converts signed to unsigned + return (sizeMB >= minSizeMB) && (sizeMB <= maxSizeMB); +} diff --git a/android/ext4_resize.h b/android/ext4_resize.h new file mode 100644 index 0000000000..47ad5afdaa --- /dev/null +++ b/android/ext4_resize.h @@ -0,0 +1,51 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ANDROID_EXT4_RESIZE_H +#define ANDROID_EXT4_RESIZE_H + +#include <android/base/Limits.h> +#include <android/utils/compiler.h> +#include <stdint.h> + +ANDROID_BEGIN_HEADER + +// Resize the partition in |partitionPath| to be newSize. +// +// |partitionPath| should hold the full, null-terminated path to the +// desired partition. +// |newByteSize| should be the desired new size of the partition in bytes, +// no smaller than 128 MiB and no greater than 16 TiB. If the |newByteSize| +// is below the minimum allowed for the specified partition, resize2fs will +// still fail and the error code will be returned to the user +// +// Returns: +// 0 - indicating the resize was successful +// -1 - indicating that formatting the arguments failed +// -2 - indicating a system call went wrong +// Otherwise the exit code of the resize2fs process is returned. +int resizeExt4Partition(const char * partitionPath, int64_t newByteSize); + +// Returns true if |byteSize| is a valid ext4 partition size; i.e. within the +// range of 128 MiB and 16 TiB inclusive, false otherwise. +// +// ext4 partitions have a theoretical limit of 1 EiB, although on 32-bit +// systems the partition limit is reduced to 16 TiB due to the data range +// of 32-bits, so enforce 16 TiB to minimize differences between systems of +// different bitness. The minimum size of an ext4 partition is 128 MiB. +bool checkExt4PartitionSize (int64_t byteSize); + +ANDROID_END_HEADER + +#endif /* _ANDROID_EXT4_RESIZE_H */ diff --git a/vl-android.c b/vl-android.c index 260da499e1..72f683db1c 100644 --- a/vl-android.c +++ b/vl-android.c @@ -46,24 +46,29 @@ #include "sysemu/blockdev.h" #include "audio/audio.h" -#include "migration/qemu-file.h" #include "android/android.h" +#include "android/camera/camera-service.h" #include "android/charpipe.h" -#include "android/log-rotate.h" -#include "modem_driver.h" +#include "android/display-core.h" +#include "android/ext4_resize.h" #include "android/filesystems/ext4_utils.h" #include "android/filesystems/fstab_parser.h" #include "android/filesystems/partition_types.h" #include "android/filesystems/ramdisk_extractor.h" +#include "android/globals.h" #include "android/gps.h" #include "android/hw-kmsg.h" #include "android/hw-pipe-net.h" #include "android/hw-qemud.h" #include "android/hw-sensors.h" -#include "android/camera/camera-service.h" +#include "android/log-rotate.h" #include "android/multitouch-port.h" +#include "android/multitouch-screen.h" +#include "android/opengles.h" +#include "android/opengl/emugl_config.h" #include "android/skin/charmap.h" -#include "android/globals.h" +#include "android/snapshot.h" +#include "android/tcpdump.h" #include "android/utils/bufprint.h" #include "android/utils/debug.h" #include "android/utils/filelock.h" @@ -71,22 +76,17 @@ #include "android/utils/socket_drainer.h" #include "android/utils/stralloc.h" #include "android/utils/tempfile.h" -#include "android/wear-agent/android_wear_agent.h" -#include "android/display-core.h" #include "android/utils/timezone.h" -#include "android/snapshot.h" -#include "android/opengles.h" -#include "android/opengl/emugl_config.h" -#include "android/multitouch-screen.h" +#include "android/wear-agent/android_wear_agent.h" #include "exec/hwaddr.h" -#include "android/tcpdump.h" - -#include <unistd.h> +#include "migration/qemu-file.h" +#include "modem_driver.h" +#include <errno.h> #include <fcntl.h> #include <signal.h> -#include <time.h> -#include <errno.h> #include <sys/time.h> +#include <time.h> +#include <unistd.h> #include <zlib.h> /* Needed early for CONFIG_BSD etc. */ @@ -3127,6 +3127,18 @@ int main(int argc, char **argv, char **envp) android_hw->disk_systemPartition_path, android_hw->disk_systemPartition_initPath); + /* For ext4, to extend an internal partition to more than the default size + * you need to initialize userdata-qemu.img to the desired size and restore + * it after moving the data in - yaffs is resilient enough for this not to + * matter + */ + if(android_op_wipe_data && + userdata_partition_type == ANDROID_PARTITION_TYPE_EXT4) { + androidPartitionType_makeEmptyFile(userdata_partition_type, + android_hw->disk_dataPartition_size, + android_hw->disk_dataPartition_path); + } + /* Initialize data partition image */ android_nand_add_image("userdata", userdata_partition_type, @@ -3135,6 +3147,15 @@ int main(int argc, char **argv, char **envp) android_hw->disk_dataPartition_path, android_hw->disk_dataPartition_initPath); + /* Extend the userdata-qemu.img to the desired size - resize2fs can only + * extend partitions to fill available space + */ + if(android_op_wipe_data && + userdata_partition_type == ANDROID_PARTITION_TYPE_EXT4) { + resizeExt4Partition(android_hw->disk_dataPartition_path, + android_hw->disk_dataPartition_size); + } + /* Initialize cache partition image, if any. Its type depends on the * kernel version. For anything >= 3.10, it must be EXT4, or * YAFFS2 otherwise. |