From 8e5c9b802841cabff50c7596ff76e169b76a95ad Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Tue, 23 Aug 2016 11:58:09 -0700 Subject: [PATCH] Split fstab mount into 2 phases This will make it possible to start some key services before mounting data partition (cherry picked from commit abfbec342fdd2fc9d139a88a2d950953918e1b4e) Bug: 30118894 Change-Id: Ia9f8cc035de6cc0df9a61605864915efa0266d7f --- fs_mgr/fs_mgr.c | 8 ++-- fs_mgr/fs_mgr_fstab.c | 6 +++ fs_mgr/fs_mgr_main.c | 2 +- fs_mgr/fs_mgr_priv.h | 3 +- fs_mgr/include/fs_mgr.h | 10 ++++- init/builtins.cpp | 89 ++++++++++++++++++++++++++++++++--------- init/readme.txt | 16 ++++++-- rootdir/init.rc | 22 ++++++++-- 8 files changed, 122 insertions(+), 34 deletions(-) diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 6de88175c..387f70859 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -489,7 +489,7 @@ static int handle_encryptable(const struct fstab_rec* rec) * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ -int fs_mgr_mount_all(struct fstab *fstab) +int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; @@ -503,8 +503,10 @@ int fs_mgr_mount_all(struct fstab *fstab) } for (i = 0; i < fstab->num_entries; i++) { - /* Don't mount entries that are managed by vold */ - if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { + /* Don't mount entries that are managed by vold or not for the mount mode*/ + if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) || + ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) || + ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) { continue; } diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c index 45adb34de..21b4c740d 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -78,6 +78,7 @@ static struct flag_list fs_mgr_flags[] = { { "formattable", MF_FORMATTABLE }, { "slotselect", MF_SLOTSELECT }, { "nofail", MF_NOFAIL }, + { "latemount", MF_LATEMOUNT }, { "defaults", 0 }, { 0, 0 }, }; @@ -545,3 +546,8 @@ int fs_mgr_is_nofail(struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_NOFAIL; } + +int fs_mgr_is_latemount(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_LATEMOUNT; +} diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c index e5a00d595..776c13ea6 100644 --- a/fs_mgr/fs_mgr_main.c +++ b/fs_mgr/fs_mgr_main.c @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) fstab = fs_mgr_read_fstab(fstab_file); if (a_flag) { - return fs_mgr_mount_all(fstab); + return fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT); } else if (n_flag) { return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0); } else if (u_flag) { diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 46975f1f4..6d9492bef 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -48,7 +48,7 @@ __BEGIN_DECLS * * is a comma separated list of flags that control the operation of * the fs_mgr program. The list includes "wait", which will wait till - * the file exists, and "check", which requests that the fs_mgr + * the file exists, and "check", which requests that the fs_mgr * run an fscheck program on the before mounting the filesystem. * If check is specifed on a read-only filesystem, it is ignored. * Also, "encryptable" means that filesystem can be encrypted. @@ -83,6 +83,7 @@ __BEGIN_DECLS #define MF_FORMATTABLE 0x4000 #define MF_SLOTSELECT 0x8000 #define MF_FORCEFDEORFBE 0x10000 +#define MF_LATEMOUNT 0x20000 #define MF_NOFAIL 0x40000 #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 46d8f9743..756596598 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -40,6 +40,13 @@ enum verity_mode { VERITY_MODE_DEFAULT = VERITY_MODE_RESTART }; +// Mount modes +enum mount_mode { + MOUNT_MODE_DEFAULT = 0, + MOUNT_MODE_EARLY = 1, + MOUNT_MODE_LATE = 2 +}; + /* * The entries must be kept in the same order as they were seen in the fstab. * Unless explicitly requested, a lookup on mount point should always @@ -82,7 +89,7 @@ void fs_mgr_free_fstab(struct fstab *fstab); #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 1 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0 #define FS_MGR_MNTALL_FAIL -1 -int fs_mgr_mount_all(struct fstab *fstab); +int fs_mgr_mount_all(struct fstab *fstab, int mount_mode); #define FS_MGR_DOMNT_FAILED -1 #define FS_MGR_DOMNT_BUSY -2 @@ -110,6 +117,7 @@ int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab); int fs_mgr_is_notrim(struct fstab_rec *fstab); int fs_mgr_is_formattable(struct fstab_rec *fstab); int fs_mgr_is_nofail(struct fstab_rec *fstab); +int fs_mgr_is_latemount(struct fstab_rec *fstab); int fs_mgr_swapon_all(struct fstab *fstab); int fs_mgr_do_format(struct fstab_rec *fstab); diff --git a/init/builtins.cpp b/init/builtins.cpp index 70f919401..44217f0f0 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -479,9 +479,9 @@ exit_success: * * start_index: index of the first path in the args list */ -static void import_late(const std::vector& args, size_t start_index) { +static void import_late(const std::vector& args, size_t start_index, size_t end_index) { Parser& parser = Parser::GetInstance(); - if (args.size() <= start_index) { + if (end_index <= start_index) { // Use the default set if no path is given static const std::vector init_directories = { "/system/etc/init", @@ -493,25 +493,23 @@ static void import_late(const std::vector& args, size_t start_index parser.ParseConfig(dir); } } else { - for (size_t i = start_index; i < args.size(); ++i) { + for (size_t i = start_index; i < end_index; ++i) { parser.ParseConfig(args[i]); } } } -/* mount_all [ ]* +/* mount_fstab * - * This function might request a reboot, in which case it will - * not return. + * Call fs_mgr_mount_all() to mount the given fstab */ -static int do_mount_all(const std::vector& args) { +static int mount_fstab(const char* fstabfile, int mount_mode) { pid_t pid; int ret = -1; int child_ret = -1; int status; struct fstab *fstab; - const char* fstabfile = args[1].c_str(); /* * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and * do the call in the child to provide protection to the main init @@ -536,7 +534,7 @@ static int do_mount_all(const std::vector& args) { /* child, call fs_mgr_mount_all() */ klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ fstab = fs_mgr_read_fstab(fstabfile); - child_ret = fs_mgr_mount_all(fstab); + child_ret = fs_mgr_mount_all(fstab, mount_mode); fs_mgr_free_fstab(fstab); if (child_ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); @@ -546,28 +544,38 @@ static int do_mount_all(const std::vector& args) { /* fork failed, return an error */ return -1; } + return ret; +} - /* Paths of .rc files are specified at the 2nd argument and beyond */ - import_late(args, 2); - - if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { +/* Queue event based on fs_mgr return code. + * + * code: return code of fs_mgr_mount_all + * + * This function might request a reboot, in which case it will + * not return. + * + * return code is processed based on input code + */ +static int queue_fs_event(int code) { + int ret = code; + if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { ActionManager::GetInstance().QueueEventTrigger("encrypt"); - } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { + } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { property_set("ro.crypto.state", "encrypted"); property_set("ro.crypto.type", "block"); ActionManager::GetInstance().QueueEventTrigger("defaultcrypto"); - } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { + } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { property_set("ro.crypto.state", "unencrypted"); ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); - } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { + } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { property_set("ro.crypto.state", "unsupported"); ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); - } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { + } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { /* Setup a wipe via recovery, and reboot into recovery */ ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n"); ret = wipe_data_via_recovery("wipe_data_via_recovery"); /* If reboot worked, there is no return. */ - } else if (ret == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { + } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } @@ -577,14 +585,55 @@ static int do_mount_all(const std::vector& args) { // Although encrypted, we have device key, so we do not need to // do anything different from the nonencrypted case. ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); - } else if (ret > 0) { - ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret); + } else if (code > 0) { + ERROR("fs_mgr_mount_all returned unexpected error %d\n", code); } /* else ... < 0: error */ return ret; } +/* mount_all [ ]* [--]* + * + * This function might request a reboot, in which case it will + * not return. + */ +static int do_mount_all(const std::vector& args) { + std::size_t na = 0; + bool import_rc = true; + bool queue_event = true; + int mount_mode = MOUNT_MODE_DEFAULT; + const char* fstabfile = args[1].c_str(); + std::size_t path_arg_end = args.size(); + + for (na = args.size() - 1; na > 1; --na) { + if (args[na] == "--early") { + path_arg_end = na; + queue_event = false; + mount_mode = MOUNT_MODE_EARLY; + } else if (args[na] == "--late") { + path_arg_end = na; + import_rc = false; + mount_mode = MOUNT_MODE_LATE; + } + } + + int ret = mount_fstab(fstabfile, mount_mode); + + if (import_rc) { + /* Paths of .rc files are specified at the 2nd argument and beyond */ + import_late(args, 2, path_arg_end); + } + + if (queue_event) { + /* queue_fs_event will queue event based on mount_fstab return code + * and return processed return code*/ + ret = queue_fs_event(ret); + } + + return ret; +} + static int do_swapon_all(const std::vector& args) { struct fstab *fstab; int ret; diff --git a/init/readme.txt b/init/readme.txt index 4481e24ef..dad7e06b9 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -1,4 +1,3 @@ - Android Init Language --------------------- @@ -78,6 +77,14 @@ monolithic init .rc files. This additionally will aid in merge conflict resolution when multiple services are added to the system, as each one will go into a separate file. +There are two options "early" and "late" in mount_all command +which can be set after optional paths. With "--early" set, the +init executable will skip mounting entries with "latemount" flag +and triggering fs encryption state event. With "--late" set, +init executable will only mount entries with "latemount" flag but skip +importing rc files. By default, no option is set, and mount_all will +mount_all will process all entries in the given fstab. + Actions ------- Actions are named sequences of commands. Actions have a trigger which @@ -291,10 +298,11 @@ mkdir [mode] [owner] [group] owned by the root user and root group. If provided, the mode, owner and group will be updated if the directory exists already. -mount_all [ ]* +mount_all [ ]* [--