fs_mrg: clean up multi-type mount_all
Move the code that attempts to mount alternative fstab entries into its own function. Clarify return codes. Suggest wipe via recovery in error messages. Bug: 15747366 Change-Id: I3634477cd4d1d73f974f3e906c53285f0d9e0eac Signed-off-by: JP Abgrall <jpa@google.com>
This commit is contained in:
parent
686bce6390
commit
f22b745294
3 changed files with 100 additions and 66 deletions
151
fs_mgr/fs_mgr.c
151
fs_mgr/fs_mgr.c
|
@ -245,31 +245,89 @@ static int device_is_debuggable() {
|
|||
return strcmp(value, "1") ? 0 : 1;
|
||||
}
|
||||
|
||||
void wipe_data_via_recovery()
|
||||
/*
|
||||
* Tries to mount any of the consecutive fstab entries that match
|
||||
* the mountpoint of the one given by fstab->recs[start_idx].
|
||||
*
|
||||
* end_idx: On return, will be the last rec that was looked at.
|
||||
* attempted_idx: On return, will indicate which fstab rec
|
||||
* succeeded. In case of failure, it will be the start_idx.
|
||||
* Returns
|
||||
* -1 on failure with errno set to match the 1st mount failure.
|
||||
* 0 on success.
|
||||
*/
|
||||
static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx)
|
||||
{
|
||||
mkdir("/cache/recovery", 0700);
|
||||
int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC, 0600);
|
||||
if (fd >= 0) {
|
||||
write(fd, "--wipe_data", strlen("--wipe_data") + 1);
|
||||
close(fd);
|
||||
} else {
|
||||
ERROR("could not open /cache/recovery/command\n");
|
||||
int i;
|
||||
int mount_errno = 0;
|
||||
int mounted = 0;
|
||||
|
||||
if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
|
||||
errno = EINVAL;
|
||||
if (end_idx) *end_idx = start_idx;
|
||||
if (attempted_idx) *end_idx = start_idx;
|
||||
return -1;
|
||||
}
|
||||
property_set(ANDROID_RB_PROPERTY, "reboot,recovery");
|
||||
|
||||
/* Hunt down an fstab entry for the same mount point that might succeed */
|
||||
for (i = start_idx;
|
||||
/* We required that fstab entries for the same mountpoint be consecutive */
|
||||
i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point);
|
||||
i++) {
|
||||
/*
|
||||
* Don't try to mount/encrypt the same mount point again.
|
||||
* Deal with alternate entries for the same point which are required to be all following
|
||||
* each other.
|
||||
*/
|
||||
if (mounted) {
|
||||
ERROR("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted as %s.\n", __func__,
|
||||
fstab->recs[i].mount_point, i, fstab->recs[i].fs_type, fstab->recs[*attempted_idx].fs_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
|
||||
check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
|
||||
fstab->recs[i].mount_point);
|
||||
}
|
||||
if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
|
||||
*attempted_idx = i;
|
||||
mounted = 1;
|
||||
if (i != start_idx) {
|
||||
ERROR("%s(): Mounted %s on %s with fs_type=%s instead of %s\n", __func__,
|
||||
fstab->recs[i].blk_device, fstab->recs[i].mount_point, fstab->recs[i].fs_type,
|
||||
fstab->recs[start_idx].fs_type);
|
||||
}
|
||||
} else {
|
||||
/* back up errno for crypto decisions */
|
||||
mount_errno = errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust i for the case where it was still withing the recs[] */
|
||||
if (i < fstab->num_entries) --i;
|
||||
|
||||
*end_idx = i;
|
||||
if (!mounted) {
|
||||
*attempted_idx = start_idx;
|
||||
errno = mount_errno;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When multiple fstab records share the same mount_point, it will
|
||||
* try to mount each one in turn, and ignore any duplicates after a
|
||||
* first successful mount.
|
||||
* Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
|
||||
*/
|
||||
int fs_mgr_mount_all(struct fstab *fstab)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
int encryptable = 0;
|
||||
int i = 0;
|
||||
int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
|
||||
int error_count = 0;
|
||||
int mret = -1;
|
||||
int mount_errno = 0;
|
||||
const char *last_ok_mount_point = NULL;
|
||||
int attempted_idx = -1;
|
||||
|
||||
if (!fstab) {
|
||||
return -1;
|
||||
|
@ -299,55 +357,27 @@ int fs_mgr_mount_all(struct fstab *fstab)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't try to mount/encrypt the same mount point again.
|
||||
* Deal with alternate entries for the same point which are required to be all following
|
||||
* each other.
|
||||
*/
|
||||
if (last_ok_mount_point && !strcmp(last_ok_mount_point, fstab->recs[i].mount_point)) {
|
||||
INFO("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted.\n", __func__,
|
||||
last_ok_mount_point, i, fstab->recs[i].fs_type);
|
||||
continue;
|
||||
}
|
||||
/* Hunt down an fstab entry for the same mount point that might succeed */
|
||||
for (j = i;
|
||||
/* We required that fstab entries for the same mountpoint be consecutive */
|
||||
j < fstab->num_entries && !strcmp(fstab->recs[i].mount_point, fstab->recs[j].mount_point);
|
||||
j++) {
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
|
||||
check_fs(fstab->recs[j].blk_device, fstab->recs[j].fs_type,
|
||||
fstab->recs[j].mount_point);
|
||||
}
|
||||
mret = __mount(fstab->recs[j].blk_device, fstab->recs[j].mount_point, &fstab->recs[j]);
|
||||
if (!mret) {
|
||||
last_ok_mount_point = fstab->recs[j].mount_point;
|
||||
if (i != j) {
|
||||
INFO("%s(): some alternate mount worked for mount_point=%s fs_type=%s instead of fs_type=%s\n", __func__,
|
||||
last_ok_mount_point, fstab->recs[j].fs_type, fstab->recs[i].fs_type);
|
||||
i = j; /* We advance the recs index to the working entry */
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
/* back up errno for crypto decisions */
|
||||
mount_errno = errno;
|
||||
}
|
||||
}
|
||||
int last_idx_inspected;
|
||||
mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
|
||||
i = last_idx_inspected;
|
||||
mount_errno = errno;
|
||||
|
||||
/* Deal with encryptability. */
|
||||
if (!mret) {
|
||||
/* If this is encryptable, need to trigger encryption */
|
||||
if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) {
|
||||
if (umount(fstab->recs[i].mount_point) == 0) {
|
||||
if (!encryptable) {
|
||||
encryptable = 2;
|
||||
if ((fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)) {
|
||||
if (umount(fstab->recs[attempted_idx].mount_point) == 0) {
|
||||
if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
|
||||
ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point,
|
||||
fstab->recs[attempted_idx].fs_type);
|
||||
encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
|
||||
} else {
|
||||
ERROR("Only one encryptable/encrypted partition supported\n");
|
||||
encryptable = 1;
|
||||
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
|
||||
}
|
||||
} else {
|
||||
INFO("Could not umount %s - allow continue unencrypted\n",
|
||||
fstab->recs[i].mount_point);
|
||||
fstab->recs[attempted_idx].mount_point);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -358,27 +388,28 @@ int fs_mgr_mount_all(struct fstab *fstab)
|
|||
/* mount(2) returned an error, check if it's encryptable and deal with it */
|
||||
if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
|
||||
fs_mgr_is_encryptable(&fstab->recs[i])) {
|
||||
if(partition_wiped(fstab->recs[i].blk_device) && fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT) {
|
||||
ERROR("Found an encryptable wiped partition with force encrypt. Formating via recovery.\n");
|
||||
wipe_data_via_recovery(); /* This is queue up a reboot */
|
||||
if (partition_wiped(fstab->recs[i].blk_device)) {
|
||||
ERROR("%s(): Encryptable wiped partition %s. Recommend wiping via recovery. Fail for now.\n", __func__, fstab->recs[i].mount_point);
|
||||
++error_count;
|
||||
continue;
|
||||
} else {
|
||||
/* Need to mount a tmpfs at this mountpoint for now, and set
|
||||
* properties that vold will query later for decrypting
|
||||
*/
|
||||
if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) {
|
||||
ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__,
|
||||
fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
|
||||
fstab->recs[attempted_idx].fs_type);
|
||||
if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
|
||||
++error_count;
|
||||
continue;
|
||||
}
|
||||
last_ok_mount_point = fstab->recs[i].mount_point;
|
||||
}
|
||||
encryptable = 1;
|
||||
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
|
||||
} else {
|
||||
ERROR("Failed to mount an un-encryptable or wiped partition on"
|
||||
"%s at %s options: %s error: %s\n",
|
||||
fstab->recs[i].blk_device, fstab->recs[i].mount_point,
|
||||
fstab->recs[i].fs_options, strerror(mount_errno));
|
||||
fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
|
||||
fstab->recs[attempted_idx].fs_options, strerror(mount_errno));
|
||||
++error_count;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ struct fstab_rec {
|
|||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
|
||||
void fs_mgr_free_fstab(struct fstab *fstab);
|
||||
|
||||
#define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 2
|
||||
#define FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED 1
|
||||
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 0
|
||||
int fs_mgr_mount_all(struct fstab *fstab);
|
||||
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
|
||||
char *tmp_mount_point);
|
||||
|
|
|
@ -511,27 +511,26 @@ int do_mount_all(int nargs, char **args)
|
|||
if (child_ret == -1) {
|
||||
ERROR("fs_mgr_mount_all returned an error\n");
|
||||
}
|
||||
exit(child_ret);
|
||||
_exit(child_ret);
|
||||
} else {
|
||||
/* fork failed, return an error */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ret is 2 if device needs encrypted, 1 if the device appears encrypted,
|
||||
* 0 if not, and -1 on error */
|
||||
if (ret == 2) {
|
||||
if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
|
||||
property_set("ro.crypto.state", "unencrypted");
|
||||
property_set("vold.decrypt", "trigger_encryption");
|
||||
} else if (ret == 1) {
|
||||
} else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("vold.decrypt", "trigger_default_encryption");
|
||||
} else if (ret == 0) {
|
||||
} else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
|
||||
property_set("ro.crypto.state", "unencrypted");
|
||||
/* If fs_mgr determined this is an unencrypted device, then trigger
|
||||
* that action.
|
||||
*/
|
||||
action_for_each_trigger("nonencrypted", action_add_queue_tail);
|
||||
}
|
||||
/* else ... < 0: error */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue