Merge commit 'remotes/korg/cupcake' into merge
Conflicts:
init/devices.c
libpixelflinger/Android.mk
diff --git a/adb/adb.c b/adb/adb.c
index fa5269f..12a36f5 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -859,8 +859,20 @@
property_get("ro.kernel.qemu", value, "");
if (strcmp(value, "1") != 0) {
property_get("ro.secure", value, "");
- if (strcmp(value, "1") == 0)
+ if (strcmp(value, "1") == 0) {
+ // don't run as root if ro.secure is set...
secure = 1;
+
+ // ... except we allow running as root in userdebug builds if the
+ // service.adb.root property has been set by the "adb root" command
+ property_get("ro.debuggable", value, "");
+ if (strcmp(value, "1") == 0) {
+ property_get("service.adb.root", value, "");
+ if (strcmp(value, "1") == 0) {
+ secure = 0;
+ }
+ }
+ }
}
/* don't listen on port 5037 if we are running in secure mode */
@@ -872,8 +884,10 @@
** AID_INPUT to diagnose input issues (getevent)
** AID_INET to diagnose network issues (netcfg, ping)
** AID_GRAPHICS to access the frame buffer
+ ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
*/
- gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS };
+ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
+ AID_NET_BT, AID_NET_BT_ADMIN };
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
/* then switch user and group to "shell" */
@@ -1080,4 +1094,3 @@
return adb_main(0);
#endif
}
-
diff --git a/adb/commandline.c b/adb/commandline.c
index be596ce..7410dce 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -147,6 +147,7 @@
" adb get-serialno - prints: <serial-number>\n"
" adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system partition on the device read-write\n"
+ " adb root - restarts adb with root permissions\n"
"\n"
"networking:\n"
" adb ppp <tty> [parameters] - Run PPP over USB.\n"
@@ -914,6 +915,17 @@
return 1;
}
+ if(!strcmp(argv[0], "root")) {
+ int fd = adb_connect("root:");
+ if(fd >= 0) {
+ read_and_dump(fd);
+ adb_close(fd);
+ return 0;
+ }
+ fprintf(stderr,"error: %s\n", adb_error());
+ return 1;
+ }
+
if(!strcmp(argv[0], "bugreport")) {
if (argc != 1) {
return 1;
diff --git a/adb/log_service.c b/adb/log_service.c
index 8edf98f..6e9bdee 100644
--- a/adb/log_service.c
+++ b/adb/log_service.c
@@ -22,7 +22,7 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
-#include <utils/logger.h>
+#include <cutils/logger.h>
#include "sysdeps.h"
#include "adb.h"
diff --git a/adb/services.c b/adb/services.c
index e686949..1de55e6 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -103,6 +103,34 @@
adb_close(fd);
}
+void restart_root_service(int fd, void *cookie)
+{
+ char buf[100];
+ char value[PROPERTY_VALUE_MAX];
+
+ if (getuid() == 0) {
+ snprintf(buf, sizeof(buf), "adbd is already running as root\n");
+ writex(fd, buf, strlen(buf));
+ adb_close(fd);
+ } else {
+ property_get("ro.debuggable", value, "");
+ if (strcmp(value, "1") != 0) {
+ snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
+ writex(fd, buf, strlen(buf));
+ return;
+ }
+
+ property_set("service.adb.root", "1");
+ snprintf(buf, sizeof(buf), "restarting adbd as root\n");
+ writex(fd, buf, strlen(buf));
+ adb_close(fd);
+
+ // quit, and init will restart us as root
+ sleep(1);
+ exit(1);
+ }
+}
+
#endif
#if 0
@@ -289,6 +317,8 @@
ret = create_service_thread(file_sync_service, NULL);
} else if(!strncmp(name, "remount:", 8)) {
ret = create_service_thread(remount_service, NULL);
+ } else if(!strncmp(name, "root:", 5)) {
+ ret = create_service_thread(restart_root_service, NULL);
#endif
#if 0
} else if(!strncmp(name, "echo:", 5)){
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 3feee07..32ce0a9 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -292,7 +292,8 @@
}
}
- register_device_callback(devname, local_ep_in, local_ep_out, i, serial, zero_mask);
+ register_device_callback(devname, local_ep_in, local_ep_out,
+ interface->bInterfaceNumber, serial, zero_mask);
found_device = 1;
break;
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 4079a38..e220dbe 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -195,7 +195,7 @@
"\n"
"commands:\n"
" update <filename> reflash device from update.zip\n"
- " flashall 'flash boot' + 'flash system'\n"
+ " flashall flash boot + recovery + system\n"
" flash <partition> [ <filename> ] write a file to a flash partition\n"
" erase <partition> erase a flash partition\n"
" getvar <variable> display a bootloader variable\n"
@@ -588,6 +588,9 @@
} else if(!strcmp(*argv, "reboot-bootloader")) {
wants_reboot_bootloader = 1;
skip(1);
+ } else if (!strcmp(*argv, "continue")) {
+ fb_queue_command("continue", "resuming boot");
+ skip(1);
} else if(!strcmp(*argv, "boot")) {
char *kname = 0;
char *rname = 0;
diff --git a/include/cutils/logger.h b/include/cutils/logger.h
new file mode 100644
index 0000000..3a08019
--- /dev/null
+++ b/include/cutils/logger.h
@@ -0,0 +1,46 @@
+/* utils/logger.h
+**
+** Copyright 2007, The Android Open Source Project
+**
+** This file is dual licensed. It may be redistributed and/or modified
+** under the terms of the Apache 2.0 License OR version 2 of the GNU
+** General Public License.
+*/
+
+#ifndef _UTILS_LOGGER_H
+#define _UTILS_LOGGER_H
+
+#include <stdint.h>
+
+struct logger_entry {
+ uint16_t len; /* length of the payload */
+ uint16_t __pad; /* no matter what, we get 2 bytes of padding */
+ int32_t pid; /* generating process's pid */
+ int32_t tid; /* generating process's tid */
+ int32_t sec; /* seconds since Epoch */
+ int32_t nsec; /* nanoseconds */
+ char msg[0]; /* the entry's payload */
+};
+
+#define LOGGER_LOG_MAIN "log/main"
+#define LOGGER_LOG_RADIO "log/radio"
+#define LOGGER_LOG_EVENTS "log/events"
+
+#define LOGGER_ENTRY_MAX_LEN (4*1024)
+#define LOGGER_ENTRY_MAX_PAYLOAD \
+ (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+
+#ifdef HAVE_IOCTL
+
+#include <sys/ioctl.h>
+
+#define __LOGGERIO 0xAE
+
+#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
+#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
+#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
+#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
+
+#endif // HAVE_IOCTL
+
+#endif /* _UTILS_LOGGER_H */
diff --git a/include/cutils/logprint.h b/include/cutils/logprint.h
index c010809..d6ec480 100644
--- a/include/cutils/logprint.h
+++ b/include/cutils/logprint.h
@@ -17,8 +17,8 @@
#ifndef _LOGPRINT_H
#define _LOGPRINT_H
-#include <utils/Log.h>
-#include <utils/logger.h>
+#include <cutils/log.h>
+#include <cutils/logger.h>
#include <cutils/event_tag_map.h>
#include <pthread.h>
diff --git a/include/pixelflinger/format.h b/include/pixelflinger/format.h
index 308e560..6b2050c 100644
--- a/include/pixelflinger/format.h
+++ b/include/pixelflinger/format.h
@@ -42,8 +42,10 @@
// YCbCr formats (SP=semi-planar, P=planar)
GGL_PIXEL_FORMAT_YCbCr_422_SP= 0x10,
GGL_PIXEL_FORMAT_YCbCr_420_SP= 0x11,
- GGL_PIXEL_FORMAT_YCbCr_422_P = 0x14,
- GGL_PIXEL_FORMAT_YCbCr_420_P = 0x15,
+ GGL_PIXEL_FORMAT_YCbCr_422_P = 0x12,
+ GGL_PIXEL_FORMAT_YCbCr_420_P = 0x13,
+ GGL_PIXEL_FORMAT_YCbCr_422_I = 0x14,
+ GGL_PIXEL_FORMAT_YCbCr_420_I = 0x15,
// reserved/special formats
GGL_PIXEL_FORMAT_Z_16 = 0x18,
@@ -60,7 +62,10 @@
GGL_RGBA = 0x1908,
GGL_LUMINANCE = 0x1909,
GGL_LUMINANCE_ALPHA = 0x190A,
- GGL_Y_CB_CR = 0x8000,
+ GGL_Y_CB_CR_SP = 0x8000,
+ GGL_Y_CB_CR = GGL_Y_CB_CR_SP,
+ GGL_Y_CB_CR_P = 0x8001,
+ GGL_Y_CB_CR_I = 0x8002,
};
enum GGLFormatComponentIndex {
diff --git a/init/devices.c b/init/devices.c
index efe3ad0..e0b1f1f 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -123,14 +123,13 @@
{ "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 },
+ { "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
+ { "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/htc-acoustic", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/snd/", 0664, AID_SYSTEM, AID_AUDIO, 1 },
{ NULL, 0, 0, 0, 0 },
};
diff --git a/init/property_service.c b/init/property_service.c
index 7a6416b..0bc6239 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -69,6 +69,7 @@
{ "dhcp.", AID_DHCP },
{ "debug.", AID_SHELL },
{ "log.", AID_SHELL },
+ { "service.adb.root", AID_SHELL },
{ "persist.sys.", AID_SYSTEM },
{ "persist.service.", AID_SYSTEM },
{ NULL, 0 }
diff --git a/libcutils/array.c b/libcutils/array.c
index ff2c8ff..55ec055 100644
--- a/libcutils/array.c
+++ b/libcutils/array.c
@@ -18,8 +18,10 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#define INITIAL_CAPACITY (4)
+#define MAX_CAPACITY ((int)(UINT_MAX/sizeof(void*)))
struct Array {
void** contents;
@@ -45,13 +47,26 @@
static int ensureCapacity(Array* array, int capacity) {
int oldCapacity = array->capacity;
if (capacity > oldCapacity) {
- int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity * 2;
-
- // Keep doubling capacity until we surpass necessary capacity.
+ int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity;
+
+ // Ensure we're not doing something nasty
+ if (capacity > MAX_CAPACITY)
+ return -1;
+
+ // Keep doubling capacity until we surpass necessary capacity.
while (newCapacity < capacity) {
- newCapacity *= 2;
+ int newCap = newCapacity*2;
+ // Handle integer overflows
+ if (newCap < newCapacity || newCap > MAX_CAPACITY) {
+ newCap = MAX_CAPACITY;
+ }
+ newCapacity = newCap;
}
-
+
+ // Should not happen, but better be safe than sorry
+ if (newCapacity < 0 || newCapacity > MAX_CAPACITY)
+ return -1;
+
void** newContents;
if (array->contents == NULL) {
// Allocate new array.
@@ -151,5 +166,5 @@
}
const void** arrayUnwrap(Array* array) {
- return array->contents;
+ return (const void**)array->contents;
}
diff --git a/libcutils/strdup8to16.c b/libcutils/strdup8to16.c
index 8654b04..63e5ca4 100644
--- a/libcutils/strdup8to16.c
+++ b/libcutils/strdup8to16.c
@@ -18,6 +18,7 @@
#include <cutils/jstring.h>
#include <assert.h>
#include <stdlib.h>
+#include <limits.h>
/* See http://www.unicode.org/reports/tr22/ for discussion
* on invalid sequences
@@ -48,6 +49,10 @@
len = strlen8to16(s);
+ // fail on overflow
+ if (len && SIZE_MAX/len < sizeof(char16_t))
+ return NULL;
+
// no plus-one here. UTF-16 strings are not null terminated
ret = (char16_t *) malloc (sizeof(char16_t) * len);
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index d9d67b4..ed9d699 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -438,31 +438,38 @@
if (*p++ == '\n') numLines++;
}
if (p > msg && *(p-1) != '\n') numLines++;
-
+
/*
* Create an array of iovecs large enough to write all of
* the lines with a prefix and a suffix.
*/
const size_t INLINE_VECS = 6;
+ const size_t MAX_LINES = ((size_t)~0)/(3*sizeof(struct iovec*));
struct iovec stackVec[INLINE_VECS];
struct iovec* vec = stackVec;
-
- numLines *= 3; // 3 iovecs per line.
- if (numLines > INLINE_VECS) {
+ size_t numVecs;
+
+ if (numLines > MAX_LINES)
+ numLines = MAX_LINES;
+
+ numVecs = numLines*3; // 3 iovecs per line.
+ if (numVecs > INLINE_VECS) {
vec = (struct iovec*)malloc(sizeof(struct iovec)*numLines);
if (vec == NULL) {
msg = "LOG: write failed, no memory";
- numLines = 3;
+ numVecs = 3;
+ numLines = 1;
+ vec = stackVec;
}
}
-
+
/*
* Fill in the iovec pointers.
*/
p = msg;
struct iovec* v = vec;
int totalLen = 0;
- while (p < end) {
+ while (numLines > 0 && p < end) {
if (prefixLen > 0) {
v->iov_base = prefixBuf;
v->iov_len = prefixLen;
@@ -484,6 +491,7 @@
totalLen += suffixLen;
v++;
}
+ numLines -= 1;
}
/*
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index e40d2ce..80867d1 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#include <stdarg.h>
-#include <utils/logger.h>
+#include <cutils/logger.h>
#include <cutils/logd.h>
#define LOG_BUF_SIZE 1024
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index ba98933..bad2e2f 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -170,14 +170,19 @@
*/
int dhcp_stop(const char *interface)
{
+ char result_prop_name[PROPERTY_KEY_MAX];
const char *ctrl_prop = "ctl.stop";
const char *desired_status = "stopped";
+ snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
+ DHCP_PROP_NAME_PREFIX,
+ interface);
/* Stop the daemon and wait until it's reported to be stopped */
property_set(ctrl_prop, DAEMON_NAME);
if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) {
return -1;
}
+ property_set(result_prop_name, "failed");
return 0;
}
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 63a5c84..0cc85d9 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -48,9 +48,7 @@
PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
endif
-LOCAL_SHARED_LIBRARIES := \
- libhardware_legacy \
- libcutils
+LOCAL_SHARED_LIBRARIES := libcutils
ifneq ($(TARGET_ARCH),arm)
# Required to define logging functions on the simulator.
@@ -68,11 +66,9 @@
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
ifneq ($(BUILD_TINY_ANDROID),true)
-# this is for some qemu-tracing cruft, which
-# 1. should not depend on libhardware
-# 2. should not be build except in emulator builds
-# but this at least stops it from breaking the tiny android build
-LOCAL_SHARED_LIBRARIES += libhardware
+# Really this should go away entirely or at least not depend on
+# libhardware, but this at least gets us built.
+LOCAL_SHARED_LIBRARIES += libhardware_legacy
LOCAL_CFLAGS += -DWITH_LIB_HARDWARE
endif
diff --git a/libpixelflinger/format.cpp b/libpixelflinger/format.cpp
index cbbd91a..161e6d6 100644
--- a/libpixelflinger/format.cpp
+++ b/libpixelflinger/format.cpp
@@ -40,12 +40,12 @@
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
- { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR },// PIXEL_FORMAT_YCbCr_422_SP
- { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR },// PIXEL_FORMAT_YCbCr_420_SP
- { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
- { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
- { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
- { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
+ { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_422_SP
+ { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_420_SP
+ { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_422_P
+ { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_420_P
+ { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_422_I
+ { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_420_I
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index 75b668d..f700306 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -1256,7 +1256,7 @@
void scanline_t32cb16(context_t* c)
{
int32_t x = c->iterators.xl;
- size_t ct = c->iterators.xr - x;
+ size_t ct = c->iterators.xr - x;
int32_t y = c->iterators.y;
surface_t* cb = &(c->state.buffers.color);
union {
@@ -1282,7 +1282,7 @@
ct--;
}
- while (ct > 0) {
+ while (ct >= 2) {
s = GGL_RGBA_TO_HOST( *src++ );
sR = (s >> ( 3))&0x1F;
sG = (s >> ( 8+2))&0x3F;
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 3ee051d..f9fd2c9 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -16,8 +16,6 @@
LOCAL_MODULE := event-log-tags
-#LOCAL_MODULE_TAGS := user development
-
# This will install the file in /system/etc
#
LOCAL_MODULE_CLASS := ETC
diff --git a/logcat/event-log-tags b/logcat/event-log-tags
index 3d977a5..28cad0a 100644
--- a/logcat/event-log-tags
+++ b/logcat/event-log-tags
@@ -58,6 +58,9 @@
# This is logged when the partial wake lock (keeping the device awake
# regardless of whether the screen is off) is acquired or released.
2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
+# This is logged when battery goes from discharging to charging.
+# It lets us count the total amount of time between charges and the discharge level
+2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
#
# Leave IDs through 2739 for more power logs
#
@@ -188,10 +191,23 @@
30030 am_create_service (Service Record|1|5),(Name|3),(Intent|3),(PID|1|5)
# A service is being destroyed
30031 am_destroy_service (Service Record|1|5),(Name|3),(PID|1|5)
+# A process has crashed too many times, it is being cleared
+30032 am_process_crashed_too_much (Name|3),(PID|1|5)
+# An unknown process is trying to attach to the activity manager
+30033 am_drop_process (PID|1|5)
+# A service has crashed too many times, it is being stopped
+30034 am_service_crashed_too_much (Crash Count|1|1),(Component Name|3),(PID|1|5)
+# A service is going to be restarted after its process went away
+30035 am_schedule_service_restart (Component Name|3),(Time|2|3)
+# A client was waiting for a content provider, but its process was lost
+30036 am_provider_lost_process (Package Name|3),(UID|1|5),(Name|3)
# Out of memory for surfaces.
31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
+# Re-connecting to input method service because we haven't received its interface
+32000 imf_force_reconnect_ime (IME|4),(Time Since Connect|2|3),(Showing|1|1)
+
# dvm_gc_info: LIST (LONG, LONG, LONG)
#
# First LONG:
@@ -295,19 +311,28 @@
# PDP Setup failures
50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
-# Call drops
+# Call drops
50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
# Data network registration failed after successful voice registration
50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
-# Suspicious status of data connection while radio poweroff
+# Suspicious status of data connection while radio poweroff
50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
+# PDP drop caused by network
+50109 pdp_network_drop (cid|1|5), (network_type|1|5)
+
# Do not change these names without updating tag in:
#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
+# db stats. 0 is query, 1 is write (may become more fine grained in the
+# future)
+52000 db_operation (name|3),(op_type|1|5),(time|2|3)
+
+# http request/response stats
+52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2)
60000 viewroot_draw (Draw time|1|3)
60001 viewroot_layout (Layout time|1|3)
60002 view_build_drawing_cache (View created drawing cache|1|5)
@@ -315,3 +340,7 @@
# 0 for screen off, 1 for screen on, 2 for key-guard done
70000 screen_toggled (screen_state|1|5)
+
+# browser stats for diary study
+70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
+70102 browser_double_tap_duration (duration|1|3),(time|2|3)
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index d9ca131..3130a1c 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -1,7 +1,6 @@
// Copyright 2006 The Android Open Source Project
-#include <utils/misc.h>
-#include <utils/logger.h>
+#include <cutils/logger.h>
#include <cutils/logd.h>
#include <cutils/sockets.h>
#include <cutils/logprint.h>
diff --git a/mountd/Android.mk b/mountd/Android.mk
index 2fb7640..16532fa 100644
--- a/mountd/Android.mk
+++ b/mountd/Android.mk
@@ -18,4 +18,5 @@
LOCAL_SHARED_LIBRARIES := libcutils
-include $(BUILD_EXECUTABLE)
+# disabled - we are using vold now instead
+# include $(BUILD_EXECUTABLE)
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7ff1a74..b2fe8cf 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -4,7 +4,6 @@
# files that live under /system/etc/...
copy_from := \
- etc/mountd.conf \
etc/dbus.conf \
etc/init.goldfish.sh \
etc/hosts
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3f8c6a0..a0d6c54 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -87,11 +87,15 @@
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40
+# Set timeout value for rmnet stats.
+ write /sys/devices/virtual/net/rmnet0/timeout_suspend 5000000
+
# Define the oom_adj values for the classes of processes that can be
# killed by the kernel. These are used in ActivityManagerService.
setprop ro.FOREGROUND_APP_ADJ 0
setprop ro.VISIBLE_APP_ADJ 1
setprop ro.SECONDARY_SERVER_ADJ 2
+ setprop ro.HOME_APP_ADJ 4
setprop ro.HIDDEN_APP_MIN_ADJ 7
setprop ro.CONTENT_PROVIDER_ADJ 14
setprop ro.EMPTY_APP_ADJ 15
@@ -101,14 +105,18 @@
setprop ro.FOREGROUND_APP_MEM 1536
setprop ro.VISIBLE_APP_MEM 2048
setprop ro.SECONDARY_SERVER_MEM 4096
+ setprop ro.HOME_APP_MEM 4096
setprop ro.HIDDEN_APP_MEM 5120
setprop ro.CONTENT_PROVIDER_MEM 5632
setprop ro.EMPTY_APP_MEM 6144
# Write value must be consistent with the above properties.
+# Note that the driver only supports 6 slots, so we have HOME_APP at the
+# same memory level as services.
write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15
write /proc/sys/vm/overcommit_memory 1
+ write /proc/sys/vm/min_free_order_shift 4
write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144
# Set init its forked children's oom_adj.
@@ -187,8 +195,11 @@
onrestart restart zygote
onrestart restart media
-service mountd /system/bin/mountd
- socket mountd stream 0660 root mount
+service vold /system/bin/vold
+ socket vold stream 0660 root mount
+
+#service mountd /system/bin/mountd
+# socket mountd stream 0660 root mount
service debuggerd /system/bin/debuggerd
@@ -217,8 +228,8 @@
user bluetooth
group bluetooth net_bt_admin
-#STOPSHIP: disable the verbose logging
-service hcid /system/bin/logwrapper /system/bin/hcid -d -s -n -f /etc/bluez/hcid.conf
+#STOPSHIP: dont use logwrapper in production
+service hcid /system/bin/logwrapper /system/bin/hcid -s -n -f /etc/bluez/hcid.conf
socket bluetooth stream 660 bluetooth bluetooth
socket dbus_bluetooth stream 660 bluetooth bluetooth
# init.rc does not yet support applying capabilities, so run as root and
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index b0c241e..5a8dc0b 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -41,6 +41,7 @@
printenv \
smd \
chmod \
+ chown \
mkdosfs \
netstat \
ioctl \
diff --git a/toolbox/chown.c b/toolbox/chown.c
new file mode 100644
index 0000000..13617db
--- /dev/null
+++ b/toolbox/chown.c
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <unistd.h>
+#include <time.h>
+
+int chown_main(int argc, char **argv)
+{
+ int i;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: chown <USER>[.GROUP] <FILE1> [FILE2] ...\n");
+ return 10;
+ }
+
+ // Copy argv[1] to 'user' so we can truncate it at the period
+ // if a group id specified.
+ char user[32];
+ char *group = NULL;
+ strncpy(user, argv[1], sizeof(user));
+ if ((group = strchr(user, '.')) != NULL) {
+ *group++ = '\0';
+ }
+
+ // Lookup uid (and gid if specified)
+ struct passwd *pw;
+ struct group *grp = NULL;
+ uid_t uid;
+ gid_t gid = -1; // passing -1 to chown preserves current group
+
+ pw = getpwnam(user);
+ if (pw == NULL) {
+ fprintf(stderr, "No such user '%s'\n", user);
+ return 10;
+ }
+ uid = pw->pw_uid;
+
+ if (group != NULL) {
+ grp = getgrnam(group);
+ if (grp == NULL) {
+ fprintf(stderr, "No such group '%s'\n", group);
+ return 10;
+ }
+ gid = grp->gr_gid;
+ }
+
+ for (i = 2; i < argc; i++) {
+ if (chown(argv[i], uid, gid) < 0) {
+ fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno));
+ return 10;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/toolbox/insmod.c b/toolbox/insmod.c
index d084403..44b9847 100644
--- a/toolbox/insmod.c
+++ b/toolbox/insmod.c
@@ -45,10 +45,12 @@
return buffer;
}
+#define min(x,y) ((x) < (y) ? (x) : (y))
int insmod_main(int argc, char **argv)
{
void *file;
- ssize_t size;
+ ssize_t size = 0;
+ char opts[1024];
int ret;
/* make sure we've got an argument */
@@ -64,9 +66,24 @@
return -1;
}
+ opts[0] = '\0';
+ if (argc > 2) {
+ int i, len;
+ char *end = opts + sizeof(opts) - 1;
+ char *ptr = opts;
+
+ for (i = 2; (i < argc) && (ptr < end); i++) {
+ len = min(strlen(argv[i]), end - ptr);
+ memcpy(ptr, argv[i], len);
+ ptr += len;
+ *ptr++ = ' ';
+ *ptr++ = '\0';
+ }
+ *(ptr - 1) = '\0';
+ }
+
/* pass it to the kernel */
- /* XXX options */
- ret = init_module(file, size, "");
+ ret = init_module(file, size, opts);
if (ret != 0) {
fprintf(stderr,
"insmod: init_module '%s' failed (%s)\n",
diff --git a/toolbox/mkdosfs.c b/toolbox/mkdosfs.c
index 9ba9409..744aad1 100644
--- a/toolbox/mkdosfs.c
+++ b/toolbox/mkdosfs.c
@@ -387,9 +387,8 @@
exit(1);
}
- lseek(fd1, 0, SEEK_SET);
- off_t length = lseek(fd1, 0, SEEK_END);
- fprintf(stderr, "lseek returned %ld\n", length);
+ lseek64(fd1, 0, SEEK_SET);
+ loff_t length = lseek64(fd1, 0, SEEK_END);
if (length > 0) {
bpb.bsec = length / bpb.bps;
bpb.spt = bpb.bsec;
@@ -615,8 +614,8 @@
fat == 32 && bpb.bkbs != MAXU16 &&
bss <= bpb.bkbs && x >= bpb.bkbs) {
x -= bpb.bkbs;
- if (!x && lseek(fd1, 0, SEEK_SET))
- fprintf(stderr, "lseek failed for %s\n", bname);
+ if (!x && lseek64(fd1, 0, SEEK_SET))
+ fprintf(stderr, "lseek64 failed for %s\n", bname);
}
if (opt_B && x < bss) {
if ((n = read(fd1, img, bpb.bps)) == -1)
diff --git a/toolbox/top.c b/toolbox/top.c
index 0f40a0c..dcc0843 100644
--- a/toolbox/top.c
+++ b/toolbox/top.c
@@ -41,15 +41,20 @@
struct cpu_info {
long unsigned utime, ntime, stime, itime;
+ long unsigned iowtime, irqtime, sirqtime;
};
+#define PROC_NAME_LEN 64
+#define THREAD_NAME_LEN 32
+
struct proc_info {
struct proc_info *next;
pid_t pid;
pid_t tid;
uid_t uid;
gid_t gid;
- char name[256];
+ char name[PROC_NAME_LEN];
+ char tname[THREAD_NAME_LEN];
char state;
long unsigned utime;
long unsigned stime;
@@ -69,7 +74,7 @@
#define die(...) { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); }
#define INIT_PROCS 50
-#define THREAD_MULT 4
+#define THREAD_MULT 8
static struct proc_info **old_procs, **new_procs;
static int num_old_procs, num_new_procs;
static struct proc_info *free_procs;
@@ -228,7 +233,8 @@
file = fopen("/proc/stat", "r");
if (!file) die("Could not open /proc/stat.\n");
- fscanf(file, "cpu %lu %lu %lu %lu", &new_cpu.utime, &new_cpu.ntime, &new_cpu.stime, &new_cpu.itime);
+ fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu", &new_cpu.utime, &new_cpu.ntime, &new_cpu.stime,
+ &new_cpu.itime, &new_cpu.iowtime, &new_cpu.irqtime, &new_cpu.sirqtime);
fclose(file);
proc_num = 0;
@@ -237,7 +243,9 @@
continue;
pid = atoi(pid_dir->d_name);
-
+
+ struct proc_info cur_proc;
+
if (!threads) {
proc = alloc_proc();
@@ -254,6 +262,12 @@
proc->num_threads = 0;
} else {
+ sprintf(filename, "/proc/%d/cmdline", pid);
+ read_cmdline(filename, &cur_proc);
+
+ sprintf(filename, "/proc/%d/status", pid);
+ read_status(filename, &cur_proc);
+
proc = NULL;
}
@@ -275,11 +289,9 @@
sprintf(filename, "/proc/%d/task/%d/stat", pid, tid);
read_stat(filename, proc);
- sprintf(filename, "/proc/%d/task/%d/cmdline", pid, tid);
- read_cmdline(filename, proc);
-
- sprintf(filename, "/proc/%d/task/%d/status", pid, tid);
- read_status(filename, proc);
+ strcpy(proc->name, cur_proc.name);
+ proc->uid = cur_proc.uid;
+ proc->gid = cur_proc.gid;
add_proc(proc_num++, proc);
} else {
@@ -315,8 +327,9 @@
if (!open_paren || !close_paren) return 1;
*open_paren = *close_paren = '\0';
- strcpy(proc->name, open_paren + 1);
-
+ strncpy(proc->tname, open_paren + 1, THREAD_NAME_LEN);
+ proc->tname[THREAD_NAME_LEN-1] = 0;
+
/* Scan rest of string. */
sscanf(close_paren + 1, " %c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
"%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld",
@@ -347,8 +360,11 @@
if (!file) return 1;
fgets(line, MAX_LINE, file);
fclose(file);
- if (strlen(line) > 0)
- strcpy(proc->name, line);
+ if (strlen(line) > 0) {
+ strncpy(proc->name, line, PROC_NAME_LEN);
+ proc->name[PROC_NAME_LEN-1] = 0;
+ } else
+ proc->name[0] = 0;
return 0;
}
@@ -391,16 +407,34 @@
}
}
- total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime)
- - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime);
+ total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime
+ + new_cpu.iowtime + new_cpu.irqtime + new_cpu.sirqtime)
+ - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime
+ + old_cpu.iowtime + old_cpu.irqtime + old_cpu.sirqtime);
qsort(new_procs, num_new_procs, sizeof(struct proc_info *), proc_cmp);
printf("\n\n\n");
+ printf("User %ld%%, System %ld%%, IOW %ld%%, IRQ %ld%%\n",
+ ((new_cpu.utime + new_cpu.ntime) - (old_cpu.utime + old_cpu.ntime)) * 100 / total_delta_time,
+ ((new_cpu.stime ) - (old_cpu.stime)) * 100 / total_delta_time,
+ ((new_cpu.iowtime) - (old_cpu.iowtime)) * 100 / total_delta_time,
+ ((new_cpu.irqtime + new_cpu.sirqtime)
+ - (old_cpu.irqtime + old_cpu.sirqtime)) * 100 / total_delta_time);
+ printf("User %ld + Nice %ld + Sys %ld + Idle %ld + IOW %ld + IRQ %ld + SIRQ %ld = %ld\n",
+ new_cpu.utime - old_cpu.utime,
+ new_cpu.ntime - old_cpu.ntime,
+ new_cpu.stime - old_cpu.stime,
+ new_cpu.itime - old_cpu.itime,
+ new_cpu.iowtime - old_cpu.iowtime,
+ new_cpu.irqtime - old_cpu.irqtime,
+ new_cpu.sirqtime - old_cpu.sirqtime,
+ total_delta_time);
+ printf("\n");
if (!threads)
printf("%5s %4s %1s %5s %7s %7s %-8s %s\n", "PID", "CPU%", "S", "#THR", "VSS", "RSS", "UID", "Name");
else
- printf("%5s %5s %4s %1s %7s %7s %-8s %s\n", "PID", "TID", "CPU%", "S", "VSS", "RSS", "UID", "Name");
+ printf("%5s %5s %4s %1s %7s %7s %-8s %-15s %s\n", "PID", "TID", "CPU%", "S", "VSS", "RSS", "UID", "Thread", "Proc");
for (i = 0; i < num_new_procs; i++) {
proc = new_procs[i];
@@ -423,10 +457,10 @@
}
if (!threads)
printf("%5d %3ld%% %c %5d %6ldK %6ldK %-8.8s %s\n", proc->pid, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads,
- proc->vss / 1024, proc->rss * getpagesize() / 1024, user_str, proc->name);
+ proc->vss / 1024, proc->rss * getpagesize() / 1024, user_str, proc->name[0] != 0 ? proc->name : proc->tname);
else
- printf("%5d %5d %3ld%% %c %6ldK %6ldK %-8.8s %s\n", proc->pid, proc->tid, proc->delta_time * 100 / total_delta_time, proc->state,
- proc->vss / 1024, proc->rss * getpagesize() / 1024, user_str, proc->name);
+ printf("%5d %5d %3ld%% %c %6ldK %6ldK %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->delta_time * 100 / total_delta_time, proc->state,
+ proc->vss / 1024, proc->rss * getpagesize() / 1024, user_str, proc->tname, proc->name);
}
}
diff --git a/vold/Android.mk b/vold/Android.mk
index 465849f..3dd9f87 100644
--- a/vold/Android.mk
+++ b/vold/Android.mk
@@ -1,7 +1,3 @@
-BUILD_VOLD := false
-
-ifeq ($(BUILD_VOLD),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -10,7 +6,6 @@
vold.c \
cmd_dispatch.c \
uevent.c \
- inotify.c \
mmc.c \
misc.c \
blkdev.c \
@@ -22,6 +17,9 @@
volmgr_ext3.c \
logwrapper.c \
ProcessKiller.c\
+ switch.c \
+ format.c \
+ devmapper.c
LOCAL_MODULE:= vold
@@ -32,5 +30,3 @@
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/vold/ProcessKiller.c b/vold/ProcessKiller.c
index eeaae04..fc3eb37 100644
--- a/vold/ProcessKiller.c
+++ b/vold/ProcessKiller.c
@@ -112,7 +112,7 @@
{
char name[PATH_MAX];
GetProcessName(pid, name);
- LOG_ERROR("process %s (%d) has open file %s\n", name, pid, link);
+ LOG_ERROR("process %s (%d) has open file %s", name, pid, link);
fileOpen = true;
}
}
@@ -140,7 +140,7 @@
{
char name[PATH_MAX];
GetProcessName(pid, name);
- LOG_ERROR("process %s (%d) has open file map for %s\n", name, pid, path);
+ LOG_ERROR("process %s (%d) has open file map for %s", name, pid, path);
mapOpen = true;
}
}
@@ -159,7 +159,7 @@
{
char name[PATH_MAX];
GetProcessName(pid, name);
- LOG_ERROR("process %s (%d) has %s in %s\n", name, pid, message, mountPoint);
+ LOG_ERROR("process %s (%d) has %s in %s", name, pid, message, mountPoint);
return true;
}
else
@@ -182,7 +182,7 @@
DIR* dir;
struct dirent* de;
- LOG_ERROR("KillProcessesWithOpenFiles %s\n", mountPoint);
+ LOG_ERROR("KillProcessesWithOpenFiles %s", mountPoint);
dir = opendir("/proc");
if (!dir) return;
@@ -205,14 +205,14 @@
for (i = 0; i < num_excluded; i++) {
if (pid == excluded[i]) {
- LOG_ERROR("I just need a little more TIME captain!\n");
+ LOG_ERROR("I just need a little more TIME captain!");
hit = true;
break;
}
}
if (!hit) {
- LOG_ERROR("Killing process %d\n", pid);
+ LOG_ERROR("Killing process %d", pid);
kill(pid, (sigkill ? SIGKILL : SIGTERM));
}
}
diff --git a/vold/blkdev.c b/vold/blkdev.c
index f7907b2..981d0f2 100644
--- a/vold/blkdev.c
+++ b/vold/blkdev.c
@@ -27,6 +27,7 @@
#include <sys/mman.h>
#include <linux/fs.h>
+#include <linux/msdos_fs.h>
#include "vold.h"
#include "blkdev.h"
@@ -37,158 +38,145 @@
static blkdev_list_t *list_root = NULL;
static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major,
- int minor, char *type, struct media *media, char *dev_fspath);
-static void blkdev_dev_fspath_set(blkdev_t *blk, char *dev_fspath);
+ int minor, char *type, struct media *media);
-int blkdev_handle_devicefile_removed(blkdev_t *blk, char *dev_fspath)
+static int fat_valid_media(unsigned char media)
+{
+ return 0xf8 <= media || media == 0xf0;
+}
+
+char *blkdev_get_devpath(blkdev_t *blk)
{
-#if DEBUG_BLKDEV
- LOG_VOL("blkdev_handle_devicefile_removed(%s):\n", dev_fspath);
-#endif
- blkdev_dev_fspath_set(blk, NULL);
- return 0;
+ char *dp = malloc(256);
+ sprintf(dp, "%s/vold/%d:%d", DEVPATH, blk->major, blk->minor);
+ return dp;
}
-int blkdev_handle_devicefile_created(blkdev_t *blk, char *dev_fspath)
+int blkdev_refresh(blkdev_t *blk)
{
- int rc = 0;
- blkdev_t *disk;
-
-#if DEBUG_BLKDEV
- LOG_VOL("blkdev_handle_devicefile_created(%s):\n", dev_fspath);
-#endif
+ int fd = 0;
+ char *devpath = NULL;
+ unsigned char *block = NULL;
+ int i, rc;
- if (!blk) {
- /*
- * This device does not yet have a backing blkdev associated with it.
- * Create a new one in the pending state and fill in the information
- * we have.
- */
- struct stat sbuf;
-
- if (stat(dev_fspath, &sbuf) < 0) {
- LOGE("Unable to stat device '%s' (%s)\n", dev_fspath, strerror(errno));
- return -errno;
- }
-
- int major = (sbuf.st_rdev & 0xfff00) >> 8;
- int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
-
- disk = blkdev_lookup_by_devno(major, 0);
-
- if (!disk) {
- /*
- * If there isn't a disk associated with this device, then
- * its not what we're looking for
- */
-#if DEBUG_BLKDEV
- LOG_VOL("Ignoring device file '%s' (no disk found)\n", dev_fspath);
-#endif
- return 0;
- }
-
- if (!(blk = blkdev_create_pending_partition(disk, dev_fspath, major,
- minor, disk->media))) {
- LOGE("Unable to create pending blkdev\n");
- return -1;
- }
- } else
- blkdev_dev_fspath_set(blk, dev_fspath);
+ if (!(block = malloc(512)))
+ goto out;
/*
- * If we're a disk, then read the partition table. Otherwise we're
- * a partition so get the partition type
+ * Get the device size
*/
- disk = blk->disk;
+ devpath = blkdev_get_devpath(blk);
- int fd;
-
- if ((fd = open(disk->dev_fspath, O_RDWR)) < 0) {
- LOGE("Unable to open device '%s' (%s)\n", disk->dev_fspath, strerror(errno));
+ if ((fd = open(devpath, O_RDONLY)) < 0) {
+ LOGE("Unable to open device '%s' (%s)", devpath, strerror(errno));
return -errno;
}
if (ioctl(fd, BLKGETSIZE, &blk->nr_sec)) {
- LOGE("Unable to get device size (%m)\n");
+ LOGE("Unable to get device size (%m)");
+ return -errno;
+ }
+ close(fd);
+ free(devpath);
+
+ /*
+ * Open the disk partition table
+ */
+ devpath = blkdev_get_devpath(blk->disk);
+ if ((fd = open(devpath, O_RDONLY)) < 0) {
+ LOGE("Unable to open device '%s' (%s)", devpath,
+ strerror(errno));
+ free(devpath);
return -errno;
}
-#if DEBUG_BLKDEV
- LOG_VOL("New device '%s' size = %u sectors\n", dev_fspath, blk->nr_sec);
-#endif
+ free(devpath);
- void *raw_pt;
- unsigned char *chr_pt;
- int i;
-
- raw_pt = chr_pt = mmap(NULL, 512, PROT_READ, MAP_PRIVATE, fd, 0);
- if (raw_pt == MAP_FAILED) {
- LOGE("Unable to mmap device paritition table (%m)\n");
- goto out_nommap;
+ if ((rc = read(fd, block, 512)) != 512) {
+ LOGE("Unable to read device partition table (%d, %s)",
+ rc, strerror(errno));
+ goto out;
}
+ /*
+ * If we're a disk, then process the partition table. Otherwise we're
+ * a partition so get the partition type
+ */
+
if (blk->type == blkdev_disk) {
blk->nr_parts = 0;
- if ((chr_pt[0x1fe] != 0x55) && (chr_pt[0x1ff] != 0xAA)) {
- LOG_VOL("Disk '%s' does not contain a partition table\n", dev_fspath);
+ if ((block[0x1fe] != 0x55) || (block[0x1ff] != 0xAA)) {
+ LOGI("Disk %d:%d does not contain a partition table",
+ blk->major, blk->minor);
goto out;
}
for (i = 0; i < 4; i++) {
struct dos_partition part;
- dos_partition_dec(raw_pt + DOSPARTOFF + i * sizeof(struct dos_partition), &part);
+ dos_partition_dec(block + DOSPARTOFF + i * sizeof(struct dos_partition), &part);
+ if (part.dp_flag != 0 && part.dp_flag != 0x80) {
+ struct fat_boot_sector *fb = (struct fat_boot_sector *) &block[0];
+
+ if (!i && fb->reserved && fb->fats && fat_valid_media(fb->media)) {
+ LOGI("Detected FAT filesystem in partition table");
+ break;
+ } else {
+ LOGI("Partition table looks corrupt");
+ break;
+ }
+ }
if (part.dp_size != 0 && part.dp_typ != 0)
blk->nr_parts++;
}
- LOG_VOL("Disk device '%s' (blkdev %s) contains %d partitions\n",
- dev_fspath, blk->devpath, blk->nr_parts);
} else if (blk->type == blkdev_partition) {
struct dos_partition part;
int part_no = blk->minor -1;
- dos_partition_dec(raw_pt + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
-
- if (!part.dp_typ)
- LOG_VOL("Warning - Partition device '%s' (blkdev %s) has no partition type set\n",
- dev_fspath, blk->devpath);
+ dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
blk->part_type = part.dp_typ;
-
- LOG_VOL("Partition device '%s' (blkdev %s) partition type 0x%x\n",
- dev_fspath, blk->devpath, blk->part_type);
- } else {
- LOGE("Bad blkdev type '%d'\n", blk->type);
- rc = -EINVAL;
- goto out;
}
out:
- munmap(raw_pt, 512);
- out_nommap:
- close(fd);
- return rc;
-}
-blkdev_t *blkdev_create_pending_partition(blkdev_t *disk, char *dev_fspath, int major,
- int minor, struct media *media)
-{
- return _blkdev_create(disk, NULL, major, minor, "partition", media, dev_fspath);
+ if (block)
+ free(block);
+
+ char tmp[255];
+ char tmp2[32];
+ sprintf(tmp, "%s (blkdev %d:%d), %u secs (%u MB)",
+ (blk->type == blkdev_disk ? "Disk" : "Partition"),
+ blk->major, blk->minor,
+ blk->nr_sec,
+ (uint32_t) (((uint64_t) blk->nr_sec * 512) / 1024) / 1024);
+
+ if (blk->type == blkdev_disk)
+ sprintf(tmp2, " %d partitions", blk->nr_parts);
+ else
+ sprintf(tmp2, " type 0x%x", blk->part_type);
+
+ strcat(tmp, tmp2);
+ LOGI(tmp);
+
+ close(fd);
+
+ return 0;
}
blkdev_t *blkdev_create(blkdev_t *disk, char *devpath, int major, int minor, struct media *media, char *type)
{
- return _blkdev_create(disk, devpath, major, minor, type, media, NULL);
+ return _blkdev_create(disk, devpath, major, minor, type, media);
}
static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major,
- int minor, char *type, struct media *media, char *dev_fspath)
+ int minor, char *type, struct media *media)
{
blkdev_t *new;
struct blkdev_list *list_entry;
if (disk && disk->type != blkdev_disk) {
- LOGE("Non disk parent specified for blkdev!\n");
+ LOGE("Non disk parent specified for blkdev!");
return NULL;
}
@@ -218,8 +206,6 @@
new->major = major;
new->minor = minor;
new->media = media;
- if (dev_fspath)
- new->dev_fspath = strdup(dev_fspath);
new->nr_sec = 0xffffffff;
if (disk)
@@ -227,12 +213,23 @@
else
new->disk = new; // Note the self disk pointer
+ /* Create device nodes */
+ char nodepath[255];
+ mode_t mode = 0666 | S_IFBLK;
+ dev_t dev = (major << 8) | minor;
+
+ sprintf(nodepath, "%s/vold/%d:%d", DEVPATH, major, minor);
+ if (mknod(nodepath, mode, dev) < 0) {
+ LOGE("Error making device nodes for '%s' (%s)",
+ nodepath, strerror(errno));
+ }
+
if (!strcmp(type, "disk"))
new->type = blkdev_disk;
else if (!strcmp(type, "partition"))
new->type = blkdev_partition;
else {
- LOGE("Unknown block device type '%s'\n", type);
+ LOGE("Unknown block device type '%s'", type);
new->type = blkdev_unknown;
}
@@ -258,8 +255,11 @@
if (blkdev->devpath)
free(blkdev->devpath);
- if (blkdev->dev_fspath)
- free(blkdev->dev_fspath);
+
+ char nodepath[255];
+ sprintf(nodepath, "%s/vold/%d:%d", DEVPATH, blkdev->major, blkdev->minor);
+ unlink(nodepath);
+
free(blkdev);
}
@@ -272,9 +272,6 @@
return list_scan->dev;
list_scan = list_scan->next;
}
-#if DEBUG_BLKDEV
- LOG_VOL("blkdev_lookup_by_path(): No blkdev found @ %s\n", devpath);
-#endif
return NULL;
}
@@ -288,32 +285,12 @@
return list_scan->dev;
list_scan = list_scan->next;
}
-#if DEBUG_BLKDEV
- LOG_VOL("blkdev_lookup_by_devno(): No blkdev found for %d.%d\n", maj, min);
-#endif
return NULL;
}
-blkdev_t *blkdev_lookup_by_dev_fspath(char *dev_fspath)
-{
- struct blkdev_list *list_scan = list_root;
-
- while (list_scan) {
- if (list_scan->dev->dev_fspath) {
- if (!strcmp(list_scan->dev->dev_fspath, dev_fspath))
- return list_scan->dev;
- }
-
- list_scan = list_scan->next;
- }
-// LOG_VOL("blkdev_lookup_by_devno(): No blkdev found for %d.%d\n", maj, min);
- return NULL;
-}
-
-
/*
- * Given a disk device, return the number of partitions yet to be
- * processed.
+ * Given a disk device, return the number of partitions which
+ * have yet to be processed.
*/
int blkdev_get_num_pending_partitions(blkdev_t *blk)
{
@@ -330,25 +307,13 @@
if (list_scan->dev->major != blk->major)
goto next;
- if (list_scan->dev->nr_sec != 0xffffffff)
+ if (list_scan->dev->nr_sec != 0xffffffff &&
+ list_scan->dev->devpath) {
num--;
+ }
next:
list_scan = list_scan->next;
}
return num;
}
-void blkdev_devpath_set(blkdev_t *blk, char *devpath)
-{
- blk->devpath = strdup(devpath);
-}
-
-static void blkdev_dev_fspath_set(blkdev_t *blk, char *dev_fspath)
-{
- if (dev_fspath)
- blk->dev_fspath = strdup(dev_fspath);
- else {
- free(blk->dev_fspath);
- blk->dev_fspath = NULL;
- }
-}
diff --git a/vold/blkdev.h b/vold/blkdev.h
index 7818419..e789739 100644
--- a/vold/blkdev.h
+++ b/vold/blkdev.h
@@ -41,7 +41,6 @@
int major;
int minor;
- char *dev_fspath;
};
struct blkdev_list {
@@ -56,11 +55,10 @@
blkdev_t *blkdev_create_pending_partition(blkdev_t *disk, char *dev_fspath, int major, int minor, struct media *media);
blkdev_t *blkdev_lookup_by_path(char *devpath);
blkdev_t *blkdev_lookup_by_devno(int maj, int min);
-blkdev_t *blkdev_lookup_by_dev_fspath(char *dev_fspath);
+char *blkdev_get_devpath(blkdev_t *blk);
+
void blkdev_destroy(blkdev_t *blk);
-int blkdev_handle_devicefile_created(blkdev_t *blk, char *dev_fspath);
-int blkdev_handle_devicefile_removed(blkdev_t *blk, char *dev_fspath);
int blkdev_get_num_pending_partitions(blkdev_t *blk);
-void blkdev_devpath_set(blkdev_t *blk, char *dev_fspath);
+int blkdev_refresh(blkdev_t *blk);
#endif
diff --git a/vold/cmd_dispatch.c b/vold/cmd_dispatch.c
index 1f48cfc..ab65fd9 100644
--- a/vold/cmd_dispatch.c
+++ b/vold/cmd_dispatch.c
@@ -33,13 +33,15 @@
static int do_set_ums_enable(char *cmd);
static int do_mount_volume(char *cmd);
static int do_eject_media(char *cmd);
+static int do_format_media(char *cmd);
static struct cmd_dispatch dispatch_table[] = {
{ VOLD_CMD_ENABLE_UMS, do_set_ums_enable },
{ VOLD_CMD_DISABLE_UMS, do_set_ums_enable },
{ VOLD_CMD_SEND_UMS_STATUS, do_send_ums_status },
- { VOLD_CMD_MOUNT_VOLUME, do_mount_volume },
+ { VOLD_CMD_MOUNT_VOLUME, do_mount_volume },
{ VOLD_CMD_EJECT_MEDIA, do_eject_media },
+ { VOLD_CMD_FORMAT_MEDIA, do_format_media },
{ NULL, NULL }
};
@@ -49,9 +51,10 @@
char buffer[101];
if ((rc = read(socket, buffer, sizeof(buffer) -1)) < 0) {
- LOGE("Unable to read framework command (%s)\n", strerror(errno));
+ LOGE("Unable to read framework command (%s)", strerror(errno));
return -errno;
- }
+ } else if (!rc)
+ return -ECONNRESET;
int start = 0;
int i;
@@ -71,7 +74,7 @@
{
struct cmd_dispatch *c;
- LOG_VOL("dispatch_cmd(%s):\n", cmd);
+ LOG_VOL("dispatch_cmd(%s):", cmd);
for (c = dispatch_table; c->cmd != NULL; c++) {
if (!strncmp(c->cmd, cmd, strlen(c->cmd))) {
@@ -80,7 +83,7 @@
}
}
- LOGE("No cmd handlers defined for '%s'\n", cmd);
+ LOGE("No cmd handlers defined for '%s'", cmd);
}
static int do_send_ums_status(char *cmd)
@@ -101,6 +104,11 @@
return volmgr_start_volume_by_mountpoint(&cmd[strlen("mount_volume:")]);
}
+static int do_format_media(char *cmd)
+{
+ return volmgr_format_volume(&cmd[strlen("format_media:")]);
+}
+
static int do_eject_media(char *cmd)
{
return volmgr_stop_volume_by_mountpoint(&cmd[strlen("eject_media:")]);
diff --git a/vold/cmd_dispatch.h b/vold/cmd_dispatch.h
index e88874e..f8ba6b3 100644
--- a/vold/cmd_dispatch.h
+++ b/vold/cmd_dispatch.h
@@ -26,5 +26,6 @@
// these commands should contain a volume mount point after the colon
#define VOLD_CMD_MOUNT_VOLUME "mount_volume:"
#define VOLD_CMD_EJECT_MEDIA "eject_media:"
+#define VOLD_CMD_FORMAT_MEDIA "format_media:"
#endif
diff --git a/vold/devmapper.c b/vold/devmapper.c
new file mode 100644
index 0000000..ef44c90
--- /dev/null
+++ b/vold/devmapper.c
@@ -0,0 +1,463 @@
+
+/*
+ * Copyright (C) 2008 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sched.h>
+#include <fcntl.h>
+
+#include <sys/mount.h>
+
+#include <linux/loop.h>
+#include <linux/dm-ioctl.h>
+
+#include <cutils/config_utils.h>
+#include <cutils/properties.h>
+
+#include "vold.h"
+#include "devmapper.h"
+
+#define DEBUG_DEVMAPPER 1
+
+static void *_align(void *ptr, unsigned int a)
+{
+ register unsigned long agn = --a;
+
+ return (void *) (((unsigned long) ptr + agn) & ~agn);
+}
+
+static struct dm_ioctl *_dm_ioctl_setup(struct devmapping *dm, int flags)
+{
+ void *buffer;
+ void *p;
+ const size_t min_size = 16 * 1024;
+ size_t len = sizeof(struct dm_ioctl);
+ struct dm_ioctl *io;
+ struct dm_target_spec *tgt;
+ int i;
+ char params[1024];
+ char key[80];
+
+ key[0] = '\0';
+ for (i = 0; i < (int) sizeof(dm->key); i++) {
+ char tmp[8];
+
+ sprintf(tmp, "%02x", dm->key[i]);
+ strcat(key, tmp);
+ }
+
+ char srcdev[128];
+
+ // XXX: Handle non crypt targets and non twofish (use param)
+ if (dm->src_type == dmsrc_loopback)
+ strcpy(srcdev, dm->type_data.loop.loop_dev);
+ else if (dm->src_type == dmsrc_partition)
+ strcpy(srcdev, dm->type_data.part.part_dev);
+
+ sprintf(params, "twofish %s 0 %s 0", key, srcdev);
+
+LOG_VOL("Params = '%s'", params);
+
+ if (len < min_size)
+ len = min_size;
+
+ if (!(buffer = malloc(len))) {
+ LOGE("out of memory");
+ return NULL;
+ }
+
+ memset(buffer, 0, len);
+ io = buffer;
+ tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
+
+ io->version[0] = 4;
+ io->version[1] = 0;
+ io->version[2] = 0;
+
+ io->data_size = len;
+ io->data_start = sizeof(struct dm_ioctl);
+
+ io->flags = flags;
+ io->dev = 0;
+
+ io->target_count = 1;
+ io->event_nr = 1;
+ strncpy(io->name, dm->target, sizeof(io->name));
+
+ tgt->status = 0;
+ tgt->sector_start = 0;
+ tgt->length = (dm->size_mb * (1024 * 1024)) / 512;
+ strncpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
+
+ p = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
+ strcpy((char *) p, params);
+ p+= strlen(params) + 1;
+
+ p = _align(p, 8);
+ tgt->next = p - buffer;
+
+ return io;
+}
+
+static int get_next_available_dm()
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ char path[255];
+ sprintf(path, "/dev/block/dm-%d", i);
+ if ((access(path, F_OK) < 0) && (errno == ENOENT))
+ return i;
+ }
+
+ LOGE("Out of device mapper numbers");
+ return -1;
+}
+
+static int create_devmapping(struct devmapping *dm)
+{
+ struct dm_ioctl *io;
+ int rc, fd;
+
+#if DEBUG_DEVMAPPER
+ LOG_VOL("create_devmapping():");
+#endif
+
+ if (dm->dm_no < 0) {
+ LOGE("Invalid dm_no set");
+ return -EINVAL;
+ }
+
+ if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+ LOGE("Error opening device mapper (%d)", errno);
+ return -errno;
+ }
+
+ if (!(io = _dm_ioctl_setup(dm, 0))) {
+ LOGE("Unable to setup ioctl (out of memory)");
+ close(fd);
+ return -ENOMEM;
+ }
+
+ if ((rc = ioctl(fd, DM_DEV_CREATE, io)) < 0) {
+ LOGE("device-mapper create ioctl failed (%d)", errno);
+ rc = -errno;
+ goto out_free;
+ }
+
+ free(io);
+
+ if (!(io = _dm_ioctl_setup(dm, DM_STATUS_TABLE_FLAG))) {
+ LOGE("Unable to setup ioctl (out of memory)");
+ rc = -ENOMEM;
+ goto out_nofree;
+ }
+
+ if ((rc = ioctl(fd, DM_TABLE_LOAD, io)) < 0) {
+ LOGE("device-mapper load ioctl failed (%d)", errno);
+ rc = -errno;
+ goto out_free;
+ }
+
+ free(io);
+
+ if (!(io = _dm_ioctl_setup(dm, 0))) {
+ LOGE("Unable to setup ioctl (out of memory)");
+ rc = -ENOMEM;
+ goto out_nofree;
+ }
+
+ if ((rc = ioctl(fd, DM_DEV_SUSPEND, io)) < 0) {
+ LOGE("device-mapper resume ioctl failed (%d)", errno);
+ rc = -errno;
+ goto out_free;
+ }
+
+out_free:
+ free (io);
+out_nofree:
+ close (fd);
+ return rc;
+}
+
+static int loopback_start(struct devmapping *dm)
+{
+ int i;
+ int fd;
+ char filename[255];
+ int rc;
+
+#if DEBUG_DEVMAPPER
+ LOG_VOL("loopback_start(%s):", dm->type_data.loop.loop_src);
+#endif
+
+ for (i = 0; i < MAX_LOOP; i++) {
+ struct loop_info info;
+
+ sprintf(filename, "/dev/block/loop%d", i);
+
+ if ((fd = open(filename, O_RDWR)) < 0) {
+ LOGE("Unable to open %s (%s)", filename, strerror(errno));
+ return -errno;
+ }
+
+ rc = ioctl(fd, LOOP_GET_STATUS, &info);
+ if (rc < 0 && errno == ENXIO)
+ break;
+
+ close(fd);
+
+ if (rc < 0) {
+ LOGE("Unable to get loop status for %s (%s)", filename,
+ strerror(errno));
+ return -errno;
+ }
+ }
+
+ if (i == MAX_LOOP) {
+ LOGE("Out of loop devices");
+ return -ENOSPC;
+ }
+
+ int file_fd;
+
+ if ((file_fd = open(dm->type_data.loop.loop_src, O_RDWR)) < 0) {
+ LOGE("Unable to open %s (%s)", dm->type_data.loop.loop_src,
+ strerror(errno));
+ return -errno;
+ }
+
+ if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) {
+ LOGE("Error setting up loopback interface (%s)", strerror(errno));
+ return -errno;
+ }
+
+ dm->type_data.loop.loop_dev = strdup(filename);
+ dm->type_data.loop.loop_no = i;
+
+ close(fd);
+ close(file_fd);
+
+#if DEBUG_DEVMAPPER
+ LOG_VOL("Loop setup on %s for %s", dm->type_data.loop.loop_dev,
+ dm->type_data.loop.loop_src);
+#endif
+
+ return 0;
+}
+
+int devmapper_start(struct devmapping *dm)
+{
+ int rc;
+ char src_blkdev_path[255];
+
+#if DEBUG_DEVMAPPER
+ LOG_VOL("devmapper_start()");
+#endif
+
+ if (dm->src_type == dmsrc_loopback) {
+ if ((rc = loopback_start(dm)) < 0)
+ return rc;
+ } else if (dm->src_type == dmsrc_partition) {
+ LOGE("partition maps not yet supported");
+ return -ENOSYS;
+ } else {
+ LOGE("devmapper_start(): Unsupported source type '%d'", dm->src_type);
+ return -ENOENT;
+ }
+
+ /*
+ * Configure the device mapper
+ */
+ if ((rc = create_devmapping(dm)) < 0) {
+ LOGE("Failed to create devmapping (%d)", rc);
+ // XXX: if loopback then tear down
+ return rc;
+ }
+
+ return 0;
+}
+
+struct devmapping *devmapper_init(char *src, char *src_type, uint32_t size_mb,
+ char *target, char *params, char *tgt_fs, char *mediapath)
+{
+ struct devmapping *dm;
+
+ if (!(dm = malloc(sizeof(struct devmapping)))) {
+ LOGE("devmapper_init(): out of memory");
+ return NULL;
+ }
+
+ memset(dm, 0, sizeof(struct devmapping));
+
+ if (!strcmp(src_type, "loopback_file")) {
+ dm->src_type = dmsrc_loopback;
+ dm->type_data.loop.loop_src = strdup(src);
+ } else if (!strncmp(src_type, "partition ", strlen("partition "))) {
+ dm->src_type = dmsrc_partition;
+ char *p = strtok(src_type, " ");
+ if (!p) {
+ LOGE("Invalid partition specifier");
+ goto out_free;
+ }
+ dm->type_data.part.part_type = strtoul(p, NULL, 0);
+ } else {
+ LOGE("Invalid src_type defined (%s)", src_type);
+ goto out_free;
+ }
+
+ // XXX: Validate these
+ dm->size_mb = size_mb;
+ dm->target = strdup(target);
+ dm->params = strdup(params);
+ dm->tgt_fs = strdup(tgt_fs);
+
+ if ((dm->dm_no = get_next_available_dm()) < 0)
+ goto out_free;
+
+ sprintf(mediapath, "/devices/virtual/block/dm-%d", dm->dm_no);
+
+ if (!(dm->media = media_create(mediapath,
+ "unknown",
+ "unknown",
+ media_devmapper))) {
+ LOGE("Unable to create media");
+ goto out_free;
+ }
+
+ return dm;
+ out_free:
+ if (dm->target)
+ free(dm->target);
+ if (dm->params)
+ free(dm->params);
+ if (dm->tgt_fs)
+ free(dm->tgt_fs);
+
+ free(dm);
+ return NULL;
+}
+
+int devmapper_genesis(struct devmapping *dm)
+{
+
+ if (dm->src_type == dmsrc_loopback) {
+ int fd;
+
+ LOG_VOL("devmapper_genesis(): Working on %s",
+ dm->type_data.loop.loop_src);
+
+ unlink(dm->type_data.loop.loop_src);
+
+ LOG_VOL("devmapper_genesis(): Creating imagefile (%u MB)",
+ dm->size_mb);
+
+ if ((fd = creat(dm->type_data.loop.loop_src, 0600)) < 0) {
+ LOGE("Error creating imagefile (%s)", strerror(errno));
+ return -errno;
+ }
+
+ if (ftruncate(fd, (dm->size_mb * (1024 * 1024))) < 0) {
+ LOGE("Error truncating imagefile (%s)", strerror(errno));
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+ } else if (dm->src_type == dmsrc_partition) {
+ LOGE("partition maps not yet supported");
+ return -ENOSYS;
+ }
+
+ return devmapper_start(dm);
+}
+
+static int destroy_devmapping(struct devmapping *dm)
+{
+ struct dm_ioctl *io;
+ int dmFd;
+ int rc = 0;
+
+ LOG_VOL("destroy_devmapping():");
+
+ if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
+ LOGE("Error opening device mapper (%d)", errno);
+ return -errno;
+ }
+
+ if (!(io = _dm_ioctl_setup(dm, DM_PERSISTENT_DEV_FLAG))) {
+ LOGE("Unable to setup ioctl (out of memory)");
+ rc = -ENOMEM;
+ goto out_nofree;
+ }
+
+ if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) {
+ LOGE("device-mapper remove ioctl failed (%d)", errno);
+ rc = -errno;
+ goto out_free;
+ }
+
+out_free:
+ free (io);
+out_nofree:
+ close (dmFd);
+ return rc;
+}
+
+static int loopback_stop(struct devmapping *dm)
+{
+ char devname[255];
+ int device_fd;
+ int rc = 0;
+
+ LOG_VOL("loopback_stop():");
+
+ device_fd = open(dm->type_data.loop.loop_dev, O_RDONLY);
+ if (device_fd < 0) {
+ LOG_ERROR("Failed to open loop (%d)", errno);
+ return -errno;
+ }
+
+ if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
+ LOG_ERROR("Failed to destroy loop (%d)", errno);
+ rc = -errno;
+ }
+
+ close(device_fd);
+ return rc;
+}
+
+int devmapper_stop(struct devmapping *dm)
+{
+ int rc;
+
+ LOG_VOL("devmapper_stop():");
+
+ if ((rc = destroy_devmapping(dm)))
+ return rc;
+
+ if (dm->src_type == dmsrc_loopback) {
+ if ((rc = loopback_stop(dm)))
+ return rc;
+ } else if (dm->src_type == dmsrc_partition) {
+ LOGE("partition maps not yet supported");
+ return -ENOSYS;
+ }
+ return 0;
+}
diff --git a/vold/devmapper.h b/vold/devmapper.h
new file mode 100644
index 0000000..3d8cab3
--- /dev/null
+++ b/vold/devmapper.h
@@ -0,0 +1,70 @@
+
+/*
+ * Copyright (C) 2008 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 _DEVMAPPER_H
+#define _DEVMAPPER_H
+
+#include <pthread.h>
+
+#include "vold.h"
+#include "blkdev.h"
+#include "media.h"
+
+#define MAX_LOOP 8
+
+enum dm_src_type {
+ dmsrc_unknown,
+ dmsrc_loopback,
+ dmsrc_partition,
+};
+
+struct loop_data {
+ char *loop_src;
+
+ char *loop_dev;
+ int loop_no;
+};
+
+struct part_data {
+ char part_type;
+
+ char *part_dev;
+};
+
+struct devmapping {
+ enum dm_src_type src_type;
+ union {
+ struct loop_data loop;
+ struct part_data part;
+ } type_data;
+
+ uint32_t size_mb;
+ char *target;
+ char *params;
+ char *tgt_fs;
+
+ unsigned char key[16];
+ int dm_no;
+
+ media_t *media;
+};
+
+struct devmapping *devmapper_init(char *, char *, unsigned int, char *, char *, char *, char *);
+int devmapper_start(struct devmapping *);
+int devmapper_stop(struct devmapping *);
+int devmapper_genesis(struct devmapping *);
+#endif
diff --git a/vold/format.c b/vold/format.c
new file mode 100755
index 0000000..dd0515c
--- /dev/null
+++ b/vold/format.c
@@ -0,0 +1,113 @@
+
+/*
+ * Copyright (C) 2008 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 <fcntl.h>
+#include <errno.h>
+
+#include <linux/fs.h>
+
+#include "vold.h"
+#include "blkdev.h"
+#include "format.h"
+#include "diskmbr.h"
+#include "logwrapper.h"
+
+static char MKDOSFS_PATH[] = "/system/bin/mkdosfs";
+static char MKE2FS_PATH[] = "/system/bin/mke2fs";
+
+int format_partition(blkdev_t *part, char *type)
+{
+ char *devpath;
+ int rc = -EINVAL;
+
+ devpath = blkdev_get_devpath(part);
+
+ if (!strcmp(type, FORMAT_TYPE_FAT32)) {
+ char *args[7];
+ args[0] = MKDOSFS_PATH;
+ args[1] = "-F 32";
+ args[2] = "-c 32";
+ args[3] = "-n 2";
+ args[4] = "-O android";
+ args[5] = devpath;
+ args[6] = NULL;
+ rc = logwrap(6, args);
+ } else {
+ char *args[7];
+ args[0] = MKE2FS_PATH;
+ args[1] = "-b 4096";
+ args[2] = "-m 1";
+ args[3] = "-L android";
+ args[4] = "-v";
+ args[5] = devpath;
+ args[6] = NULL;
+ rc = logwrap(6, args);
+ }
+
+ free(devpath);
+
+ if (rc == 0) {
+ LOG_VOL("Filesystem formatted OK");
+ return 0;
+ } else {
+ LOGE("Format failed (unknokwn exit code %d)", rc);
+ return -EIO;
+ }
+ return 0;
+}
+
+int initialize_mbr(blkdev_t *disk)
+{
+ int fd, rc;
+ unsigned char block[512];
+ struct dos_partition part;
+ char *devpath;
+
+ devpath = blkdev_get_devpath(disk);
+
+ memset(&part, 0, sizeof(part));
+ part.dp_flag = 0x80;
+ part.dp_typ = 0xc;
+ part.dp_start = ((1024 * 64) / 512) + 1;
+ part.dp_size = disk->nr_sec - part.dp_start;
+
+ memset(block, 0, sizeof(block));
+ block[0x1fe] = 0x55;
+ block[0x1ff] = 0xaa;
+
+ dos_partition_enc(block + DOSPARTOFF, &part);
+
+ if ((fd = open(devpath, O_RDWR)) < 0) {
+ LOGE("Error opening disk file (%s)", strerror(errno));
+ return -errno;
+ }
+ free(devpath);
+
+ if (write(fd, block, sizeof(block)) < 0) {
+ LOGE("Error writing MBR (%s)", strerror(errno));
+ close(fd);
+ return -errno;
+ }
+
+ if (ioctl(fd, BLKRRPART, NULL) < 0) {
+ LOGE("Error re-reading partition table (%s)", strerror(errno));
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+ return 0;
+}
diff --git a/vold/inotify.h b/vold/format.h
similarity index 76%
copy from vold/inotify.h
copy to vold/format.h
index ada42a8..73cc012 100644
--- a/vold/inotify.h
+++ b/vold/format.h
@@ -15,8 +15,12 @@
* limitations under the License.
*/
-#ifndef _INOTIFY_EVT_H
-#define _INOTIFY_EVT_H
+#ifndef _FORMAT_H
+#define _FORMAT_H
+#define FORMAT_TYPE_EXT2 "ext2"
+#define FORMAT_TYPE_FAT32 "fat32"
+int format_partition(blkdev_t *part, char *type);
+int initialize_mbr(blkdev_t *disk);
#endif
diff --git a/vold/geom_mbr_enc.c b/vold/geom_mbr_enc.c
index 755fbba..f1f8339 100644
--- a/vold/geom_mbr_enc.c
+++ b/vold/geom_mbr_enc.c
@@ -44,6 +44,17 @@
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
}
+static __inline void
+le32enc(void *pp, uint32_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+ p[2] = (u >> 16) & 0xff;
+ p[3] = (u >> 24) & 0xff;
+}
+
void
dos_partition_dec(void const *pp, struct dos_partition *d)
{
@@ -60,3 +71,20 @@
d->dp_start = le32dec(p + 8);
d->dp_size = le32dec(p + 12);
}
+
+void
+dos_partition_enc(void *pp, struct dos_partition *d)
+{
+ unsigned char *p = pp;
+
+ p[0] = d->dp_flag;
+ p[1] = d->dp_shd;
+ p[2] = d->dp_ssect;
+ p[3] = d->dp_scyl;
+ p[4] = d->dp_typ;
+ p[5] = d->dp_ehd;
+ p[6] = d->dp_esect;
+ p[7] = d->dp_ecyl;
+ le32enc(p + 8, d->dp_start);
+ le32enc(p + 12, d->dp_size);
+}
diff --git a/vold/inotify.c b/vold/inotify.c
deleted file mode 100644
index a7b789c..0000000
--- a/vold/inotify.c
+++ /dev/null
@@ -1,270 +0,0 @@
-
-/*
- * Copyright (C) 2008 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 <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/inotify.h>
-#include <sys/stat.h>
-
-#include "vold.h"
-#include "inotify.h"
-#include "blkdev.h"
-#include "volmgr.h"
-
-#define DEBUG_INOTIFY 0
-
-static int handle_inotify_event(struct inotify_event *evt);
-
-int process_inotify_event(int fd)
-{
- char buffer[512];
- int len;
- int offset = 0;
-
- if ((len = read(fd, buffer, sizeof(buffer))) < 0) {
- LOGE("Unable to read inotify event (%m)\n");
- return -errno;
- }
-
- while (len >= (int) sizeof(struct inotify_event)) {
- struct inotify_event *evt = (struct inotify_event *) &buffer[offset];
-
- if (handle_inotify_event(evt) < 0)
- LOGE("Error handling inotify event (%m)\n");
-
- len -= sizeof(struct inotify_event) + evt->len;
- offset += sizeof(struct inotify_event) + evt->len;
-
- }
- return 0;
-}
-
-struct blk_dev_entry {
- int minor;
- char *name;
- struct blk_dev_entry *next;
-};
-
-int inotify_bootstrap(void)
-{
- DIR *d;
- struct dirent *de;
-
- if (!(d = opendir(DEVPATH))) {
- LOGE("Unable to open directory '%s' (%m)\n", DEVPATH);
- return -errno;
- }
-
- struct blk_dev_entry *blkdevs[255];
-
- memset(blkdevs, 0, sizeof(blkdevs));
-
- while((de = readdir(d))) {
- char filename[255];
- struct stat sbuf;
-
- if (de->d_name[0] == '.')
- continue;
-
- sprintf(filename, "%s/%s", DEVPATH, de->d_name);
-
- if (stat(filename, &sbuf) < 0) {
- LOGE("Unable to stat '%s' (%m)\n", filename);
- continue;
- }
-
- if (!S_ISBLK(sbuf.st_mode))
- continue;
-
-
- int major = (sbuf.st_rdev & 0xfff00) >> 8;
- int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
-
- struct blk_dev_entry *entry;
-
- if (!(entry = malloc(sizeof(struct blk_dev_entry)))) {
- LOGE("Out of memory\n");
- break;
- }
- entry->minor = minor;
- entry->name = strdup(de->d_name);
- entry->next = NULL;
-
- if (!blkdevs[major])
- blkdevs[major] = entry;
- else {
- struct blk_dev_entry *scan = blkdevs[major];
-
- /*
- * Insert the entry in minor number ascending order
- */
- while(scan) {
- if (minor < scan->minor) {
- entry->next = scan;
-
- if (scan == blkdevs[major])
- blkdevs[major] = entry;
- else
- scan->next = entry;
- break;
- }
- scan = scan->next;
- }
- if (!scan) {
- scan = blkdevs[major];
- while(scan->next)
- scan = scan->next;
- scan->next = entry;
- }
- }
-
- }
-
- closedir(d);
-
- int i = 0;
-
- for (i = 0; i < 255; i++) {
- if (!blkdevs[i])
- continue;
- struct blk_dev_entry *scan = blkdevs[i];
-
- while(scan) {
- struct inotify_event *evt;
- int len;
-
- len = sizeof(struct inotify_event) + strlen(scan->name);
-
- if (!(evt = malloc(len))) {
- LOGE("Out of memory\n");
- break;
- }
- memset(evt, 0, len);
- strcpy(evt->name, scan->name);
- evt->mask = IN_CREATE;
-
- if (handle_inotify_event(evt) < 0)
- LOGE("Error handling bootstrapped inotify event (%m)\n");
- free(evt);
-
- scan = scan->next;
- }
- }
-
- for (i = 0; i < 255; i++) {
- if (!blkdevs[i])
- continue;
-
- if (!blkdevs[i]->next) {
- free(blkdevs[i]->name);
- free(blkdevs[i]);
- blkdevs[i] = NULL;
- continue;
- }
-
- struct blk_dev_entry *scan = blkdevs[i];
- while(scan) {
- struct blk_dev_entry *next = scan->next->next;
-
- free(scan->next->name);
- free(scan->next);
-
- scan->next = next;
- scan = next;
- }
-
- } // for
-
-
- return 0;
-}
-
-static int handle_inotify_event(struct inotify_event *evt)
-{
- char filename[255];
- int rc;
-
-#if DEBUG_INOTIFY
- LOG_VOL("Inotify '%s' %s\n", evt->name, (evt->mask == IN_CREATE ? "created" : "deleted"));
-#endif
-
- sprintf(filename, "%s%s", DEVPATH, evt->name);
-
- if (evt->mask == IN_CREATE) {
- struct stat sbuf;
-
- if (stat(filename, &sbuf) < 0) {
- LOGE("Unable to stat '%s' (%m)\n", filename);
- return -errno;
- }
-
- if (!S_ISBLK(sbuf.st_mode)) {
-#if DEBUG_INOTIFY
- LOG_VOL("Ignoring inotify on '%s' (not a block device)\n", evt->name);
-#endif
- return 0;
- }
-
- int major = (sbuf.st_rdev & 0xfff00) >> 8;
- int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
-
- blkdev_t *blkdev = blkdev_lookup_by_devno(major, minor);
-
- if ((rc = blkdev_handle_devicefile_created(blkdev, filename)) < 0) {
- LOGE("Error handling device file '%s' creation (%s)\n", filename, strerror(rc));
- return rc;
- }
-
- if (!blkdev) {
-#if DEBUG_INOTIFY
- LOG_VOL("No backing blkdev for '%s' available (yet) - pending volmgr dispatch\n", filename);
-#endif
- return 0;
- }
-
-#if DEBUG_INOTIFY
- LOG_VOL("NUM_PENDING_PARTITIONS = %d\n", blkdev_get_num_pending_partitions(blkdev));
-#endif
- if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
- if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
- LOGE("Error from volmgr - %d\n", rc);
- return rc;
- }
- }
- } else {
- blkdev_t *blkdev;
-
- if (!(blkdev = blkdev_lookup_by_dev_fspath(filename))) {
-#if DEBUG_INOTIFY
- LOG_VOL("Ignoring removal of '%s' (no backend blkdev)\n", filename);
-#endif
- return 0;
- }
-
- if ((rc = blkdev_handle_devicefile_removed(blkdev, filename)) < 0) {
- LOGE("Error handling device file '%s' removal (%s)\n", filename, strerror(rc));
- return rc;
- }
- }
-
- return 0;
-}
diff --git a/vold/logwrapper.c b/vold/logwrapper.c
index f803dba..25d2281 100644
--- a/vold/logwrapper.c
+++ b/vold/logwrapper.c
@@ -95,7 +95,7 @@
// XXX: PROTECT FROM VIKING KILLER
if (execvp(argv_child[0], argv_child)) {
LOG(LOG_ERROR, "logwrapper",
- "executing %s failed: %s\n", argv_child[0], strerror(errno));
+ "executing %s failed: %s", argv_child[0], strerror(errno));
exit(-1);
}
}
@@ -111,24 +111,24 @@
/* Use ptty instead of socketpair so that STDOUT is not buffered */
parent_ptty = open("/dev/ptmx", O_RDWR);
if (parent_ptty < 0) {
- LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty\n");
+ LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
return -errno;
}
if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
- LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx\n");
+ LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
return -1;
}
pid = fork();
if (pid < 0) {
- LOG(LOG_ERROR, "logwrapper", "Failed to fork\n");
+ LOG(LOG_ERROR, "logwrapper", "Failed to fork");
return -errno;
} else if (pid == 0) {
child_ptty = open(child_devname, O_RDWR);
if (child_ptty < 0) {
- LOG(LOG_ERROR, "logwrapper", "Problem with child ptty\n");
+ LOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
return -errno;
}
diff --git a/vold/media.c b/vold/media.c
index f385586..db42a3e 100644
--- a/vold/media.c
+++ b/vold/media.c
@@ -85,8 +85,8 @@
free(media->devpath);
free(media->name);
- if (media->devs)
- LOGE("media_destroy(): media still has blkdevs associated with it! Possible leak\n");
+ while(media->devs)
+ media_remove_blkdev(media, media->devs->dev);
free(media);
}
@@ -105,7 +105,7 @@
list_scan = list_scan->next;
}
#if DEBUG_MEDIA
- LOG_VOL("media_lookup_by_path(): No media found @ %s\n", devpath);
+ LOG_VOL("media_lookup_by_path(): No media found @ %s", devpath);
#endif
return NULL;
}
@@ -114,10 +114,8 @@
{
blkdev_list_t *list_entry;
- if (!(list_entry = malloc(sizeof(blkdev_list_t)))) {
- LOGE("Out of memory\n");
+ if (!(list_entry = malloc(sizeof(blkdev_list_t))))
return -ENOMEM;
- }
list_entry->next = NULL;
list_entry->dev = dev;
diff --git a/vold/media.h b/vold/media.h
index 84c3947..567ce04 100644
--- a/vold/media.h
+++ b/vold/media.h
@@ -25,7 +25,7 @@
typedef enum media_type {
media_unknown,
media_mmc,
- media_dm
+ media_devmapper,
} media_type_t;
typedef struct media {
diff --git a/vold/mmc.c b/vold/mmc.c
index a4c93c5..0f08964 100644
--- a/vold/mmc.c
+++ b/vold/mmc.c
@@ -43,7 +43,7 @@
struct dirent *de;
if (!(d = opendir(SYSFS_CLASS_MMC_PATH))) {
- LOG_ERROR("Unable to open '%s' (%m)\n", SYSFS_CLASS_MMC_PATH);
+ LOG_ERROR("Unable to open '%s' (%m)", SYSFS_CLASS_MMC_PATH);
return -errno;
}
@@ -55,7 +55,7 @@
sprintf(tmp, "%s/%s", SYSFS_CLASS_MMC_PATH, de->d_name);
if (mmc_bootstrap_controller(tmp))
- LOG_ERROR("Error bootstrapping controller '%s' (%m)\n", tmp);
+ LOG_ERROR("Error bootstrapping controller '%s' (%m)", tmp);
}
closedir(d);
@@ -69,10 +69,10 @@
struct dirent *de;
#if DEBUG_BOOTSTRAP
- LOG_VOL("bootstrap_controller(%s):\n", sysfs_path);
+ LOG_VOL("bootstrap_controller(%s):", sysfs_path);
#endif
if (!(d = opendir(sysfs_path))) {
- LOG_ERROR("Unable to open '%s' (%m)\n", sysfs_path);
+ LOG_ERROR("Unable to open '%s' (%m)", sysfs_path);
return -errno;
}
@@ -92,7 +92,7 @@
sprintf(tmp, "%s/%s", sysfs_path, de->d_name);
if (mmc_bootstrap_card(tmp) < 0)
- LOG_ERROR("Error bootstrapping card '%s' (%m)\n", tmp);
+ LOG_ERROR("Error bootstrapping card '%s' (%m)", tmp);
} // while
closedir(d);
@@ -111,29 +111,29 @@
ssize_t sz;
#if DEBUG_BOOTSTRAP
- LOG_VOL("bootstrap_card(%s):\n", sysfs_path);
+ LOG_VOL("bootstrap_card(%s):", sysfs_path);
#endif
/*
* sysfs_path is based on /sys/class, but we want the actual device class
*/
if (!getcwd(saved_cwd, sizeof(saved_cwd))) {
- LOGE("Buffer too small for working dir path\n");
+ LOGE("Error getting working dir path");
return -errno;
}
if (chdir(sysfs_path) < 0) {
- LOGE("Unable to chdir to %s (%m)\n", sysfs_path);
+ LOGE("Unable to chdir to %s (%m)", sysfs_path);
return -errno;
}
if (!getcwd(new_cwd, sizeof(new_cwd))) {
- LOGE("Buffer too small for device path\n");
+ LOGE("Buffer too small for device path");
return -errno;
}
if (chdir(saved_cwd) < 0) {
- LOGE("Unable to restore working dir\n");
+ LOGE("Unable to restore working dir");
return -errno;
}
@@ -162,7 +162,7 @@
uevent_params[3] = (char *) NULL;
if (simulate_uevent("mmc", devpath, "add", uevent_params) < 0) {
- LOGE("Error simulating uevent (%m)\n");
+ LOGE("Error simulating uevent (%m)");
return -errno;
}
@@ -174,7 +174,7 @@
sprintf(filename, "/sys%s/block", devpath);
if (!access(filename, F_OK)) {
if (mmc_bootstrap_block(tmp)) {
- LOGE("Error bootstrapping block @ %s\n", tmp);
+ LOGE("Error bootstrapping block @ %s", tmp);
}
}
@@ -188,13 +188,13 @@
struct dirent *de;
#if DEBUG_BOOTSTRAP
- LOG_VOL("mmc_bootstrap_block(%s):\n", devpath);
+ LOG_VOL("mmc_bootstrap_block(%s):", devpath);
#endif
sprintf(blockdir_path, "/sys%s", devpath);
if (!(d = opendir(blockdir_path))) {
- LOGE("Failed to opendir %s\n", devpath);
+ LOGE("Failed to opendir %s", devpath);
return -errno;
}
@@ -205,7 +205,7 @@
continue;
sprintf(tmp, "%s/%s", devpath, de->d_name);
if (mmc_bootstrap_mmcblk(tmp))
- LOGE("Error bootstraping mmcblk @ %s\n", tmp);
+ LOGE("Error bootstraping mmcblk @ %s", tmp);
}
closedir(d);
return 0;
@@ -218,11 +218,11 @@
int rc;
#if DEBUG_BOOTSTRAP
- LOG_VOL("mmc_bootstrap_mmcblk(%s):\n", devpath);
+ LOG_VOL("mmc_bootstrap_mmcblk(%s):", devpath);
#endif
if ((rc = mmc_bootstrap_mmcblk_partition(devpath))) {
- LOGE("Error bootstrapping mmcblk partition '%s'\n", devpath);
+ LOGE("Error bootstrapping mmcblk partition '%s'", devpath);
return rc;
}
@@ -238,7 +238,7 @@
sprintf(part_devpath, "%s/%sp%d", devpath, mmcblk_devname, part_no);
if (mmc_bootstrap_mmcblk_partition(part_devpath))
- LOGE("Error bootstrapping mmcblk partition '%s'\n", part_devpath);
+ LOGE("Error bootstrapping mmcblk partition '%s'", part_devpath);
}
}
@@ -256,7 +256,7 @@
char line[255];
#if DEBUG_BOOTSTRAP
- LOG_VOL("mmc_bootstrap_mmcblk_partition(%s):\n", devpath);
+ LOG_VOL("mmc_bootstrap_mmcblk_partition(%s):", devpath);
#endif
sprintf(tmp, "DEVPATH=%s", devpath);
@@ -264,7 +264,7 @@
sprintf(filename, "/sys%s/uevent", devpath);
if (!(fp = fopen(filename, "r"))) {
- LOGE("Unable to open '%s' (%m)\n", filename);
+ LOGE("Unable to open '%s' (%m)", filename);
return -errno;
}
@@ -280,13 +280,13 @@
fclose(fp);
if (!uevent_params[1] || !uevent_params[2] || !uevent_params[3]) {
- LOGE("mmcblk uevent missing required params\n");
+ LOGE("mmcblk uevent missing required params");
return -1;
}
uevent_params[4] = '\0';
if (simulate_uevent("block", devpath, "add", uevent_params) < 0) {
- LOGE("Error simulating uevent (%m)\n");
+ LOGE("Error simulating uevent (%m)");
return -errno;
}
return 0;
diff --git a/vold/switch.c b/vold/switch.c
new file mode 100644
index 0000000..ba9ddb3
--- /dev/null
+++ b/vold/switch.c
@@ -0,0 +1,121 @@
+
+/*
+ * Copyright (C) 2008 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 <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include "vold.h"
+#include "switch.h"
+
+#define DEBUG_BOOTSTRAP 0
+
+static int mmc_bootstrap_switch(char *sysfs_path);
+
+int switch_bootstrap()
+{
+ DIR *d;
+ struct dirent *de;
+
+ if (!(d = opendir(SYSFS_CLASS_SWITCH_PATH))) {
+ LOG_ERROR("Unable to open '%s' (%m)", SYSFS_CLASS_SWITCH_PATH);
+ return -errno;
+ }
+
+ while ((de = readdir(d))) {
+ char tmp[255];
+
+ if (de->d_name[0] == '.')
+ continue;
+
+ sprintf(tmp, "%s/%s", SYSFS_CLASS_SWITCH_PATH, de->d_name);
+ if (mmc_bootstrap_switch(tmp))
+ LOG_ERROR("Error bootstrapping switch '%s' (%m)", tmp);
+ }
+
+ closedir(d);
+
+ return 0;
+}
+
+static int mmc_bootstrap_switch(char *sysfs_path)
+{
+#if DEBUG_BOOTSTRAP
+ LOG_VOL("bootstrap_switch(%s):", sysfs_path);
+#endif
+
+ char filename[255];
+ char name[255];
+ char state[255];
+ char tmp[255];
+ char *uevent_params[3];
+ char devpath[255];
+ FILE *fp;
+
+ /*
+ * Read switch name
+ */
+ sprintf(filename, "%s/name", sysfs_path);
+ if (!(fp = fopen(filename, "r"))) {
+ LOGE("Error opening switch name path '%s' (%s)",
+ sysfs_path, strerror(errno));
+ return -errno;
+ }
+ if (!fgets(name, sizeof(name), fp)) {
+ LOGE("Unable to read switch name");
+ fclose(fp);
+ return -EIO;
+ }
+ fclose(fp);
+
+ name[strlen(name) -1] = '\0';
+ sprintf(devpath, "/devices/virtual/switch/%s", name);
+ sprintf(tmp, "SWITCH_NAME=%s", name);
+ uevent_params[0] = (char *) strdup(tmp);
+
+ /*
+ * Read switch state
+ */
+ sprintf(filename, "%s/state", sysfs_path);
+ if (!(fp = fopen(filename, "r"))) {
+ LOGE("Error opening switch state path '%s' (%s)",
+ sysfs_path, strerror(errno));
+ return -errno;
+ }
+ if (!fgets(state, sizeof(state), fp)) {
+ LOGE("Unable to read switch state");
+ fclose(fp);
+ return -EIO;
+ }
+ fclose(fp);
+
+ state[strlen(state) -1] = '\0';
+ sprintf(tmp, "SWITCH_STATE=%s", state);
+ uevent_params[1] = (char *) strdup(tmp);
+
+ uevent_params[2] = (char *) NULL;
+
+ if (simulate_uevent("switch", devpath, "add", uevent_params) < 0) {
+ LOGE("Error simulating uevent (%s)", strerror(errno));
+ return -errno;
+ }
+
+ return 0;
+}
diff --git a/vold/inotify.h b/vold/switch.h
similarity index 85%
rename from vold/inotify.h
rename to vold/switch.h
index ada42a8..6729f2d 100644
--- a/vold/inotify.h
+++ b/vold/switch.h
@@ -15,8 +15,11 @@
* limitations under the License.
*/
-#ifndef _INOTIFY_EVT_H
-#define _INOTIFY_EVT_H
+#ifndef _SWITCH_H
+#define _SWITCH_H
+#include "vold.h"
+
+#define SYSFS_CLASS_SWITCH_PATH "/sys/class/switch"
#endif
diff --git a/vold/uevent.c b/vold/uevent.c
index 6b724d0..d16f315 100644
--- a/vold/uevent.c
+++ b/vold/uevent.c
@@ -71,6 +71,9 @@
{ NULL, NULL }
};
+static boolean low_batt = false;
+static boolean door_open = true;
+
int process_uevent_message(int socket)
{
char buffer[64 * 1024]; // Thank god we're not in the kernel :)
@@ -84,12 +87,12 @@
int rc = 0;
if ((count = recv(socket, buffer, sizeof(buffer), 0)) < 0) {
- LOGE("Error receiving uevent (%s)\n", strerror(errno));
+ LOGE("Error receiving uevent (%s)", strerror(errno));
return -errno;
}
if (!(event = malloc(sizeof(struct uevent)))) {
- LOGE("Error allocating memory (%s)\n", strerror(errno));
+ LOGE("Error allocating memory (%s)", strerror(errno));
return -errno;
}
@@ -120,7 +123,7 @@
else
event->param[param_idx++] = strdup(s);
}
- s+= (strlen(s) + 1);
+ s+= strlen(s) + 1;
}
rc = dispatch_uevent(event);
@@ -136,7 +139,7 @@
int i, rc;
if (!(event = malloc(sizeof(struct uevent)))) {
- LOGE("Error allocating memory (%s)\n", strerror(errno));
+ LOGE("Error allocating memory (%s)", strerror(errno));
return -errno;
}
@@ -151,7 +154,7 @@
else if (!strcmp(action, "remove"))
event->action = action_remove;
else {
- LOGE("Invalid action '%s'\n", action);
+ LOGE("Invalid action '%s'", action);
return -1;
}
@@ -172,13 +175,16 @@
{
int i;
+#if DEBUG_UEVENT
+ dump_uevent(event);
+#endif
for (i = 0; dispatch_table[i].subsystem != NULL; i++) {
if (!strcmp(dispatch_table[i].subsystem, event->subsystem))
return dispatch_table[i].dispatch(event);
}
#if DEBUG_UEVENT
- LOG_VOL("No uevent handlers registered for '%s' subsystem\n", event->subsystem);
+ LOG_VOL("No uevent handlers registered for '%s' subsystem", event->subsystem);
#endif
return 0;
}
@@ -187,12 +193,12 @@
{
int i;
- LOG_VOL("[UEVENT] Sq: %u S: %s A: %d P: %s\n",
+ LOG_VOL("[UEVENT] Sq: %u S: %s A: %d P: %s",
event->seqnum, event->subsystem, event->action, event->path);
for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
if (!event->param[i])
break;
- LOG_VOL("%s\n", event->param[i]);
+ LOG_VOL("%s", event->param[i]);
}
}
@@ -220,7 +226,7 @@
return &event->param[i][strlen(param_name) + 1];
}
- LOGE("get_uevent_param(): No parameter '%s' found\n", param_name);
+ LOGE("get_uevent_param(): No parameter '%s' found", param_name);
return NULL;
}
@@ -232,7 +238,18 @@
static int handle_powersupply_event(struct uevent *event)
{
- dump_uevent(event);
+ char *ps_type = get_uevent_param(event, "POWER_SUPPLY_TYPE");
+ char *ps_cap = get_uevent_param(event, "POWER_SUPPLY_CAPACITY");
+
+ if (!strcasecmp(ps_type, "battery")) {
+ int capacity = atoi(ps_cap);
+
+ if (capacity < 5)
+ low_batt = true;
+ else
+ low_batt = false;
+ volmgr_safe_mode(low_batt || door_open);
+ }
return 0;
}
@@ -241,21 +258,28 @@
char *name = get_uevent_param(event, "SWITCH_NAME");
char *state = get_uevent_param(event, "SWITCH_STATE");
+
if (!strcmp(name, "usb_mass_storage")) {
if (!strcmp(state, "online")) {
ums_hostconnected_set(true);
} else {
ums_hostconnected_set(false);
+ volmgr_enable_ums(false);
}
+ } else if (!strcmp(name, "sd-door")) {
+ if (!strcmp(state, "open"))
+ door_open = true;
+ else
+ door_open = false;
+ volmgr_safe_mode(low_batt || door_open);
} else
- LOG_VOL("handle_switch_event(): Ignoring switch '%s'\n", name);
+ LOG_VOL("handle_switch_event(): Ignoring switch '%s'", name);
return 0;
}
static int handle_battery_event(struct uevent *event)
{
- dump_uevent(event);
return 0;
}
@@ -270,12 +294,16 @@
/*
* Look for backing media for this block device
*/
- if (!strcmp(get_uevent_param(event, "DEVTYPE"), "disk"))
+ if (!strncmp(get_uevent_param(event, "DEVPATH"),
+ "/devices/virtual/",
+ strlen("/devices/virtual/"))) {
+ n = 0;
+ } else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "disk"))
n = 2;
else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "partition"))
n = 3;
else {
- LOGE("Bad blockdev type '%s'\n", get_uevent_param(event, "DEVTYPE"));
+ LOGE("Bad blockdev type '%s'", get_uevent_param(event, "DEVTYPE"));
return -EINVAL;
}
@@ -283,7 +311,7 @@
if (!(media = media_lookup_by_path(mediapath, false))) {
#if DEBUG_UEVENT
- LOG_VOL("No backend media found @ device path '%s'\n", mediapath);
+ LOG_VOL("No backend media found @ device path '%s'", mediapath);
#endif
return 0;
}
@@ -293,7 +321,6 @@
if (event->action == action_add) {
blkdev_t *disk;
- boolean pending = false;
/*
* If there isn't a disk already its because *we*
@@ -301,70 +328,56 @@
*/
disk = blkdev_lookup_by_devno(maj, 0);
- /*
- * It is possible that there is already a blkdev
- * for this device (created by blkdev_create_pending_partition())
- */
-
- if ((blkdev = blkdev_lookup_by_devno(maj, min))) {
- blkdev_devpath_set(blkdev, event->path);
- pending = true;
- } else {
- if (!(blkdev = blkdev_create(disk,
- event->path,
- maj,
- min,
- media,
- get_uevent_param(event, "DEVTYPE")))) {
- LOGE("Unable to allocate new blkdev (%m)\n");
- return -1;
- }
+ if (!(blkdev = blkdev_create(disk,
+ event->path,
+ maj,
+ min,
+ media,
+ get_uevent_param(event, "DEVTYPE")))) {
+ LOGE("Unable to allocate new blkdev (%m)");
+ return -1;
}
+ blkdev_refresh(blkdev);
+
/*
* Add the blkdev to media
*/
int rc;
if ((rc = media_add_blkdev(media, blkdev)) < 0) {
- LOGE("Unable to add blkdev to card (%d)\n", rc);
+ LOGE("Unable to add blkdev to card (%d)", rc);
return rc;
}
- LOG_VOL("New blkdev %d.%d on media %s, media path %s\n", blkdev->major, blkdev->minor, media->name, mediapath);
+ LOGI("New blkdev %d.%d on media %s, media path %s, Dpp %d",
+ blkdev->major, blkdev->minor, media->name, mediapath,
+ blkdev_get_num_pending_partitions(blkdev->disk));
- if (pending) {
- /*
- * This blkdev already has its dev_fspath set so
- * if all partitions are read, pass it off to
- * the volume manager
- */
- LOG_VOL("Pending disk '%d.%d' has %d pending partitions\n",
- blkdev->disk->major, blkdev->disk->minor,
- blkdev_get_num_pending_partitions(blkdev->disk));
-
- if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
- if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
- LOGE("Volmgr failed to handle pending device (%d)\n", rc);
- return rc;
- }
+ if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
+ if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
+ LOGE("Volmgr failed to handle device (%d)", rc);
+ return rc;
}
}
} else if (event->action == action_remove) {
- int rc;
-
- if (!(blkdev = blkdev_lookup_by_devno(maj, min))) {
-#if DEBUG_UEVENT
- LOG_VOL("We aren't handling blkdev @ %s\n", event->path);
-#endif
+ if (!(blkdev = blkdev_lookup_by_devno(maj, min)))
return 0;
- }
- LOG_VOL("Destroying blkdev %d.%d @ %s on media %s\n", blkdev->major, blkdev->minor, blkdev->devpath, media->name);
- if ((rc = volmgr_notify_eject(blkdev, _cb_blkdev_ok_to_destroy)) < 0)
- LOGE("Error notifying volmgr of eject\n");
- } else {
+ LOGI("Destroying blkdev %d.%d @ %s on media %s", blkdev->major,
+ blkdev->minor, blkdev->devpath, media->name);
+ volmgr_notify_eject(blkdev, _cb_blkdev_ok_to_destroy);
+
+ } else if (event->action == action_change) {
+ if (!(blkdev = blkdev_lookup_by_devno(maj, min)))
+ return 0;
+
+ LOGI("Modified blkdev %d.%d @ %s on media %s", blkdev->major,
+ blkdev->minor, blkdev->devpath, media->name);
+
+ blkdev_refresh(blkdev);
+ } else {
#if DEBUG_UEVENT
- LOG_VOL("No handler implemented for action %d\n", event->action);
+ LOG_VOL("No handler implemented for action %d", event->action);
#endif
}
return 0;
@@ -402,28 +415,25 @@
get_uevent_param(event, "MMC_NAME"),
serial,
media_mmc))) {
- LOGE("Unable to allocate new media (%m)\n");
+ LOGE("Unable to allocate new media (%m)");
return -1;
}
- LOG_VOL("New MMC card '%s' (serial %u) added @ %s\n", media->name,
+ LOGI("New MMC card '%s' (serial %u) added @ %s", media->name,
media->serial, media->devpath);
} else if (event->action == action_remove) {
media_t *media;
if (!(media = media_lookup_by_path(event->path, false))) {
- LOGE("Unable to lookup media '%s'\n", event->path);
+ LOGE("Unable to lookup media '%s'", event->path);
return -1;
}
- LOG_VOL("MMC card '%s' (serial %u) @ %s removed\n", media->name,
+ LOGI("MMC card '%s' (serial %u) @ %s removed", media->name,
media->serial, media->devpath);
- /*
- * If this media is still mounted, then we have an unsafe removal
- */
media_destroy(media);
} else {
#if DEBUG_UEVENT
- LOG_VOL("No handler implemented for action %d\n", event->action);
+ LOG_VOL("No handler implemented for action %d", event->action);
#endif
}
diff --git a/vold/ums.c b/vold/ums.c
index a6468fc..4d0fc25 100644
--- a/vold/ums.c
+++ b/vold/ums.c
@@ -21,6 +21,8 @@
#include "vold.h"
#include "ums.h"
+#define DEBUG_UMS 0
+
static boolean host_connected = false;
static boolean ums_enabled = false;
@@ -42,7 +44,9 @@
void ums_hostconnected_set(boolean connected)
{
- LOG_VOL("ums_hostconnected_set(%d):\n", connected);
+#if DEBUG_UMS
+ LOG_VOL("ums_hostconnected_set(%d):", connected);
+#endif
host_connected = connected;
if (!connected)
@@ -52,19 +56,19 @@
int ums_enable(char *dev_fspath, char *lun_syspath)
{
- LOG_VOL("ums_enable(%s, %s):\n", dev_fspath, lun_syspath);
+ LOG_VOL("ums_enable(%s, %s):", dev_fspath, lun_syspath);
int fd;
char filename[255];
sprintf(filename, "/sys/%s/file", lun_syspath);
if ((fd = open(filename, O_WRONLY)) < 0) {
- LOGE("Unable to open '%s' (%s)\n", filename, strerror(errno));
+ LOGE("Unable to open '%s' (%s)", filename, strerror(errno));
return -errno;
}
if (write(fd, dev_fspath, strlen(dev_fspath)) < 0) {
- LOGE("Unable to write to ums lunfile (%s)\n", strerror(errno));
+ LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
close(fd);
return -errno;
}
@@ -75,21 +79,23 @@
int ums_disable(char *lun_syspath)
{
- LOG_VOL("ums_disable(%s):\n", lun_syspath);
+#if DEBUG_UMS
+ LOG_VOL("ums_disable(%s):", lun_syspath);
+#endif
int fd;
char filename[255];
sprintf(filename, "/sys/%s/file", lun_syspath);
if ((fd = open(filename, O_WRONLY)) < 0) {
- LOGE("Unable to open '%s' (%s)\n", filename, strerror(errno));
+ LOGE("Unable to open '%s' (%s)", filename, strerror(errno));
return -errno;
}
char ch = 0;
if (write(fd, &ch, 1) < 0) {
- LOGE("Unable to write to ums lunfile (%s)\n", strerror(errno));
+ LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
close(fd);
return -errno;
}
@@ -107,7 +113,9 @@
{
int rc;
- LOG_VOL("ums_send_status():\n");
+#if DEBUG_UMS
+ LOG_VOL("ums_send_status():");
+#endif
rc = send_msg(ums_enabled_get() ? VOLD_EVT_UMS_ENABLED :
VOLD_EVT_UMS_DISABLED);
diff --git a/vold/vold.c b/vold/vold.c
index b2c8eb2..7d50a2f 100644
--- a/vold/vold.c
+++ b/vold/vold.c
@@ -27,7 +27,6 @@
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/inotify.h>
#include <sys/un.h>
#include <cutils/config_utils.h>
@@ -57,12 +56,11 @@
int main(int argc, char **argv)
{
int door_sock = -1;
- int inotify_sock = -1;
int uevent_sock = -1;
struct sockaddr_nl nladdr;
int uevent_sz = 64 * 1024;
- LOG_VOL("Android Volume Daemon version %d.%d\n", ver_major, ver_minor);
+ LOGI("Android Volume Daemon version %d.%d", ver_major, ver_minor);
/*
* Create all the various sockets we'll need
@@ -70,29 +68,18 @@
// Socket to listen on for incomming framework connections
if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) {
- LOGE("Obtaining file descriptor socket '%s' failed: %s\n",
+ LOGE("Obtaining file descriptor socket '%s' failed: %s",
VOLD_SOCKET, strerror(errno));
exit(1);
}
if (listen(door_sock, 4) < 0) {
- LOGE("Unable to listen on fd '%d' for socket '%s': %s\n",
+ LOGE("Unable to listen on fd '%d' for socket '%s': %s",
door_sock, VOLD_SOCKET, strerror(errno));
exit(1);
}
- // Socket to listen on for changes to /dev/block
- if ((inotify_sock = inotify_init()) < 0) {
- LOGE("Unable to initialize inotify interface (%s)\n", strerror(errno));
- exit(1);
- }
-
- fcntl(inotify_sock, F_SETFL, O_NONBLOCK | fcntl(inotify_sock, F_GETFL));
-
- if (inotify_add_watch(inotify_sock, DEVPATH, IN_CREATE | IN_DELETE) < 0) {
- LOGE("Unable to add inotify watch (%s)\n", strerror(errno));
- exit(1);
- }
+ mkdir("/dev/block/vold", 0755);
// Socket to listen on for uevent changes
memset(&nladdr, 0, sizeof(nladdr));
@@ -102,18 +89,18 @@
if ((uevent_sock = socket(PF_NETLINK,
SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
- LOGE("Unable to create uevent socket: %s\n", strerror(errno));
+ LOGE("Unable to create uevent socket: %s", strerror(errno));
exit(1);
}
if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
sizeof(uevent_sz)) < 0) {
- LOGE("Unable to set uevent socket options: %s\n", strerror(errno));
+ LOGE("Unable to set uevent socket options: %s", strerror(errno));
exit(1);
}
if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
- LOGE("Unable to bind uevent socket: %s\n", strerror(errno));
+ LOGE("Unable to bind uevent socket: %s", strerror(errno));
exit(1);
}
@@ -121,22 +108,22 @@
* Bootstrap
*/
+ // Volume Manager
+ volmgr_bootstrap();
+
// SD Card system
mmc_bootstrap();
// USB Mass Storage
ums_bootstrap();
- // Volume Manager
- volmgr_bootstrap();
-
- // Block device system
- inotify_bootstrap();
+ // Switch
+ switch_bootstrap();
/*
* Main loop
*/
-
+ LOG_VOL("Bootstrapping complete");
while(1) {
fd_set read_fds;
struct timeval to;
@@ -146,12 +133,10 @@
to.tv_sec = (60 * 60);
to.tv_usec = 0;
+ FD_ZERO(&read_fds);
FD_SET(door_sock, &read_fds);
if (door_sock > max)
max = door_sock;
- FD_SET(inotify_sock, &read_fds);
- if (inotify_sock > max)
- max = inotify_sock;
FD_SET(uevent_sock, &read_fds);
if (uevent_sock > max)
max = uevent_sock;
@@ -163,7 +148,7 @@
}
if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
- LOGE("select() failed (%s)\n", strerror(errno));
+ LOGE("select() failed (%s)", strerror(errno));
sleep(1);
continue;
}
@@ -178,42 +163,41 @@
alen = sizeof(addr);
+ if (fw_sock != -1) {
+ LOGE("Dropping duplicate framework connection");
+ int tmp = accept(door_sock, &addr, &alen);
+ close(tmp);
+ continue;
+ }
+
if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
- LOGE("Unable to accept framework connection (%s)\n",
+ LOGE("Unable to accept framework connection (%s)",
strerror(errno));
}
- LOG_VOL("Accepted connection from framework\n");
+ LOG_VOL("Accepted connection from framework");
if ((rc = volmgr_send_states()) < 0) {
- LOGE("Unable to send volmgr status to framework (%d)\n", rc);
+ LOGE("Unable to send volmgr status to framework (%d)", rc);
}
}
if (FD_ISSET(fw_sock, &read_fds)) {
if ((rc = process_framework_command(fw_sock)) < 0) {
if (rc == -ECONNRESET) {
- LOGE("Framework disconnected\n");
+ LOGE("Framework disconnected");
close(fw_sock);
fw_sock = -1;
} else {
- LOGE("Error processing framework command (%s)\n",
+ LOGE("Error processing framework command (%s)",
strerror(errno));
}
}
}
- if (FD_ISSET(inotify_sock, &read_fds)) {
- if ((rc = process_inotify_event(inotify_sock)) < 0) {
- LOGE("Error processing inotify msg (%s)\n", strerror(errno));
- }
- }
-
if (FD_ISSET(uevent_sock, &read_fds)) {
if ((rc = process_uevent_message(uevent_sock)) < 0) {
- LOGE("Error processing uevent msg (%s)\n", strerror(errno));
+ LOGE("Error processing uevent msg (%s)", strerror(errno));
}
}
-
-
} // while
}
@@ -224,7 +208,7 @@
pthread_mutex_lock(&write_mutex);
- LOG_VOL("send_msg(%s):\n", message);
+// LOG_VOL("send_msg(%s):", message);
if (fw_sock >= 0)
result = write(fw_sock, message, strlen(message) + 1);
@@ -240,7 +224,7 @@
char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
if (!buffer) {
- LOGE("alloca failed in send_msg_with_data\n");
+ LOGE("alloca failed in send_msg_with_data");
return -1;
}
diff --git a/vold/vold.h b/vold/vold.h
index f25fcff..0876bec 100644
--- a/vold/vold.h
+++ b/vold/vold.h
@@ -86,6 +86,8 @@
int volmgr_bootstrap(void);
+int switch_bootstrap(void);
+
void *read_file(char *filename, ssize_t *_size);
char *truncate_sysfs_path(char *path, int num_elements_to_remove, char *buffer);
char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var);
diff --git a/vold/volmgr.c b/vold/volmgr.c
index b162ff5..7c4c077 100644
--- a/vold/volmgr.c
+++ b/vold/volmgr.c
@@ -31,18 +31,21 @@
#include "volmgr.h"
#include "blkdev.h"
#include "ums.h"
+#include "format.h"
+#include "devmapper.h"
#include "volmgr_ext3.h"
#include "volmgr_vfat.h"
#define DEBUG_VOLMGR 0
-static volume_t *vol_root = NULL;
+static volume_t *vol_root = NULL;
+static boolean safe_mode = true;
static struct volmgr_fstable_entry fs_table[] = {
- { "ext3", ext3_identify, ext3_check, ext3_mount },
- { "vfat", vfat_identify, vfat_check, vfat_mount },
- { NULL, NULL, NULL, NULL }
+ { "ext3", ext_identify, ext_check, ext_mount , true },
+ { "vfat", vfat_identify, vfat_check, vfat_mount , false },
+ { NULL, NULL, NULL, NULL , false}
};
struct _volume_state_event_map {
@@ -80,26 +83,163 @@
static int volume_send_state(volume_t *vol);
static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg);
static int _volmgr_enable_ums(volume_t *);
-static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *arg));
-static int volmgr_stop_volume(volume_t *v, void (*cb) (volume_t *, void *), void *arg, int emit_statechange);
+static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *arg), boolean emit_statechange);
+static int volmgr_stop_volume(volume_t *v, void (*cb) (volume_t *, void *), void *arg, boolean emit_statechange);
static void _cb_volume_stopped_for_eject(volume_t *v, void *arg);
static void _cb_volume_stopped_for_shutdown(volume_t *v, void *arg);
static int _volmgr_consider_disk_and_vol(volume_t *vol, blkdev_t *dev);
-static void volmgr_uncage_reaper(volume_t *vol);
+static void volmgr_uncage_reaper(volume_t *vol, void (* cb) (volume_t *, void *arg), void *arg);
static void volmgr_reaper_thread_sighandler(int signo);
+static void volmgr_add_mediapath_to_volume(volume_t *v, char *media_path);
+static int volmgr_send_eject_request(volume_t *v);
+static volume_t *volmgr_lookup_volume_by_mountpoint(char *mount_point, boolean leave_locked);
+
+static boolean _mountpoint_mounted(char *mp)
+{
+ char device[256];
+ char mount_path[256];
+ char rest[256];
+ FILE *fp;
+ char line[1024];
+
+ if (!(fp = fopen("/proc/mounts", "r"))) {
+ LOGE("Error opening /proc/mounts (%s)", strerror(errno));
+ return false;
+ }
+
+ while(fgets(line, sizeof(line), fp)) {
+ line[strlen(line)-1] = '\0';
+ sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
+ if (!strcmp(mount_path, mp)) {
+ fclose(fp);
+ return true;
+ }
+
+ }
+
+ fclose(fp);
+ return false;
+}
/*
* Public functions
*/
+
+int volmgr_set_volume_key(char *mount_point, unsigned char *key)
+{
+ volume_t *v = volmgr_lookup_volume_by_mountpoint(mount_point, true);
+
+ if (!v)
+ return -ENOENT;
+
+ if (v->media_type != media_devmapper) {
+ LOGE("Cannot set key on a non devmapper volume");
+ pthread_mutex_unlock(&v->lock);
+ return -EINVAL;
+ }
+
+ memcpy(v->dm->key, key, sizeof(v->dm->key));
+ pthread_mutex_unlock(&v->lock);
+ return 0;
+}
+
+int volmgr_format_volume(char *mount_point)
+{
+ int rc;
+ volume_t *v;
+
+ LOG_VOL("volmgr_format_volume(%s):", mount_point);
+
+ v = volmgr_lookup_volume_by_mountpoint(mount_point, true);
+
+ if (!v)
+ return -ENOENT;
+
+ if (v->state == volstate_mounted ||
+ v->state == volstate_mounted_ro ||
+ v->state == volstate_ums ||
+ v->state == volstate_checking) {
+ LOGE("Can't format '%s', currently in state %d", mount_point, v->state);
+ pthread_mutex_unlock(&v->lock);
+ return -EBUSY;
+ } else if (v->state == volstate_nomedia &&
+ v->media_type != media_devmapper) {
+ LOGE("Can't format '%s', (no media)", mount_point);
+ pthread_mutex_unlock(&v->lock);
+ return -ENOMEDIUM;
+ }
+
+ // XXX:Reject if the underlying source media is not present
+
+ if (v->media_type == media_devmapper) {
+ if ((rc = devmapper_genesis(v->dm)) < 0) {
+ LOGE("devmapper genesis failed for %s (%d)", mount_point, rc);
+ pthread_mutex_unlock(&v->lock);
+ return rc;
+ }
+ } else {
+ if ((rc = initialize_mbr(v->dev->disk)) < 0) {
+ LOGE("MBR init failed for %s (%d)", mount_point, rc);
+ pthread_mutex_unlock(&v->lock);
+ return rc;
+ }
+ }
+
+ volume_setstate(v, volstate_formatting);
+ pthread_mutex_unlock(&v->lock);
+ return rc;
+}
+
int volmgr_bootstrap(void)
{
int rc;
if ((rc = volmgr_readconfig("/system/etc/vold.conf")) < 0) {
- LOGE("Unable to process config\n");
+ LOGE("Unable to process config");
return rc;
}
+ /*
+ * Check to see if any of our volumes is mounted
+ */
+ volume_t *v = vol_root;
+ while (v) {
+ if (_mountpoint_mounted(v->mount_point)) {
+ LOGW("Volume '%s' already mounted at startup", v->mount_point);
+ v->state = volstate_mounted;
+ }
+ v = v->next;
+ }
+
+ return 0;
+}
+
+int volmgr_safe_mode(boolean enable)
+{
+ if (enable == safe_mode)
+ return 0;
+
+ safe_mode = enable;
+
+ volume_t *v = vol_root;
+ int rc;
+
+ while (v) {
+ pthread_mutex_lock(&v->lock);
+ if (v->state == volstate_mounted && v->fs) {
+ rc = v->fs->mount_fn(v->dev, v, safe_mode);
+ if (!rc) {
+ LOGI("Safe mode %s on %s", (enable ? "enabled" : "disabled"), v->mount_point);
+ } else {
+ LOGE("Failed to %s safe-mode on %s (%s)",
+ (enable ? "enable" : "disable" ), v->mount_point, strerror(-rc));
+ }
+ }
+
+ pthread_mutex_unlock(&v->lock);
+ v = v->next;
+ }
+
return 0;
}
@@ -111,10 +251,11 @@
while (vol_scan) {
pthread_mutex_lock(&vol_scan->lock);
if ((rc = volume_send_state(vol_scan)) < 0) {
- LOGE("Error sending state to framework (%d)\n", rc);
+ LOGE("Error sending state to framework (%d)", rc);
}
pthread_mutex_unlock(&vol_scan->lock);
vol_scan = vol_scan->next;
+ break; // XXX:
}
return 0;
@@ -128,67 +269,94 @@
{
volume_t *vol;
- if (!(vol = volmgr_lookup_volume_by_mediapath(dev->media->devpath, true))) {
- LOG_VOL("volmgr ignoring '%s' - no matching volume found\n", dev->media->devpath);
+ if (!(vol = volmgr_lookup_volume_by_mediapath(dev->media->devpath, true)))
+ return 0;
+
+ pthread_mutex_lock(&vol->lock);
+
+ if (vol->state == volstate_mounted) {
+ LOGE("Volume %s already mounted (did we just crash?)", vol->mount_point);
+ pthread_mutex_unlock(&vol->lock);
return 0;
}
- pthread_mutex_lock(&vol->lock);
int rc = _volmgr_consider_disk_and_vol(vol, dev);
pthread_mutex_unlock(&vol->lock);
return rc;
}
int volmgr_start_volume_by_mountpoint(char *mount_point)
-{
- volume_t *v = vol_root;
+{
+ volume_t *v;
- while(v) {
- if (!strcmp(v->mount_point, mount_point)) {
- pthread_mutex_lock(&v->lock);
- if (!v->dev) {
- LOGE("Cannot start volume '%s' (volume is not bound to a blkdev)\n", mount_point);
- pthread_mutex_unlock(&v->lock);
- return -ENOENT;
- }
+ v = volmgr_lookup_volume_by_mountpoint(mount_point, true);
+ if (!v)
+ return -ENOENT;
- if (_volmgr_consider_disk_and_vol(v, v->dev->disk) < 0) {
- LOGE("volmgr failed to start volume '%s'\n", v->mount_point);
- }
- pthread_mutex_unlock(&v->lock);
- return 0;
+ if (v->media_type == media_devmapper) {
+ if (devmapper_start(v->dm) < 0) {
+ LOGE("volmgr failed to start devmapper volume '%s'",
+ v->mount_point);
}
- v = v->next;
+ } else if (v->media_type == media_mmc) {
+ if (!v->dev) {
+ LOGE("Cannot start volume '%s' (volume is not bound)", mount_point);
+ pthread_mutex_unlock(&v->lock);
+ return -ENOENT;
+ }
+
+ if (_volmgr_consider_disk_and_vol(v, v->dev->disk) < 0) {
+ LOGE("volmgr failed to start volume '%s'", v->mount_point);
+ }
}
- return -ENOENT;
+ pthread_mutex_unlock(&v->lock);
+ return 0;
+}
+
+static void _cb_volstopped_for_devmapper_teardown(volume_t *v, void *arg)
+{
+ devmapper_stop(v->dm);
+ volume_setstate(v, volstate_nomedia);
+ pthread_mutex_unlock(&v->lock);
}
int volmgr_stop_volume_by_mountpoint(char *mount_point)
{
- volume_t *v = vol_root;
+ int rc;
+ volume_t *v;
- while(v) {
- if (!strcmp(v->mount_point, mount_point)) {
- pthread_mutex_lock(&v->lock);
- if (volmgr_shutdown_volume(v, NULL) < 0)
- LOGE("unable to shutdown volume '%s'\n", v->mount_point);
- pthread_mutex_unlock(&v->lock);
- return 0;
- }
- v = v->next;
+ v = volmgr_lookup_volume_by_mountpoint(mount_point, true);
+ if (!v)
+ return -ENOENT;
+
+ if (v->state == volstate_mounted)
+ volmgr_send_eject_request(v);
+
+ if (v->media_type == media_devmapper)
+ rc = volmgr_shutdown_volume(v, _cb_volstopped_for_devmapper_teardown, false);
+ else
+ rc = volmgr_shutdown_volume(v, NULL, true);
+
+ /*
+ * If shutdown returns -EINPROGRESS,
+ * do *not* release the lock as
+ * it is now owned by the reaper thread
+ */
+ if (rc != -EINPROGRESS) {
+ if (rc)
+ LOGE("unable to shutdown volume '%s'", v->mount_point);
+ pthread_mutex_unlock(&v->lock);
}
-
- return -ENOENT;
+ return 0;
}
int volmgr_notify_eject(blkdev_t *dev, void (* cb) (blkdev_t *))
{
-#if DEBUG_VOLMGR
- LOG_VOL("volmgr_notify_eject(%s)\n", dev->dev_fspath);
-#endif
+ LOG_VOL("Volmgr notified of %d:%d eject", dev->major, dev->minor);
volume_t *v;
+ int rc;
// XXX: Partitioning support is going to need us to stop *all*
// devices in this volume
@@ -199,21 +367,80 @@
}
pthread_mutex_lock(&v->lock);
- if (v->state == volstate_mounted)
+
+ volume_state_t old_state = v->state;
+
+ if (v->state == volstate_mounted ||
+ v->state == volstate_ums ||
+ v->state == volstate_checking) {
+
volume_setstate(v, volstate_badremoval);
- int rc = volmgr_stop_volume(v, _cb_volume_stopped_for_eject, cb, false);
+ /*
+ * Stop any devmapper volumes which
+ * are using us as a source
+ * XXX: We may need to enforce stricter
+ * order here
+ */
+ volume_t *dmvol = vol_root;
+ while (dmvol) {
+ if ((dmvol->media_type == media_devmapper) &&
+ (dmvol->dm->src_type == dmsrc_loopback) &&
+ (!strncmp(dmvol->dm->type_data.loop.loop_src,
+ v->mount_point, strlen(v->mount_point)))) {
- pthread_mutex_unlock(&v->lock);
- return rc;
+ pthread_mutex_lock(&dmvol->lock);
+ if (dmvol->state != volstate_nomedia) {
+ rc = volmgr_shutdown_volume(dmvol, _cb_volstopped_for_devmapper_teardown, false);
+ if (rc != -EINPROGRESS) {
+ if (rc)
+ LOGE("unable to shutdown volume '%s'", v->mount_point);
+ pthread_mutex_unlock(&dmvol->lock);
+ }
+ } else
+ pthread_mutex_unlock(&dmvol->lock);
+ }
+ dmvol = dmvol->next;
+ }
+
+ } else if (v->state == volstate_formatting) {
+ /*
+ * The device is being ejected due to
+ * kernel disk revalidation.
+ */
+ LOG_VOL("Volmgr ignoring eject of %d:%d (volume formatting)",
+ dev->major, dev->minor);
+ if (cb)
+ cb(dev);
+ pthread_mutex_unlock(&v->lock);
+ return 0;
+ } else
+ volume_setstate(v, volstate_nomedia);
+
+ if (old_state == volstate_ums) {
+ ums_disable(v->ums_path);
+ pthread_mutex_unlock(&v->lock);
+ } else {
+ int rc = volmgr_stop_volume(v, _cb_volume_stopped_for_eject, cb, false);
+ if (rc != -EINPROGRESS) {
+ if (rc)
+ LOGE("unable to shutdown volume '%s'", v->mount_point);
+ pthread_mutex_unlock(&v->lock);
+ }
+ }
+ return 0;
}
static void _cb_volume_stopped_for_eject(volume_t *v, void *arg)
{
void (* eject_cb) (blkdev_t *) = arg;
- LOG_VOL("Volume %s has been stopped for eject\n", v->mount_point);
- eject_cb(v->dev);
+#if DEBUG_VOLMGR
+ LOG_VOL("Volume %s has been stopped for eject", v->mount_point);
+#endif
+
+ if (eject_cb)
+ eject_cb(v->dev);
v->dev = NULL; // Clear dev because its being ejected
}
@@ -231,27 +458,45 @@
if (enable) {
pthread_mutex_lock(&v->lock);
+ if (v->state == volstate_mounted)
+ volmgr_send_eject_request(v);
+ else if (v->state == volstate_ums) {
+ pthread_mutex_unlock(&v->lock);
+ goto next_vol;
+ }
+
// Stop the volume, and enable UMS in the callback
- if ((rc = volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable)) < 0)
- LOGE("unable to shutdown volume '%s'\n", v->mount_point);
+ rc = volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable, false);
+ if (rc != -EINPROGRESS) {
+ if (rc)
+ LOGE("unable to shutdown volume '%s'", v->mount_point);
+ pthread_mutex_unlock(&v->lock);
+ }
} else {
// Disable UMS
pthread_mutex_lock(&v->lock);
+ if (v->state != volstate_ums) {
+ pthread_mutex_unlock(&v->lock);
+ goto next_vol;
+ }
+
if ((rc = ums_disable(v->ums_path)) < 0) {
- LOGE("unable to disable ums on '%s'\n", v->mount_point);
+ LOGE("unable to disable ums on '%s'", v->mount_point);
pthread_mutex_unlock(&v->lock);
continue;
}
- volume_setstate(v, volstate_unmounted);
- LOG_VOL("Kick-starting volume '%s' after UMS disable\n", v->dev->disk->dev_fspath);
+ LOG_VOL("Kick-starting volume %d:%d after UMS disable",
+ v->dev->disk->major, v->dev->disk->minor);
// Start volume
if ((rc = _volmgr_consider_disk_and_vol(v, v->dev->disk)) < 0) {
- LOGE("volmgr failed to consider disk '%s'\n", v->dev->disk->dev_fspath);
+ LOGE("volmgr failed to consider disk %d:%d",
+ v->dev->disk->major, v->dev->disk->minor);
}
pthread_mutex_unlock(&v->lock);
}
}
+ next_vol:
v = v->next;
}
return 0;
@@ -261,30 +506,63 @@
* Static functions
*/
+static int volmgr_send_eject_request(volume_t *v)
+{
+ return send_msg_with_data(VOLD_EVT_EJECTING, v->mount_point);
+}
+
// vol->lock must be held!
static int _volmgr_consider_disk_and_vol(volume_t *vol, blkdev_t *dev)
{
int rc = 0;
#if DEBUG_VOLMGR
- LOG_VOL("volmgr_consider_disk_and_vol(%s, %s):\n", vol->mount_point, dev->dev_fspath);
+ LOG_VOL("volmgr_consider_disk_and_vol(%s, %d:%d):", vol->mount_point,
+ dev->major, dev->minor);
#endif
- if (vol->state != volstate_nomedia &&
- vol->state != volstate_unmounted &&
- vol->state != volstate_badremoval) {
- LOGE("Volume manager is already handling volume '%s' (currently in state %d)\n", vol->mount_point, vol->state);
+ if (vol->state == volstate_unknown ||
+ vol->state == volstate_mounted ||
+ vol->state == volstate_mounted_ro ||
+ vol->state == volstate_damaged) {
+ LOGE("Cannot consider volume '%s' because it is in state '%d",
+ vol->mount_point, vol->state);
return -EADDRINUSE;
}
- volume_setstate(vol, volstate_unmounted);
+ if (vol->state == volstate_formatting) {
+ LOG_VOL("Evaluating dev '%s' for formattable filesystems for '%s'",
+ dev->devpath, vol->mount_point);
+ /*
+ * Since we only support creating 1 partition (right now),
+ * we can just lookup the target by devno
+ */
+ blkdev_t *part = blkdev_lookup_by_devno(dev->major, 1);
+ if (!part) {
+ part = blkdev_lookup_by_devno(dev->major, 0);
+ if (!part) {
+ LOGE("Unable to find device to format");
+ return -ENODEV;
+ }
+ }
- LOG_VOL("Evaluating dev '%s' for mountable filesystems for '%s'\n", dev->devpath, vol->mount_point);
+ if ((rc = format_partition(part,
+ vol->media_type == media_devmapper ?
+ FORMAT_TYPE_EXT2 : FORMAT_TYPE_FAT32)) < 0) {
+ LOGE("format failed (%d)", rc);
+ return rc;
+ }
+
+ }
+
+ LOGI("Evaluating dev '%s' for mountable filesystems for '%s'",
+ dev->devpath, vol->mount_point);
if (dev->nr_parts == 0) {
rc = _volmgr_start(vol, dev);
#if DEBUG_VOLMGR
- LOG_VOL("_volmgr_start(%s, %s) rc = %d\n", vol->mount_point, dev->dev_fspath ,rc);
+ LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d", vol->mount_point,
+ dev->major, dev->minor, rc);
#endif
} else {
/*
@@ -298,12 +576,13 @@
for (i = 0; i < dev->nr_parts; i++) {
blkdev_t *part = blkdev_lookup_by_devno(dev->major, (i+1));
if (!part) {
- LOGE("Error - unable to lookup partition for blkdev %d:%d\n", dev->major, (i+1));
+ LOGE("Error - unable to lookup partition for blkdev %d:%d", dev->major, (i+1));
continue;
}
rc = _volmgr_start(vol, part);
#if DEBUG_VOLMGR
- LOG_VOL("_volmgr_start(%s, %s) rc = %d\n", vol->mount_point, part->dev_fspath, rc);
+ LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d",
+ vol->mount_point, part->major, part->minor, rc);
#endif
if (!rc)
break;
@@ -311,13 +590,14 @@
if (rc == -ENODEV) {
// Assert to make sure each partition had a backing blkdev
- LOGE("Internal consistency error\n");
+ LOGE("Internal consistency error");
return 0;
}
}
if (rc == -ENODATA) {
- LOGE("Device %s contains no usable filesystems\n", dev->dev_fspath);
+ LOGE("Device %d:%d contains no usable filesystems",
+ dev->major, dev->minor);
rc = 0;
}
@@ -326,14 +606,15 @@
static void volmgr_reaper_thread_sighandler(int signo)
{
- LOGE("volmgr reaper thread got signal %d\n", signo);
+ LOGE("Volume reaper thread got signal %d", signo);
}
static void __reaper_cleanup(void *arg)
{
volume_t *vol = (volume_t *) arg;
- LOG_VOL("__reaper_cleanup(%s):\n", vol->mount_point);
+ if (vol->worker_args.reaper_args.cb)
+ vol->worker_args.reaper_args.cb(vol, vol->worker_args.reaper_args.cb_arg);
vol->worker_running = false;
@@ -349,7 +630,6 @@
volume_t *vol = (volume_t *) arg;
pthread_cleanup_push(__reaper_cleanup, arg);
- pthread_mutex_lock(&vol->lock);
vol->worker_running = true;
vol->worker_pid = getpid();
@@ -362,32 +642,36 @@
actions.sa_handler = volmgr_reaper_thread_sighandler;
sigaction(SIGUSR1, &actions, NULL);
- LOG_VOL("Worker thread pid %d reaping %s\n", getpid(), vol->mount_point);
+ LOGW("Reaper here - working on %s", vol->mount_point);
boolean send_sig_kill = false;
int i, rc;
for (i = 0; i < 10; i++) {
+ errno = 0;
rc = umount(vol->mount_point);
- LOG_VOL("volmngr reaper umount(%s) attempt %d rc = %d\n",
- vol->mount_point, i + 1, rc);
+ LOGW("volmngr reaper umount(%s) attempt %d (%s)",
+ vol->mount_point, i + 1, strerror(errno));
if (!rc)
break;
if (rc && (errno == EINVAL || errno == ENOENT)) {
rc = 0;
break;
}
- KillProcessesWithOpenFiles(vol->mount_point, send_sig_kill, NULL, 0);
sleep(1);
- if (!send_sig_kill)
- send_sig_kill = true;
+ if (i >= 4) {
+ KillProcessesWithOpenFiles(vol->mount_point, send_sig_kill, NULL, 0);
+ if (!send_sig_kill)
+ send_sig_kill = true;
+ }
}
if (!rc) {
- LOG_VOL("Reaper sucessfully unmounted %s\n", vol->mount_point);
+ LOGI("Reaper sucessfully unmounted %s", vol->mount_point);
+ vol->fs = NULL;
volume_setstate(vol, volstate_unmounted);
} else {
- LOGE("Unable to unmount!! (%d)\n", rc);
+ LOGE("Unable to unmount!! (%d)", rc);
}
out:
@@ -396,16 +680,18 @@
return NULL;
}
-static void volmgr_uncage_reaper(volume_t *vol)
+// vol->lock must be held!
+static void volmgr_uncage_reaper(volume_t *vol, void (* cb) (volume_t *, void *arg), void *arg)
{
+
if (vol->worker_running) {
- LOGE("Worker thread is currently running.. waiting..\n");
+ LOGE("Worker thread is currently running.. waiting..");
pthread_mutex_lock(&vol->worker_sem);
- LOG_VOL("Worker thread now available\n");
+ LOGI("Worker thread now available");
}
- vol->worker_args.fs = NULL;
- vol->worker_args.dev = NULL;
+ vol->worker_args.reaper_args.cb = cb;
+ vol->worker_args.reaper_args.cb_arg = arg;
pthread_attr_t attr;
pthread_attr_init(&attr);
@@ -422,22 +708,29 @@
// Try to unmount right away (5 retries)
for (i = 0; i < 5; i++) {
rc = umount(v->mount_point);
- LOG_VOL("volmngr quick stop umount(%s) attempt %d rc = %d\n",
- v->mount_point, i + 1, rc);
if (!rc)
break;
+
if (rc && (errno == EINVAL || errno == ENOENT)) {
rc = 0;
break;
}
- sched_yield();
+
+ LOGI("volmngr quick stop umount(%s) attempt %d (%s)",
+ v->mount_point, i + 1, strerror(errno));
+
+ if (i == 0)
+ usleep(1000 * 250); // First failure, sleep for 250 ms
+ else
+ sched_yield();
}
if (!rc) {
- LOG_VOL("volmgr_stop_volume(%s): Volume unmounted sucessfully\n",
+ LOGI("volmgr_stop_volume(%s): Volume unmounted sucessfully",
v->mount_point);
if (emit_statechange)
volume_setstate(v, volstate_unmounted);
+ v->fs = NULL;
goto out_cb_immed;
}
@@ -445,21 +738,19 @@
* Since the volume is still in use, dispatch the stopping to
* a thread
*/
- LOG_VOL("Volume %s is busy (%d) - uncaging the reaper\n", v->mount_point, rc);
- volmgr_uncage_reaper(v);
+ LOGW("Volume %s is busy (%d) - uncaging the reaper", v->mount_point, rc);
+ volmgr_uncage_reaper(v, cb, arg);
return -EINPROGRESS;
} else if (v->state == volstate_checking) {
volume_setstate(v, volstate_unmounted);
if (v->worker_running) {
- LOG_VOL("Cancelling worker thread\n");
+ LOG_VOL("Cancelling worker thread");
pthread_kill(v->worker_thread, SIGUSR1);
} else
- LOGE("Strange... we were in checking state but worker thread wasn't running..\n");
+ LOGE("Strange... we were in checking state but worker thread wasn't running..");
goto out_cb_immed;
}
- LOGE("volmgr: nothing to do to stop vol '%s' (in state %d)\n",
- v->mount_point, v->state);
out_cb_immed:
if (cb)
cb(v, arg);
@@ -469,32 +760,45 @@
/*
* Gracefully stop a volume
+ * v->lock must be held!
+ * if we return -EINPROGRESS, do NOT release the lock as the reaper
+ * is using the volume
*/
-static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *))
+static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *), boolean emit_statechange)
{
- return volmgr_stop_volume(v, cb, NULL, true);
+ return volmgr_stop_volume(v, cb, NULL, emit_statechange);
}
static void _cb_volume_stopped_for_shutdown(volume_t *v, void *arg)
{
void (* shutdown_cb) (volume_t *) = arg;
- LOG_VOL("Volume %s has been stopped for shutdown\n", v->mount_point);
+#if DEBUG_VOLMGR
+ LOG_VOL("Volume %s has been stopped for shutdown", v->mount_point);
+#endif
shutdown_cb(v);
}
+
/*
* Called when a volume is sucessfully unmounted for UMS enable
*/
static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg)
{
int rc;
+ char *devdir_path;
- LOG_VOL("_cb_volstopped_for_ums_enable(%s):\n", v->dev->dev_fspath);
- if ((rc = ums_enable(v->dev->disk->dev_fspath, v->ums_path)) < 0) {
- LOGE("Error enabling ums (%d)\n", rc);
+#if DEBUG_VOLMGR
+ LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point);
+#endif
+ devdir_path = blkdev_get_devpath(v->dev->disk);
+
+ if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) {
+ free(devdir_path);
+ LOGE("Error enabling ums (%d)", rc);
return;
}
+ free(devdir_path);
volume_setstate(v, volstate_ums);
pthread_mutex_unlock(&v->lock);
}
@@ -508,20 +812,43 @@
node = root->first_child;
while (node) {
- if (!strcmp(node->name, "volume"))
+ if (!strncmp(node->name, "volume_", 7))
volmgr_config_volume(node);
else
- LOGE("Skipping unknown configuration node '%s'\n", node->name);
+ LOGE("Skipping unknown configuration node '%s'", node->name);
node = node->next;
}
return 0;
}
+static void volmgr_add_mediapath_to_volume(volume_t *v, char *media_path)
+{
+ int i;
+
+#if DEBUG_VOLMGR
+ LOG_VOL("volmgr_add_mediapath_to_volume(%p, %s):", v, media_path);
+#endif
+ for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) {
+ if (!v->media_paths[i]) {
+ v->media_paths[i] = strdup(media_path);
+ return;
+ }
+ }
+ LOGE("Unable to add media path '%s' to volume (out of media slots)", media_path);
+}
+
static int volmgr_config_volume(cnode *node)
{
volume_t *new;
- int rc = 0;
+ int rc = 0, i;
+ char *dm_src, *dm_src_type, *dm_tgt, *dm_param, *dm_tgtfs;
+ uint32_t dm_size_mb = 0;
+
+ dm_src = dm_src_type = dm_tgt = dm_param = dm_tgtfs = NULL;
+#if DEBUG_VOLMGR
+ LOG_VOL("volmgr_configure_volume(%s):", node->name);
+#endif
if (!(new = malloc(sizeof(volume_t))))
return -ENOMEM;
memset(new, 0, sizeof(volume_t));
@@ -534,12 +861,16 @@
while (child) {
if (!strcmp(child->name, "media_path"))
- new->media_path = strdup(child->value);
+ volmgr_add_mediapath_to_volume(new, child->value);
+ else if (!strcmp(child->name, "emu_media_path"))
+ volmgr_add_mediapath_to_volume(new, child->value);
else if (!strcmp(child->name, "media_type")) {
if (!strcmp(child->value, "mmc"))
new->media_type = media_mmc;
+ else if (!strcmp(child->value, "devmapper"))
+ new->media_type = media_devmapper;
else {
- LOGE("Invalid media type '%s'\n", child->value);
+ LOGE("Invalid media type '%s'", child->value);
rc = -EINVAL;
goto out_free;
}
@@ -547,15 +878,45 @@
new->mount_point = strdup(child->value);
else if (!strcmp(child->name, "ums_path"))
new->ums_path = strdup(child->value);
+ else if (!strcmp(child->name, "dm_src"))
+ dm_src = strdup(child->value);
+ else if (!strcmp(child->name, "dm_src_type"))
+ dm_src_type = strdup(child->value);
+ else if (!strcmp(child->name, "dm_src_size_mb"))
+ dm_size_mb = atoi(child->value);
+ else if (!strcmp(child->name, "dm_target"))
+ dm_tgt = strdup(child->value);
+ else if (!strcmp(child->name, "dm_target_params"))
+ dm_param = strdup(child->value);
+ else if (!strcmp(child->name, "dm_target_fs"))
+ dm_tgtfs = strdup(child->value);
else
- LOGE("Ignoring unknown config entry '%s'\n", child->name);
+ LOGE("Ignoring unknown config entry '%s'", child->name);
child = child->next;
}
- if (!new->media_path || !new->mount_point || new->media_type == media_unknown) {
- LOGE("Required configuration parameter missing for volume\n");
- rc = -EINVAL;
- goto out_free;
+ if (new->media_type == media_mmc) {
+ if (!new->media_paths[0] || !new->mount_point || new->media_type == media_unknown) {
+ LOGE("Required configuration parameter missing for mmc volume");
+ rc = -EINVAL;
+ goto out_free;
+ }
+ } else if (new->media_type == media_devmapper) {
+ if (!dm_src || !dm_src_type || !dm_tgt ||
+ !dm_param || !dm_tgtfs || !dm_size_mb) {
+ LOGE("Required configuration parameter missing for devmapper volume");
+ rc = -EINVAL;
+ goto out_free;
+ }
+
+ char dm_mediapath[255];
+ if (!(new->dm = devmapper_init(dm_src, dm_src_type, dm_size_mb,
+ dm_tgt, dm_param, dm_tgtfs, dm_mediapath))) {
+ LOGE("Unable to initialize devmapping");
+ goto out_free;
+ }
+ LOG_VOL("media path for devmapper volume = '%s'", dm_mediapath);
+ volmgr_add_mediapath_to_volume(new, dm_mediapath);
}
if (!vol_root)
@@ -567,11 +928,37 @@
scan->next = new;
}
+ if (dm_src)
+ free(dm_src);
+ if (dm_src_type)
+ free(dm_src_type);
+ if (dm_tgt)
+ free(dm_tgt);
+ if (dm_param)
+ free(dm_param);
+ if (dm_tgtfs)
+ free(dm_tgtfs);
+
return rc;
out_free:
- if (new->media_path)
- free(new->media_path);
+
+ if (dm_src)
+ free(dm_src);
+ if (dm_src_type)
+ free(dm_src_type);
+ if (dm_tgt)
+ free(dm_tgt);
+ if (dm_param)
+ free(dm_param);
+ if (dm_tgtfs)
+ free(dm_tgtfs);
+
+
+ for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) {
+ if (new->media_paths[i])
+ free(new->media_paths[i]);
+ }
if (new->mount_point)
free(new->mount_point);
if (new->ums_path)
@@ -590,27 +977,43 @@
return NULL;
}
+static volume_t *volmgr_lookup_volume_by_mountpoint(char *mount_point, boolean leave_locked)
+{
+ volume_t *v = vol_root;
+
+ while(v) {
+ pthread_mutex_lock(&v->lock);
+ if (!strcmp(v->mount_point, mount_point)) {
+ if (!leave_locked)
+ pthread_mutex_unlock(&v->lock);
+ return v;
+ }
+ pthread_mutex_unlock(&v->lock);
+ v = v->next;
+ }
+ return NULL;
+}
+
static volume_t *volmgr_lookup_volume_by_mediapath(char *media_path, boolean fuzzy)
{
volume_t *scan = vol_root;
- volume_t *res = NULL;
+ int i;
while (scan) {
- if (fuzzy) {
- if (!strncmp(media_path, scan->media_path, strlen(scan->media_path))) {
- if (!res)
- res = scan;
- else {
- LOGE("Warning - multiple matching volumes for media '%s' - using first\n", media_path);
- break;
- }
- }
- } else if (!strcmp(media_path, scan->media_path))
- return scan;
+
+ for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) {
+ if (!scan->media_paths[i])
+ continue;
+
+ if (fuzzy && !strncmp(media_path, scan->media_paths[i], strlen(scan->media_paths[i])))
+ return scan;
+ else if (!fuzzy && !strcmp(media_path, scan->media_paths[i]))
+ return scan;
+ }
scan = scan->next;
}
- return res;
+ return NULL;
}
/*
@@ -625,16 +1028,22 @@
int rc = ENODATA;
#if DEBUG_VOLMGR
- LOG_VOL("_volmgr_start(%s, %s):\n", vol->mount_point, dev->dev_fspath);
+ LOG_VOL("_volmgr_start(%s, %d:%d):", vol->mount_point,
+ dev->major, dev->minor);
#endif
+ if (vol->state == volstate_mounted) {
+ LOGE("Unable to start volume '%s' (already mounted)", vol->mount_point);
+ return -EBUSY;
+ }
+
for (fs = fs_table; fs->name; fs++) {
if (!fs->identify_fn(dev))
break;
}
if (!fs) {
- LOGE("No supported filesystems on %s\n", dev->dev_fspath);
+ LOGE("No supported filesystems on %d:%d", dev->major, dev->minor);
volume_setstate(vol, volstate_nofs);
return -ENODATA;
}
@@ -650,15 +1059,15 @@
*/
if (vol->worker_running) {
- LOGE("Worker thread is currently running.. waiting..\n");
+ LOGE("Worker thread is currently running.. waiting..");
pthread_mutex_lock(&vol->worker_sem);
- LOG_VOL("Worker thread now available\n");
+ LOGI("Worker thread now available");
}
vol->dev = dev;
- vol->worker_args.fs = fs;
- vol->worker_args.dev = dev;
+ vol->worker_args.start_args.fs = fs;
+ vol->worker_args.start_args.dev = dev;
pthread_attr_t attr;
pthread_attr_init(&attr);
@@ -673,7 +1082,9 @@
{
volume_t *vol = (volume_t *) arg;
- LOG_VOL("__start_fs_thread_lock_cleanup(%s):\n", vol->mount_point);
+#if DEBUG_VOLMGR
+ LOG_VOL("__start_fs_thread_lock_cleanup(%s):", vol->mount_point);
+#endif
vol->worker_running = false;
@@ -702,38 +1113,56 @@
actions.sa_handler = volmgr_start_fs_thread_sighandler;
sigaction(SIGUSR1, &actions, NULL);
- struct volmgr_fstable_entry *fs = vol->worker_args.fs;
- blkdev_t *dev = vol->worker_args.dev;
+ struct volmgr_fstable_entry *fs = vol->worker_args.start_args.fs;
+ blkdev_t *dev = vol->worker_args.start_args.dev;
int rc;
- LOG_VOL("Worker thread pid %d starting %s fs %s on %s\n", getpid(), fs->name, dev->dev_fspath, vol->mount_point);
+#if DEBUG_VOLMGR
+ LOG_VOL("Worker thread pid %d starting %s fs %d:%d on %s", getpid(),
+ fs->name, dev->major, dev->minor, vol->mount_point);
+#endif
if (fs->check_fn) {
- LOG_VOL("Starting %s filesystem check on %s\n", fs->name, dev->dev_fspath);
+#if DEBUG_VOLMGR
+ LOG_VOL("Starting %s filesystem check on %d:%d", fs->name,
+ dev->major, dev->minor);
+#endif
volume_setstate(vol, volstate_checking);
pthread_mutex_unlock(&vol->lock);
rc = fs->check_fn(dev);
pthread_mutex_lock(&vol->lock);
if (vol->state != volstate_checking) {
- LOG_VOL("filesystem check aborted\n");
+ LOGE("filesystem check aborted");
goto out;
}
if (rc < 0) {
- LOG_VOL("%s filesystem check failed on %s\n", fs->name, dev->dev_fspath);
+ LOGE("%s filesystem check failed on %d:%d (%s)", fs->name,
+ dev->major, dev->minor, strerror(-rc));
+ if (rc == -ENODATA) {
+ volume_setstate(vol, volstate_nofs);
+ goto out;
+ }
goto out_unmountable;
}
- LOG_VOL("%s filesystem check of %s OK\n", fs->name, dev->dev_fspath);
+#if DEBUG_VOLMGR
+ LOGI("%s filesystem check of %d:%d OK", fs->name,
+ dev->major, dev->minor);
+#endif
}
- rc = fs->mount_fn(dev, vol);
+ rc = fs->mount_fn(dev, vol, safe_mode);
if (!rc) {
- LOG_VOL("Sucessfully mounted %s filesystem %s on %s\n", fs->name, dev->devpath, vol->mount_point);
+ LOGI("Sucessfully mounted %s filesystem %d:%d on %s (safe-mode %s)",
+ fs->name, dev->major, dev->minor, vol->mount_point,
+ (safe_mode ? "on" : "off"));
+ vol->fs = fs;
volume_setstate(vol, volstate_mounted);
goto out;
}
- LOGE("%s filesystem mount of %s failed (%d)\n", fs->name, dev->devpath, rc);
+ LOGE("%s filesystem mount of %d:%d failed (%d)", fs->name, dev->major,
+ dev->minor, rc);
out_unmountable:
volume_setstate(vol, volstate_damaged);
@@ -745,19 +1174,26 @@
static void volmgr_start_fs_thread_sighandler(int signo)
{
- LOGE("volmgr thread got signal %d\n", signo);
+ LOGE("Volume startup thread got signal %d", signo);
}
static void volume_setstate(volume_t *vol, volume_state_t state)
{
- LOG_VOL("Volume %s state change from %d -> %d\n", vol->mount_point, vol->state, state);
+ if (state == vol->state)
+ return;
+
+#if DEBUG_VOLMGR
+ LOG_VOL("Volume %s state change from %d -> %d", vol->mount_point, vol->state, state);
+#endif
vol->state = state;
char *prop_val = conv_volstate_to_propstr(vol->state);
- property_set(PROP_EXTERNAL_STORAGE_STATE, prop_val);
- volume_send_state(vol);
+ if (prop_val) {
+ property_set(PROP_EXTERNAL_STORAGE_STATE, prop_val);
+ volume_send_state(vol);
+ }
}
static int volume_send_state(volume_t *vol)
@@ -776,8 +1212,6 @@
break;
}
- if (!volume_state_strings[i].event)
- LOGE("conv_volstate_to_eventstr(%d): Invalid state\n", state);
return volume_state_strings[i].event;
}
@@ -790,8 +1224,6 @@
break;
}
- if (!volume_state_strings[i].event)
- LOGE("conv_volstate_to_propval(%d): Invalid state\n", state);
return volume_state_strings[i].property_val;
}
diff --git a/vold/volmgr.h b/vold/volmgr.h
index a7f5701..2c7ec50 100644
--- a/vold/volmgr.h
+++ b/vold/volmgr.h
@@ -23,6 +23,7 @@
#include "vold.h"
#include "blkdev.h"
#include "media.h"
+#include "devmapper.h"
#define PROP_EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE"
@@ -70,15 +71,18 @@
volstate_ejecting,
#define VOLD_EVT_EJECTING "volume_ejecting:"
#define VOLD_ES_PVAL_EJECTING "ejecting"
+
+ volstate_formatting,
} volume_state_t;
struct volume;
struct volmgr_fstable_entry {
char *name;
- int (*identify_fn) (blkdev_t *dev);
- int (*check_fn) (blkdev_t *dev);
- int (*mount_fn) (blkdev_t *dev, struct volume *vol);
+ int (*identify_fn) (blkdev_t *dev);
+ int (*check_fn) (blkdev_t *dev);
+ int (*mount_fn) (blkdev_t *dev, struct volume *vol, boolean safe_mode);
+ boolean case_sensitive_paths;
};
struct volmgr_start_args {
@@ -86,21 +90,35 @@
blkdev_t *dev;
};
+struct volmgr_reaper_args {
+ void (*cb) (struct volume *, void *);
+ void *cb_arg;
+};
+
+#define VOLMGR_MAX_MEDIAPATHS_PER_VOLUME 8
+
typedef struct volume {
- char *media_path;
- media_type_t media_type;
- char *mount_point;
- char *ums_path;
+ char *media_paths[VOLMGR_MAX_MEDIAPATHS_PER_VOLUME];
+
+ media_type_t media_type;
+ char *mount_point;
+ char *ums_path;
+ struct devmapping *dm;
pthread_mutex_t lock;
volume_state_t state;
blkdev_t *dev;
pid_t worker_pid;
pthread_t worker_thread;
- struct volmgr_start_args worker_args;
+ union {
+ struct volmgr_start_args start_args;
+ struct volmgr_reaper_args reaper_args;
+ } worker_args;
boolean worker_running;
pthread_mutex_t worker_sem;
+ struct volmgr_fstable_entry *fs;
+
struct volume *next;
} volume_t;
@@ -110,6 +128,8 @@
int volmgr_enable_ums(boolean enable);
int volmgr_stop_volume_by_mountpoint(char *mount_point);
int volmgr_start_volume_by_mountpoint(char *mount_point);
-
+int volmgr_safe_mode(boolean enable);
+int volmgr_format_volume(char *mount_point);
+int volmgr_set_volume_key(char *mount_point, unsigned char *key);
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded);
#endif
diff --git a/vold/volmgr_ext3.c b/vold/volmgr_ext3.c
index 2be07fb..680be21 100644
--- a/vold/volmgr_ext3.c
+++ b/vold/volmgr_ext3.c
@@ -15,34 +15,170 @@
* limitations under the License.
*/
+#include <fcntl.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include <linux/ext2_fs.h>
+#include <linux/ext3_fs.h>
+
#include "vold.h"
#include "volmgr.h"
#include "volmgr_ext3.h"
+#include "logwrapper.h"
-#define EXT3_DEBUG 0
-int ext3_identify(blkdev_t *dev)
+#define EXT_DEBUG 0
+
+static char E2FSCK_PATH[] = "/system/bin/e2fsck";
+
+int ext_identify(blkdev_t *dev)
{
-#if EXT3_DEBUG
- LOG_VOL("ext3_identify(%s):\n", dev->dev_fspath);
+ int rc = -1;
+ int fd;
+ struct ext3_super_block sb;
+ char *devpath;
+
+#if EXT_DEBUG
+ LOG_VOL("ext_identify(%d:%d):", dev-major, dev->minor);
#endif
- return -ENOSYS;
+
+ devpath = blkdev_get_devpath(dev);
+
+ if ((fd = open(devpath, O_RDWR)) < 0) {
+ LOGE("Unable to open device '%s' (%s)", devpath,
+ strerror(errno));
+ free(devpath);
+ return -errno;
+ }
+
+ if (lseek(fd, 1024, SEEK_SET) < 0) {
+ LOGE("Unable to lseek to get superblock (%s)", strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
+ LOGE("Unable to read superblock (%s)", strerror(errno));
+ rc = -errno;
+ goto out;
+ }
+
+ if (sb.s_magic == EXT2_SUPER_MAGIC ||
+ sb.s_magic == EXT3_SUPER_MAGIC)
+ rc = 0;
+ else
+ rc = -ENODATA;
+
+ out:
+#if EXT_DEBUG
+ LOG_VOL("ext_identify(%s): rc = %d", devpath, rc);
+#endif
+ free(devpath);
+ close(fd);
+ return rc;
}
-int ext3_check(blkdev_t *dev)
+int ext_check(blkdev_t *dev)
{
-#if EXT3_DEBUG
- LOG_VOL("ext3_check(%s):\n", dev->dev_fspath);
+ char *devpath;
+
+#if EXT_DEBUG
+ LOG_VOL("ext_check(%s):", dev->dev_fspath);
#endif
- return -ENOSYS;
+
+ devpath = blkdev_get_devpath(dev);
+
+ if (access(E2FSCK_PATH, X_OK)) {
+ LOGE("ext_check(%s): %s not found (skipping checks)",
+ devpath, E2FSCK_PATH);
+ free(devpath);
+ return 0;
+ }
+
+ char *args[5];
+
+ args[0] = E2FSCK_PATH;
+ args[1] = "-v";
+ args[2] = "-p";
+ args[3] = devpath;
+ args[4] = NULL;
+
+ int rc = logwrap(4, args);
+
+ if (rc == 0) {
+ LOG_VOL("filesystem '%s' had no errors", devpath);
+ } else if (rc == 1) {
+ LOG_VOL("filesystem '%s' had corrected errors", devpath);
+ rc = 0;
+ } else if (rc == 2) {
+ LOGE("VOL volume '%s' had corrected errors (system should be rebooted)", devpath);
+ rc = -EIO;
+ } else if (rc == 4) {
+ LOGE("VOL volume '%s' had uncorrectable errors", devpath);
+ rc = -EIO;
+ } else if (rc == 8) {
+ LOGE("Operational error while checking volume '%s'", devpath);
+ rc = -EIO;
+ } else {
+ LOGE("Unknown e2fsck exit code (%d)", rc);
+ rc = -EIO;
+ }
+ free(devpath);
+ return rc;
}
-int ext3_mount(blkdev_t *dev, volume_t *vol)
+int ext_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode)
{
-#if EXT3_DEBUG
- LOG_VOL("ext3_mount(%s, %s):\n", dev->dev_fspath, vol->mount_point);
+#if EXT_DEBUG
+ LOG_VOL("ext_mount(%s, %s, %d):", dev->dev_fspath, vol->mount_point, safe_mode);
#endif
- return -ENOSYS;
+
+ char *fs[] = { "ext3", "ext2", NULL };
+ char *devpath;
+
+ devpath = blkdev_get_devpath(dev);
+
+ int flags, rc = 0;
+
+ flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME;
+
+ if (safe_mode)
+ flags |= MS_SYNCHRONOUS;
+
+ if (vol->state == volstate_mounted) {
+ LOG_VOL("Remounting %s on %s, safe mode %d", devpath,
+ vol->mount_point, safe_mode);
+ flags |= MS_REMOUNT;
+ }
+
+ char **f;
+ for (f = fs; *f != NULL; f++) {
+ rc = mount(devpath, vol->mount_point, *f, flags, NULL);
+ if (rc && errno == EROFS) {
+ LOGE("ext_mount(%s, %s): Read only filesystem - retrying mount RO",
+ devpath, vol->mount_point);
+ flags |= MS_RDONLY;
+ rc = mount(devpath, vol->mount_point, *f, flags, NULL);
+ }
+#if EXT_DEBUG
+ LOG_VOL("ext_mount(%s, %s): %s mount rc = %d", devpath, *f,
+ vol->mount_point, rc);
+#endif
+ if (!rc)
+ break;
+ }
+ free(devpath);
+
+ // Chmod the mount point so that its a free-for-all.
+ // (required for consistency with VFAT.. sigh)
+ if (chmod(vol->mount_point, 0777) < 0) {
+ LOGE("Failed to chmod %s (%s)", vol->mount_point, strerror(errno));
+ return -errno;
+ }
+
+ return rc;
}
diff --git a/vold/volmgr_ext3.h b/vold/volmgr_ext3.h
index a8bac19..bfe882a 100644
--- a/vold/volmgr_ext3.h
+++ b/vold/volmgr_ext3.h
@@ -21,9 +21,7 @@
#include "volmgr.h"
#include "blkdev.h"
-
-
-int ext3_identify(blkdev_t *blkdev);
-int ext3_check(blkdev_t *blkdev);
-int ext3_mount(blkdev_t *blkdev, volume_t *vol);
+int ext_identify(blkdev_t *blkdev);
+int ext_check(blkdev_t *blkdev);
+int ext_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode);
#endif
diff --git a/vold/volmgr_vfat.c b/vold/volmgr_vfat.c
index 661f714..344a166 100644
--- a/vold/volmgr_vfat.c
+++ b/vold/volmgr_vfat.c
@@ -31,7 +31,7 @@
int vfat_identify(blkdev_t *dev)
{
#if VFAT_DEBUG
- LOG_VOL("vfat_identify(%s):\n", dev->dev_fspath);
+ LOG_VOL("vfat_identify(%d:%d):", dev->major, dev->minor);
#endif
return 0; // XXX: Implement
}
@@ -41,12 +41,12 @@
int rc;
#if VFAT_DEBUG
- LOG_VOL("vfat_check(%s):\n", dev->dev_fspath);
+ LOG_VOL("vfat_check(%d:%d):", dev->major, dev->minor);
#endif
if (access(FSCK_MSDOS_PATH, X_OK)) {
- LOGE("vfat_check(%s): %s not found (skipping checks)\n",
- FSCK_MSDOS_PATH, dev->dev_fspath);
+ LOGE("vfat_check(%d:%d): %s not found (skipping checks)",
+ dev->major, dev->minor, FSCK_MSDOS_PATH);
return 0;
}
@@ -57,61 +57,77 @@
args[2] = "-V";
args[3] = "-w";
args[4] = "-p";
- args[5] = dev->dev_fspath;
+ args[5] = blkdev_get_devpath(dev);
args[6] = NULL;
rc = logwrap(6, args);
+ free(args[5]);
#else
char *args[6];
args[0] = FSCK_MSDOS_PATH;
args[1] = "-v";
args[2] = "-w";
args[3] = "-p";
- args[4] = dev->dev_fspath;
+ args[4] = blkdev_get_devpath(dev);
args[5] = NULL;
rc = logwrap(5, args);
+ free(args[4]);
#endif
if (rc == 0) {
- LOG_VOL("Filesystem check completed OK\n");
+ LOG_VOL("Filesystem check completed OK");
return 0;
} else if (rc == 1) {
- LOG_VOL("Filesystem check failed (general failure)\n");
+ LOG_VOL("Filesystem check failed (general failure)");
return -EINVAL;
} else if (rc == 2) {
- LOG_VOL("Filesystem check failed (invalid usage)\n");
+ LOG_VOL("Filesystem check failed (invalid usage)");
return -EIO;
} else if (rc == 4) {
- LOG_VOL("Filesystem check completed (errors fixed)\n");
+ LOG_VOL("Filesystem check completed (errors fixed)");
+ } else if (rc == 8) {
+ LOG_VOL("Filesystem check failed (not a FAT filesystem)");
+ return -ENODATA;
} else {
- LOG_VOL("Filesystem check failed (unknown exit code %d)\n", rc);
+ LOG_VOL("Filesystem check failed (unknown exit code %d)", rc);
return -EIO;
}
return 0;
}
-int vfat_mount(blkdev_t *dev, volume_t *vol)
+int vfat_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode)
{
int flags, rc;
+ char *devpath;
+
+ devpath = blkdev_get_devpath(dev);
#if VFAT_DEBUG
- LOG_VOL("vfat_mount(%s, %s):\n", dev->dev_fspath, vol->mount_point);
+ LOG_VOL("vfat_mount(%d:%d, %s, %d):", dev->major, dev->minor, vol->mount_point, safe_mode);
#endif
flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;
- rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags,
- "utf8,uid=1000,gid=1000,fmask=711,dmask=700");
+
+ if (vol->state == volstate_mounted) {
+ LOG_VOL("Remounting %d:%d on %s, safe mode %d", dev->major,
+ dev->minor, vol->mount_point, safe_mode);
+ flags |= MS_REMOUNT;
+ }
+
+ rc = mount(devpath, vol->mount_point, "vfat", flags,
+ "utf8,uid=1000,gid=1000,fmask=711,dmask=700,shortname=mixed");
if (rc && errno == EROFS) {
- LOGE("vfat_mount(%s, %s): Read only filesystem - retrying mount RO\n",
- dev->dev_fspath, vol->mount_point);
+ LOGE("vfat_mount(%d:%d, %s): Read only filesystem - retrying mount RO",
+ dev->major, dev->minor, vol->mount_point);
flags |= MS_RDONLY;
- rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags,
- "utf8,uid=1000,gid=1000,fmask=711,dmask=700");
+ rc = mount(devpath, vol->mount_point, "vfat", flags,
+ "utf8,uid=1000,gid=1000,fmask=711,dmask=700,shortname=mixed");
}
#if VFAT_DEBUG
- LOG_VOL("vfat_mount(%s, %s): mount rc = %d\n", dev->dev_fspath,
+ LOG_VOL("vfat_mount(%s, %d:%d): mount rc = %d", dev->major,k dev->minor,
vol->mount_point, rc);
#endif
+ free (devpath);
return rc;
}
diff --git a/vold/volmgr_vfat.h b/vold/volmgr_vfat.h
index 2bd9fed..d9cf04d 100644
--- a/vold/volmgr_vfat.h
+++ b/vold/volmgr_vfat.h
@@ -25,5 +25,5 @@
int vfat_identify(blkdev_t *blkdev);
int vfat_check(blkdev_t *blkdev);
-int vfat_mount(blkdev_t *blkdev, volume_t *vol);
+int vfat_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode);
#endif