Split fstab mount into 2 phases
This will make it possible to start some key services before mounting
data partition
Bug: 30118894
Change-Id: Ia9f8cc035de6cc0df9a61605864915efa0266d7f
(cherry picked from commit abfbec342f
)
This commit is contained in:
parent
3cc284a656
commit
d61a7e2da4
8 changed files with 122 additions and 34 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
@ -553,3 +554,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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -48,7 +48,7 @@ __BEGIN_DECLS
|
|||
*
|
||||
* <fs_mgr_options> 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 <source> file exists, and "check", which requests that the fs_mgr
|
||||
* the <source> file exists, and "check", which requests that the fs_mgr
|
||||
* run an fscheck program on the <source> 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
|
||||
|
|
|
@ -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
|
||||
|
@ -85,7 +92,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)
|
||||
|
@ -113,6 +120,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);
|
||||
|
|
|
@ -465,9 +465,9 @@ exit_success:
|
|||
*
|
||||
* start_index: index of the first path in the args list
|
||||
*/
|
||||
static void import_late(const std::vector<std::string>& args, size_t start_index) {
|
||||
static void import_late(const std::vector<std::string>& 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<std::string> init_directories = {
|
||||
"/system/etc/init",
|
||||
|
@ -479,21 +479,19 @@ static void import_late(const std::vector<std::string>& 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 <fstab> [ <path> ]*
|
||||
/* 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<std::string>& 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
|
||||
|
@ -523,7 +521,7 @@ static int do_mount_all(const std::vector<std::string>& 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";
|
||||
|
@ -533,28 +531,38 @@ static int do_mount_all(const std::vector<std::string>& 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;
|
||||
}
|
||||
|
@ -564,14 +572,55 @@ static int do_mount_all(const std::vector<std::string>& 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 <fstab> [ <path> ]* [--<options>]*
|
||||
*
|
||||
* This function might request a reboot, in which case it will
|
||||
* not return.
|
||||
*/
|
||||
static int do_mount_all(const std::vector<std::string>& 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<std::string>& args) {
|
||||
struct fstab *fstab;
|
||||
int ret;
|
||||
|
|
|
@ -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 <path> [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 <fstab> [ <path> ]*
|
||||
mount_all <fstab> [ <path> ]* [--<option>]
|
||||
Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files
|
||||
at the specified paths (e.g., on the partitions just mounted). Refer to the
|
||||
section of "Init .rc Files" for detail.
|
||||
at the specified paths (e.g., on the partitions just mounted) with optional
|
||||
options "early" and "late".
|
||||
Refer to the section of "Init .rc Files" for detail.
|
||||
|
||||
mount <type> <device> <dir> [ <flag> ]* [<options>]
|
||||
Attempt to mount the named device at the directory <dir>
|
||||
|
|
|
@ -236,6 +236,9 @@ on init
|
|||
|
||||
export DOWNLOAD_CACHE /data/cache
|
||||
|
||||
# set RLIMIT_NICE to allow priorities from 19 to -20
|
||||
setrlimit 13 40 40
|
||||
|
||||
# Healthd can trigger a full boot from charger mode by signaling this
|
||||
# property when the power button is held.
|
||||
on property:sys.boot_from_charger_mode=1
|
||||
|
@ -258,6 +261,11 @@ on firmware_mounts_complete
|
|||
# Mount filesystems and start core system services.
|
||||
on late-init
|
||||
trigger early-fs
|
||||
|
||||
# Mount fstab in init.{$device}.rc by mount_all command. Optional parameter
|
||||
# '--early' can be specified to skip entries with 'latemount'.
|
||||
# /system and /vendor must be mounted by the end of the fs stage,
|
||||
# while /data is optional.
|
||||
trigger fs
|
||||
trigger post-fs
|
||||
|
||||
|
@ -266,9 +274,18 @@ on late-init
|
|||
# issued fs triggers have completed.
|
||||
trigger load_system_props_action
|
||||
|
||||
# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
|
||||
# to only mount entries with 'latemount'. This is needed if '--early' is
|
||||
# specified in the previous mount_all command on the fs stage.
|
||||
# With /system mounted and properties form /system + /factory available,
|
||||
# some services can be started.
|
||||
trigger late-fs
|
||||
|
||||
# Now we can mount /data. File encryption requires keymaster to decrypt
|
||||
# /data, which in turn can only be loaded when system properties are present
|
||||
# /data, which in turn can only be loaded when system properties are present.
|
||||
trigger post-fs-data
|
||||
|
||||
# Load persist properties and override properties (if enabled) from /data.
|
||||
trigger load_persist_props_action
|
||||
|
||||
# Remove a file to wake up anything waiting for firmware.
|
||||
|
@ -478,9 +495,6 @@ on boot
|
|||
hostname localhost
|
||||
domainname localdomain
|
||||
|
||||
# set RLIMIT_NICE to allow priorities from 19 to -20
|
||||
setrlimit 13 40 40
|
||||
|
||||
# Memory management. Basic kernel parameters, and allow the high
|
||||
# level system server to be able to adjust the kernel OOM driver
|
||||
# parameters to match how it is managing things.
|
||||
|
|
Loading…
Reference in a new issue