From 254f44363b85f4665b1942762a708bf87301a462 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 | 23 ++++++++--- 8 files changed, 122 insertions(+), 35 deletions(-) diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 46d147ab9..b11ce754c 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -486,7 +486,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; @@ -500,8 +500,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 791ddd217..313bc5abb 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -77,6 +77,7 @@ static struct flag_list fs_mgr_flags[] = { { "formattable", MF_FORMATTABLE }, { "slotselect", MF_SLOTSELECT }, { "nofail", MF_NOFAIL }, + { "latemount", MF_LATEMOUNT }, { "defaults", 0 }, { 0, 0 }, }; @@ -516,3 +517,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 b3f131ea6..33a749653 100644 --- a/fs_mgr/fs_mgr_main.c +++ b/fs_mgr/fs_mgr_main.c @@ -95,7 +95,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 36918fada..c0116ef80 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -42,6 +42,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 @@ -84,7 +91,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, bool reserve_footer); diff --git a/init/builtins.cpp b/init/builtins.cpp index 48b1ad725..200b723e4 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -460,9 +460,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", @@ -474,21 +474,19 @@ 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) { int ret = -1; - 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 @@ -518,7 +516,7 @@ static int do_mount_all(const std::vector& args) { android::base::ScopedLogSeverity info(android::base::INFO); struct fstab* fstab = fs_mgr_read_fstab(fstabfile); - int child_ret = fs_mgr_mount_all(fstab); + int child_ret = fs_mgr_mount_all(fstab, mount_mode); fs_mgr_free_fstab(fstab); if (child_ret == -1) { PLOG(ERROR) << "fs_mgr_mount_all returned an error"; @@ -528,28 +526,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 */ PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery."; 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; } @@ -559,14 +567,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) { - PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << ret; + } else if (code > 0) { + PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << 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 bc3874a87..26225b2b5 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 @@ -312,10 +319,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 [ ]* [--