diff options
author | JP Abgrall <jpa@google.com> | 2014-06-18 23:55:11 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-06-18 19:24:54 +0000 |
commit | 93a67779dc0d85d71dfe333244084341be0aa458 (patch) | |
tree | 8981f0e7c7c2ce231ad09e1554275f69a0957182 /fs_mgr/fs_mgr.c | |
parent | da7a448f38cd812b3d2519381dcae23a4dc305bb (diff) | |
parent | 5c01dac6d81a804dcff233da777882bec852f25b (diff) | |
download | system_core-93a67779dc0d85d71dfe333244084341be0aa458.zip system_core-93a67779dc0d85d71dfe333244084341be0aa458.tar.gz system_core-93a67779dc0d85d71dfe333244084341be0aa458.tar.bz2 |
Merge "fsmgr: support multiple fs-types/mountpoint"
Diffstat (limited to 'fs_mgr/fs_mgr.c')
-rw-r--r-- | fs_mgr/fs_mgr.c | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index d2938cf..183712a 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -113,6 +113,7 @@ static void check_fs(char *blk_device, char *fs_type, char *target) * fix the filesystem. */ ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); + INFO("%s(): mount(%s,%s,%s)=%d\n", __func__, blk_device, target, fs_type, ret); if (!ret) { umount(target); } @@ -190,16 +191,19 @@ 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; + int save_errno; + ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); + save_errno = errno; + INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret); if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { fs_set_blk_ro(source); } - + errno = save_errno; return ret; } @@ -232,13 +236,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; + int mret = -1; + int mount_errno = 0; + const char *last_ok_mount_point = NULL; if (!fstab) { return -1; @@ -261,11 +270,6 @@ int fs_mgr_mount_all(struct fstab *fstab) wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } - 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 ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { @@ -274,10 +278,41 @@ 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)) { + 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; + } + } + /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) { @@ -294,24 +329,18 @@ int fs_mgr_mount_all(struct fstab *fstab) continue; } } - /* Success! Go get the next one */ continue; } - /* back up errno as partition_wipe clobbers the value */ - mount_errno = errno; /* mount(2) returned an error, check if it's encryptable and deal with it */ - if (mount_errno != EBUSY && mount_errno != EACCES && + if (mret && mount_errno != EBUSY && mount_errno != EACCES && (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) && !partition_wiped(fstab->recs[i].blk_device)) { /* 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 +364,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 +419,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; |