summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJP Abgrall <jpa@google.com>2014-06-17 16:58:46 -0700
committerJP Abgrall <jpa@google.com>2014-06-17 17:01:20 -0700
commita794f86522f9125f2547c94ebc7c74d1e7ace013 (patch)
tree86c06f8e6089ebc0c1618a19dfc74e87041132af
parent1235158c29909132fbe9aa52939061fc81f0800e (diff)
downloadsystem_core-a794f86522f9125f2547c94ebc7c74d1e7ace013.tar.gz
system_core-a794f86522f9125f2547c94ebc7c74d1e7ace013.tar.bz2
system_core-a794f86522f9125f2547c94ebc7c74d1e7ace013.zip
fsmgr: allow for a multiple fs-types for a mount point.
This changes allows an fstab to contain multiple lines for a given mount point. The lines sharing a mount MUST be after each other. The 1st matching line is the primary when it comes to mounting and look ups for wiping. Mounting based on a mount_point will attempt each dup in turn until one succeeds. This is to allow quick experimentations between different FSes. It does not deal with checkfs yet, because the underlying invocation of fs-type appropriate fsck does not handle the error code. Only the primary FS (1st in the dups) is checked. Change-Id: I8329737454b53e2681436fe85cd00a9bc522676b Signed-off-by: JP Abgrall <jpa@google.com>
-rw-r--r--fs_mgr/fs_mgr.c69
-rw-r--r--fs_mgr/fs_mgr_fstab.c30
-rw-r--r--fs_mgr/include/fs_mgr.h5
3 files changed, 78 insertions, 26 deletions
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index d2938cf31..798007d8b 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -190,12 +190,12 @@ static void fs_set_blk_ro(const char *blockdev)
* sets the underlying block device to read-only if the mount is read-only.
* See "man 2 mount" for return values.
*/
-static int __mount(const char *source, const char *target,
- const char *filesystemtype, unsigned long mountflags,
- const void *data)
+static int __mount(const char *source, const char *target, const struct fstab_rec *rec)
{
- int ret = mount(source, target, filesystemtype, mountflags, data);
+ unsigned long mountflags = rec->flags;
+ int ret;
+ ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
fs_set_blk_ro(source);
}
@@ -232,13 +232,18 @@ static int device_is_debuggable() {
return strcmp(value, "1") ? 0 : 1;
}
+/* 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.
+ */
int fs_mgr_mount_all(struct fstab *fstab)
{
- int i = 0;
+ int i = 0, j = 0;
int encryptable = 0;
int error_count = 0;
int mret;
int mount_errno;
+ const char *last_ok_mount_point = NULL;
if (!fstab) {
return -1;
@@ -274,10 +279,26 @@ int fs_mgr_mount_all(struct fstab *fstab)
}
}
- mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
- fstab->recs[i].fs_type, fstab->recs[i].flags,
- fstab->recs[i].fs_options);
-
+ /*
+ * 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)) {
+ continue;
+ }
+ /* Hunt down an fstab entry for the same mount point that might succeed */
+ for (j = i, mret = -1;
+ /* We required that fstab entries for the same mountpoint be consecutive */
+ mret && j < fstab->num_entries && !strcmp(fstab->recs[i].mount_point, fstab->recs[j].mount_point);
+ j++) {
+ mret = __mount(fstab->recs[j].blk_device, fstab->recs[j].mount_point, &fstab->recs[j]);
+ }
+ /* Did one of the same mount points mount? If so pick it. */
+ if (!mret) {
+ i = j;
+ last_ok_mount_point = fstab->recs[i].mount_point;
+ }
if (!mret) {
/* If this is encryptable, need to trigger encryption */
if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) {
@@ -294,7 +315,6 @@ int fs_mgr_mount_all(struct fstab *fstab)
continue;
}
}
-
/* Success! Go get the next one */
continue;
}
@@ -308,10 +328,7 @@ int fs_mgr_mount_all(struct fstab *fstab)
/* Need to mount a tmpfs at this mountpoint for now, and set
* properties that vold will query later for decrypting
*/
- if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs",
- MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
- ERROR("Cannot mount tmpfs filesystem for encryptable fs at %s error: %s\n",
- fstab->recs[i].mount_point, strerror(errno));
+ if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) {
++error_count;
continue;
}
@@ -335,12 +352,16 @@ int fs_mgr_mount_all(struct fstab *fstab)
/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
* tmp mount we do to check the user password
+ * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
+ * in turn, and stop on 1st success, or no more match.
*/
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
char *tmp_mount_point)
{
int i = 0;
int ret = -1;
+ int mount_errors = 0;
+ int first_mount_errno = 0;
char *m;
if (!fstab) {
@@ -386,19 +407,23 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
} else {
m = fstab->recs[i].mount_point;
}
- if (__mount(n_blk_device, m, fstab->recs[i].fs_type,
- fstab->recs[i].flags, fstab->recs[i].fs_options)) {
- ERROR("Cannot mount filesystem on %s at %s options: %s error: %s\n",
- n_blk_device, m, fstab->recs[i].fs_options, strerror(errno));
- goto out;
+ if (__mount(n_blk_device, m, &fstab->recs[i])) {
+ if (!first_mount_errno) first_mount_errno = errno;
+ mount_errors++;
+ continue;
} else {
ret = 0;
goto out;
}
}
-
- /* We didn't find a match, say so and return an error */
- ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
+ if (mount_errors) {
+ ERROR("Cannot mount filesystem on %s at %s. error: %s\n",
+ n_blk_device, m, strerror(first_mount_errno));
+ ret = -1;
+ } else {
+ /* We didn't find a match, say so and return an error */
+ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
+ }
out:
return ret;
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 6c21425bd..3f841792c 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -367,25 +367,47 @@ int fs_mgr_add_entry(struct fstab *fstab,
return 0;
}
-struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
+/*
+ * Returns the 1st matching fstab_rec that follows the start_rec.
+ * start_rec is the result of a previous search or NULL.
+ */
+struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path)
{
int i;
-
if (!fstab) {
return NULL;
}
- for (i = 0; i < fstab->num_entries; i++) {
+ if (start_rec) {
+ for (i = 0; i < fstab->num_entries; i++) {
+ if (&fstab->recs[i] == start_rec) {
+ i++;
+ break;
+ }
+ }
+ } else {
+ i = 0;
+ }
+ for (; i < fstab->num_entries; i++) {
int len = strlen(fstab->recs[i].mount_point);
if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
(path[len] == '\0' || path[len] == '/')) {
return &fstab->recs[i];
}
}
-
return NULL;
}
+/*
+ * Returns the 1st matching mount point.
+ * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
+ * and give the fstab_rec from the previous search.
+ */
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
+{
+ return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
+}
+
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & MF_VOLDMANAGED;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 835cf6456..b8bb5aa16 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -24,6 +24,11 @@
extern "C" {
#endif
+/*
+ * 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
+ * return the 1st one.
+ */
struct fstab {
int num_entries;
struct fstab_rec *recs;