aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Kaye <jameskaye@google.com>2015-08-01 00:14:16 +0000
committerandroid-build-merger <android-build-merger@google.com>2015-08-01 00:14:16 +0000
commit22844a8954d205a20afdf33dffea6c52f07677d5 (patch)
tree9f98793a0526f6f1ffe654b79d69a54d1878da0f
parent89057119d7b854776ed04baed9de73d093fb4f97 (diff)
parent7fbbbcf1ac6946c5ab944c1b739a9468a86e1378 (diff)
downloadqemu-22844a8954d205a20afdf33dffea6c52f07677d5.tar.gz
Merge "Making the emulator respect user-specified data partition size for API 19+" into studio-1.4-dev automerge: dd6391c
automerge: 7fbbbcf * commit '7fbbbcf1ac6946c5ab944c1b739a9468a86e1378': Making the emulator respect user-specified data partition size for API 19+
-rw-r--r--Makefile.common1
-rw-r--r--android/ext4_resize.cpp164
-rw-r--r--android/ext4_resize.h51
-rw-r--r--vl-android.c53
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.