Merge "Switch sdcardfs over to bind mounts." am: 94b9e4df04
am: 895cd44bd9
Change-Id: I33328d236f0ccfb9f65cfdc90d626a8561c032a1
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 740720b..c9876fd 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/swap.h>
@@ -38,6 +39,7 @@
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
+#include <linux/fs.h>
#include <linux/loop.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
@@ -50,8 +52,9 @@
#define KEY_IN_FOOTER "footer"
#define E2FSCK_BIN "/system/bin/e2fsck"
-#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
+#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
#define MKSWAP_BIN "/system/bin/mkswap"
+#define TUNE2FS_BIN "/system/bin/tune2fs"
#define FSCK_LOG_FILE "/dev/fscklogs/log"
@@ -180,6 +183,99 @@
return;
}
+/* Function to read the primary superblock */
+static int read_super_block(int fd, struct ext4_super_block *sb)
+{
+ off64_t ret;
+
+ ret = lseek64(fd, 1024, SEEK_SET);
+ if (ret < 0)
+ return ret;
+
+ ret = read(fd, sb, sizeof(*sb));
+ if (ret < 0)
+ return ret;
+ if (ret != sizeof(*sb))
+ return ret;
+
+ return 0;
+}
+
+static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+{
+ return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
+ le32_to_cpu(es->s_blocks_count_lo);
+}
+
+static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
+{
+ return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
+ le32_to_cpu(es->s_r_blocks_count_lo);
+}
+
+static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
+{
+ /* Check for the types of filesystems we know how to check */
+ if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
+ /*
+ * Some system images do not have tune2fs for licensing reasons
+ * Detect these and skip reserve blocks.
+ */
+ if (access(TUNE2FS_BIN, X_OK)) {
+ ERROR("Not running %s on %s (executable not in system image)\n",
+ TUNE2FS_BIN, blk_device);
+ } else {
+ INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);
+
+ int status = 0;
+ int ret = 0;
+ unsigned long reserved_blocks = 0;
+ int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
+ if (fd >= 0) {
+ struct ext4_super_block sb;
+ ret = read_super_block(fd, &sb);
+ if (ret < 0) {
+ ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
+ goto out;
+ }
+ reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
+ unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
+ if (reserved_threshold < reserved_blocks) {
+ WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
+ reserved_blocks = reserved_threshold;
+ }
+
+ if (ext4_r_blocks_count(&sb) == reserved_blocks) {
+ INFO("Have reserved same blocks\n");
+ goto out;
+ }
+ } else {
+ ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
+ return;
+ }
+
+ char buf[16] = {0};
+ snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
+ char *tune2fs_argv[] = {
+ TUNE2FS_BIN,
+ buf,
+ blk_device,
+ };
+
+ ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
+ &status, true, LOG_KLOG | LOG_FILE,
+ true, NULL, NULL, 0);
+
+ if (ret < 0) {
+ /* No need to check for error in fork, we can't really handle it now */
+ ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
+ }
+ out:
+ close(fd);
+ }
+ }
+}
+
static void remove_trailing_slashes(char *n)
{
int len;
@@ -325,6 +421,12 @@
check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
fstab->recs[i].mount_point);
}
+
+ if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
+ do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
+ &fstab->recs[i]);
+ }
+
if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
*attempted_idx = i;
mounted = 1;
@@ -690,6 +792,10 @@
fstab->recs[i].mount_point);
}
+ if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
+ do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
+ }
+
if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
int rc = fs_mgr_setup_verity(&fstab->recs[i]);
if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 0bc8bef..f25d10c 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -33,6 +33,7 @@
int swap_prio;
int max_comp_streams;
unsigned int zram_size;
+ uint64_t reserved_size;
unsigned int file_encryption_mode;
};
@@ -74,6 +75,7 @@
{ "swapprio=", MF_SWAPPRIO },
{ "zramsize=", MF_ZRAMSIZE },
{ "max_comp_streams=", MF_MAX_COMP_STREAMS },
+ { "verifyatboot", MF_VERIFYATBOOT },
{ "verify", MF_VERIFY },
{ "noemulatedsd", MF_NOEMULATEDSD },
{ "notrim", MF_NOTRIM },
@@ -81,6 +83,7 @@
{ "slotselect", MF_SLOTSELECT },
{ "nofail", MF_NOFAIL },
{ "latemount", MF_LATEMOUNT },
+ { "reservedsize=", MF_RESERVEDSIZE },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -107,6 +110,20 @@
return total;
}
+static uint64_t parse_size(const char *arg)
+{
+ char *endptr;
+ uint64_t size = strtoull(arg, &endptr, 10);
+ if (*endptr == 'k' || *endptr == 'K')
+ size *= 1024LL;
+ else if (*endptr == 'm' || *endptr == 'M')
+ size *= 1024LL * 1024LL;
+ else if (*endptr == 'g' || *endptr == 'G')
+ size *= 1024LL * 1024LL * 1024LL;
+
+ return size;
+}
+
static int parse_flags(char *flags, struct flag_list *fl,
struct fs_mgr_flag_values *flag_vals,
char *fs_options, int fs_options_len)
@@ -216,6 +233,11 @@
flag_vals->zram_size = calculate_zram_size(val);
else
flag_vals->zram_size = val;
+ } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
+ /* The reserved flag is followed by an = and the
+ * reserved size of the partition. Get it and return it.
+ */
+ flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
}
break;
}
@@ -360,6 +382,7 @@
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
fstab->recs[cnt].zram_size = flag_vals.zram_size;
+ fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
cnt++;
}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 741f5e9..4632521 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -85,7 +85,9 @@
#define MF_FORCEFDEORFBE 0x10000
#define MF_LATEMOUNT 0x20000
#define MF_NOFAIL 0x40000
+#define MF_VERIFYATBOOT 0x80000
#define MF_MAX_COMP_STREAMS 0x100000
+#define MF_RESERVEDSIZE 0x200000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 031b042..bb61b93 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -32,6 +32,7 @@
#include <android-base/file.h>
#include <android-base/strings.h>
#include <crypto_utils/android_pubkey.h>
+#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <logwrap/logwrap.h>
#include <openssl/obj_mac.h>
@@ -73,6 +74,8 @@
#define VERITY_KMSG_RESTART "dm-verity device corrupted"
#define VERITY_KMSG_BUFSIZE 1024
+#define READ_BUF_SIZE 4096
+
#define __STRINGIFY(x) #x
#define STRINGIFY(x) __STRINGIFY(x)
@@ -205,6 +208,16 @@
return 0;
}
+static int destroy_verity_device(struct dm_ioctl *io, char *name, int fd)
+{
+ verity_ioctl_init(io, name, 0);
+ if (ioctl(fd, DM_DEV_REMOVE, io)) {
+ ERROR("Error removing device mapping (%s)", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name)
{
verity_ioctl_init(io, name, 0);
@@ -606,6 +619,30 @@
return rc;
}
+static int read_partition(const char *path, uint64_t size)
+{
+ char buf[READ_BUF_SIZE];
+ ssize_t size_read;
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)));
+
+ if (fd == -1) {
+ ERROR("Failed to open %s: %s\n", path, strerror(errno));
+ return -errno;
+ }
+
+ while (size) {
+ size_read = TEMP_FAILURE_RETRY(read(fd, buf, READ_BUF_SIZE));
+ if (size_read == -1) {
+ ERROR("Error in reading partition %s: %s\n", path,
+ strerror(errno));
+ return -errno;
+ }
+ size -= size_read;
+ }
+
+ return 0;
+}
+
static int compare_last_signature(struct fstab_rec *fstab, int *match)
{
char tag[METADATA_TAG_MAX_LENGTH + 1];
@@ -788,7 +825,7 @@
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
const char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
- char *status;
+ const char *status;
int fd = -1;
int i;
int mode;
@@ -838,9 +875,13 @@
verity_ioctl_init(io, mount_point, 0);
if (ioctl(fd, DM_TABLE_STATUS, io)) {
- ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point,
- strerror(errno));
- continue;
+ if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
+ status = "V";
+ } else {
+ ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point,
+ strerror(errno));
+ continue;
+ }
}
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
@@ -904,6 +945,7 @@
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
char *mount_point = basename(fstab->mount_point);
+ bool verified_at_boot = false;
if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
FEC_DEFAULT_ROOTS) < 0) {
@@ -1037,10 +1079,26 @@
// mark the underlying block device as read-only
fs_mgr_set_blk_ro(fstab->blk_device);
+ // Verify the entire partition in one go
+ // If there is an error, allow it to mount as a normal verity partition.
+ if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
+ INFO("Verifying partition %s at boot\n", fstab->blk_device);
+ int err = read_partition(verity_blk_name, verity.data_size);
+ if (!err) {
+ INFO("Verified verity partition %s at boot\n", fstab->blk_device);
+ verified_at_boot = true;
+ }
+ }
+
// assign the new verity block device as the block device
- free(fstab->blk_device);
- fstab->blk_device = verity_blk_name;
- verity_blk_name = 0;
+ if (!verified_at_boot) {
+ free(fstab->blk_device);
+ fstab->blk_device = verity_blk_name;
+ verity_blk_name = 0;
+ } else if (destroy_verity_device(io, mount_point, fd) < 0) {
+ ERROR("Failed to remove verity device %s\n", mount_point);
+ goto out;
+ }
// make sure we've set everything up properly
if (test_access(fstab->blk_device) < 0) {
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 9323069..ed22e90 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -75,6 +75,7 @@
int swap_prio;
int max_comp_streams;
unsigned int zram_size;
+ uint64_t reserved_size;
unsigned int file_encryption_mode;
};
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 7c5e35b..b292725 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -21,6 +21,10 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
+LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
+LOCAL_SHARED_LIBRARIES += libsuspend
+endif
LOCAL_SRC_FILES := \
healthd_mode_android.cpp \
healthd_mode_charger.cpp \
@@ -90,6 +94,14 @@
LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_FAST),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_FAST=$(BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+endif
+
+ifneq ($(BOARD_PERIODIC_CHORES_INTERVAL_SLOW),)
+LOCAL_CFLAGS += -DBOARD_PERIODIC_CHORES_INTERVAL_SLOW=$(BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+endif
+
LOCAL_STATIC_LIBRARIES := \
libhealthd_internal \
libbatterymonitor \
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 20a6bf6..aa6735d 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -35,9 +35,19 @@
using namespace android;
-// Periodic chores intervals in seconds
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_FAST
+ // Periodic chores fast interval in seconds
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+#else
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (BOARD_PERIODIC_CHORES_INTERVAL_FAST)
+#endif
+
+#ifndef BOARD_PERIODIC_CHORES_INTERVAL_SLOW
+ // Periodic chores fast interval in seconds
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#else
+ #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (BOARD_PERIODIC_CHORES_INTERVAL_SLOW)
+#endif
static struct healthd_config healthd_config = {
.periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
@@ -143,10 +153,14 @@
struct android::BatteryProperties* /*props*/) {
}
-int healthd_register_event(int fd, void (*handler)(uint32_t)) {
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
struct epoll_event ev;
- ev.events = EPOLLIN | EPOLLWAKEUP;
+ ev.events = EPOLLIN;
+
+ if (wakeup == EVENT_WAKEUP_FD)
+ ev.events |= EPOLLWAKEUP;
+
ev.data.ptr = (void *)handler;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
KLOG_ERROR(LOG_TAG,
@@ -252,7 +266,7 @@
}
fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
- if (healthd_register_event(uevent_fd, uevent_event))
+ if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG,
"register for uevent events failed\n");
}
@@ -275,7 +289,7 @@
return;
}
- if (healthd_register_event(wakealarm_fd, wakealarm_event))
+ if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD))
KLOG_ERROR(LOG_TAG,
"Registration of wakealarm event failed\n");
@@ -283,17 +297,22 @@
}
static void healthd_mainloop(void) {
+ int nevents = 0;
while (1) {
struct epoll_event events[eventct];
- int nevents;
int timeout = awake_poll_interval;
int mode_timeout;
+ /* Don't wait for first timer timeout to run periodic chores */
+ if (!nevents)
+ periodic_chores();
+
+ healthd_mode_ops->heartbeat();
+
mode_timeout = healthd_mode_ops->preparetowait();
if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))
timeout = mode_timeout;
nevents = epoll_wait(epollfd, events, eventct, timeout);
-
if (nevents == -1) {
if (errno == EINTR)
continue;
@@ -305,11 +324,6 @@
if (events[n].data.ptr)
(*(void (*)(int))events[n].data.ptr)(events[n].events);
}
-
- if (!nevents)
- periodic_chores();
-
- healthd_mode_ops->heartbeat();
}
return;
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 36c4664..ec3de34 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -341,14 +341,19 @@
static void draw_percent(const animation& anim)
{
- if (anim.cur_level <= 0 || anim.cur_status != BATTERY_STATUS_CHARGING) return;
+ int cur_level = anim.cur_level;
+ if (anim.cur_status == BATTERY_STATUS_FULL) {
+ cur_level = 100;
+ }
+
+ if (cur_level <= 0) return;
const animation::text_field& field = anim.text_percent;
if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
return;
}
- std::string str = base::StringPrintf("%d%%", anim.cur_level);
+ std::string str = base::StringPrintf("%d%%", cur_level);
int x, y;
determine_xy(field, str.size(), &x, &y);
@@ -839,7 +844,7 @@
ret = ev_init(input_callback, charger);
if (!ret) {
epollfd = ev_get_epollfd();
- healthd_register_event(epollfd, charger_event_handler);
+ healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
}
struct animation* anim = init_animation();
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index 34ea55f..17efbd6 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -73,9 +73,14 @@
bool (*screen_on)(android::BatteryProperties *props);
};
+enum EventWakeup {
+ EVENT_NO_WAKEUP_FD,
+ EVENT_WAKEUP_FD,
+};
+
// Global helper functions
-int healthd_register_event(int fd, void (*handler)(uint32_t));
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup = EVENT_NO_WAKEUP_FD);
void healthd_battery_update();
android::status_t healthd_get_property(int id,
struct android::BatteryProperty *val);
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 3457d5b..d3fb45f 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -24,7 +24,6 @@
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -36,24 +35,12 @@
#define SYS_POWER_STATE "/sys/power/state"
#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
-#define BASE_SLEEP_TIME 100000
-
static int state_fd;
static int wakeup_count_fd;
static pthread_t suspend_thread;
static sem_t suspend_lockout;
static const char *sleep_state = "mem";
static void (*wakeup_func)(bool success) = NULL;
-static int sleep_time = BASE_SLEEP_TIME;
-
-static void update_sleep_time(bool success) {
- if (success) {
- sleep_time = BASE_SLEEP_TIME;
- return;
- }
- // double sleep time after each failure up to one minute
- sleep_time = MIN(sleep_time * 2, 60000000);
-}
static void *suspend_thread_func(void *arg __attribute__((unused)))
{
@@ -61,12 +48,10 @@
char wakeup_count[20];
int wakeup_count_len;
int ret;
- bool success = true;
+ bool success;
while (1) {
- update_sleep_time(success);
- usleep(sleep_time);
- success = false;
+ usleep(100000);
ALOGV("%s: read wakeup_count\n", __func__);
lseek(wakeup_count_fd, 0, SEEK_SET);
wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -90,6 +75,7 @@
continue;
}
+ success = true;
ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
if (ret < 0) {
@@ -98,8 +84,8 @@
} else {
ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
- if (ret >= 0) {
- success = true;
+ if (ret < 0) {
+ success = false;
}
void (*func)(bool success) = wakeup_func;
if (func != NULL) {