Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93a67779 authored by JP Abgrall's avatar JP Abgrall Committed by Android (Google) Code Review
Browse files

Merge "fsmgr: support multiple fs-types/mountpoint"

parents da7a448f 5c01dac6
Loading
Loading
Loading
Loading
+69 −32
Original line number Original line Diff line number Diff line
@@ -113,6 +113,7 @@ static void check_fs(char *blk_device, char *fs_type, char *target)
         * fix the filesystem.
         * fix the filesystem.
         */
         */
        ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
        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) {
        if (!ret) {
            umount(target);
            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.
 * sets the underlying block device to read-only if the mount is read-only.
 * See "man 2 mount" for return values.
 * See "man 2 mount" for return values.
 */
 */
static int __mount(const char *source, const char *target,
static int __mount(const char *source, const char *target, const struct fstab_rec *rec)
                   const char *filesystemtype, unsigned long mountflags,
                   const void *data)
{
{
    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) {
    if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
        fs_set_blk_ro(source);
        fs_set_blk_ro(source);
    }
    }

    errno = save_errno;
    return ret;
    return ret;
}
}


@@ -232,13 +236,18 @@ static int device_is_debuggable() {
    return strcmp(value, "1") ? 0 : 1;
    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 fs_mgr_mount_all(struct fstab *fstab)
{
{
    int i = 0;
    int i = 0, j = 0;
    int encryptable = 0;
    int encryptable = 0;
    int error_count = 0;
    int error_count = 0;
    int mret;
    int mret = -1;
    int mount_errno;
    int mount_errno = 0;
    const char *last_ok_mount_point = NULL;


    if (!fstab) {
    if (!fstab) {
        return -1;
        return -1;
@@ -261,11 +270,6 @@ int fs_mgr_mount_all(struct fstab *fstab)
            wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
            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) &&
        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
            !device_is_debuggable()) {
            !device_is_debuggable()) {
            if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
            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,
         * Don't try to mount/encrypt the same mount point again.
                       fstab->recs[i].fs_options);
         * 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 (!mret) {
            /* If this is encryptable, need to trigger encryption */
            /* If this is encryptable, need to trigger encryption */
            if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) {
            if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) {
@@ -294,24 +329,18 @@ int fs_mgr_mount_all(struct fstab *fstab)
                    continue;
                    continue;
                }
                }
            }
            }

            /* Success!  Go get the next one */
            /* Success!  Go get the next one */
            continue;
            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 */
        /* 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)) &&
            (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) &&
            !partition_wiped(fstab->recs[i].blk_device)) {
            !partition_wiped(fstab->recs[i].blk_device)) {
            /* Need to mount a tmpfs at this mountpoint for now, and set
            /* Need to mount a tmpfs at this mountpoint for now, and set
             * properties that vold will query later for decrypting
             * properties that vold will query later for decrypting
             */
             */
            if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs",
            if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) {
                      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));
                ++error_count;
                ++error_count;
                continue;
                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
/* If tmp_mount_point is non-null, mount the filesystem there.  This is for the
 * tmp mount we do to check the user password
 * 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,
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
                    char *tmp_mount_point)
                    char *tmp_mount_point)
{
{
    int i = 0;
    int i = 0;
    int ret = -1;
    int ret = -1;
    int mount_errors = 0;
    int first_mount_errno = 0;
    char *m;
    char *m;


    if (!fstab) {
    if (!fstab) {
@@ -386,19 +419,23 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
        } else {
        } else {
            m = fstab->recs[i].mount_point;
            m = fstab->recs[i].mount_point;
        }
        }
        if (__mount(n_blk_device, m, fstab->recs[i].fs_type,
        if (__mount(n_blk_device, m, &fstab->recs[i])) {
                    fstab->recs[i].flags, fstab->recs[i].fs_options)) {
            if (!first_mount_errno) first_mount_errno = errno;
            ERROR("Cannot mount filesystem on %s at %s options: %s error: %s\n",
            mount_errors++;
                n_blk_device, m, fstab->recs[i].fs_options, strerror(errno));
            continue;
            goto out;
        } else {
        } else {
            ret = 0;
            ret = 0;
            goto out;
            goto out;
        }
        }
    }
    }

    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 */
        /* 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);
        ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
    }


out:
out:
    return ret;
    return ret;
+26 −4
Original line number Original line Diff line number Diff line
@@ -367,25 +367,47 @@ int fs_mgr_add_entry(struct fstab *fstab,
     return 0;
     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;
    int i;

    if (!fstab) {
    if (!fstab) {
        return NULL;
        return NULL;
    }
    }


    if (start_rec) {
        for (i = 0; i < fstab->num_entries; i++) {
        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);
        int len = strlen(fstab->recs[i].mount_point);
        if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
        if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
            (path[len] == '\0' || path[len] == '/')) {
            (path[len] == '\0' || path[len] == '/')) {
            return &fstab->recs[i];
            return &fstab->recs[i];
        }
        }
    }
    }

    return NULL;
    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)
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
{
{
    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
+5 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,11 @@
extern "C" {
extern "C" {
#endif
#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 {
struct fstab {
    int num_entries;
    int num_entries;
    struct fstab_rec *recs;
    struct fstab_rec *recs;