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

Commit 6d89610d authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Add fs_mgr option to enable/disable quotas.

To support upcoming disk usage calculation optimizations, this change
adds a new 'quota' mount flag.  As part of mounting an ext4 device,
we now enable/disable the quota feature using tune2fs to match the
requested value in the fstab.

When changing the quota status, we force a fsck pass on the device
before actually mounting it to prime the quota data structures which
are stored in hidden inodes.

Changing quota state and priming the data structures needs to happen
before we actually mount the device, so fs_mgr is the best place to
place this logic.

Test: builds, boots, enables and disables quota
Bug: 27948817
Change-Id: I7ccbf97cbc4a679bdd7a31a77be4b99aa9a88e66
parent 9a0fd1d5
Loading
Loading
Loading
Loading
+75 −2
Original line number Diff line number Diff line
@@ -213,6 +213,73 @@ static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
            le32_to_cpu(es->s_r_blocks_count_lo);
}

static int do_quota(char *blk_device, char *fs_type, struct fstab_rec *rec)
{
    int force_check = 0;
    if (!strcmp(fs_type, "ext4")) {
        /*
         * Some system images do not have tune2fs for licensing reasons
         * Detect these and skip reserve blocks.
         */
        if (access(TUNE2FS_BIN, X_OK)) {
            ERROR("Not running %s on %s (executable not in system image)\n",
                  TUNE2FS_BIN, blk_device);
        } else {
            char* arg1 = NULL;
            char* arg2 = NULL;
            int status = 0;
            int ret = 0;
            int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
            if (fd >= 0) {
                struct ext4_super_block sb;
                ret = read_super_block(fd, &sb);
                if (ret < 0) {
                    ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
                    goto out;
                }

                int has_quota = (sb.s_feature_ro_compat
                        & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
                int want_quota = fs_mgr_is_quota(rec) != 0;

                if (has_quota == want_quota) {
                    INFO("Requested quota status is match on %s\n", blk_device);
                    goto out;
                } else if (want_quota) {
                    INFO("Enabling quota on %s\n", blk_device);
                    arg1 = "-Oquota";
                    arg2 = "-Qusrquota,grpquota";
                    force_check = 1;
                } else {
                    INFO("Disabling quota on %s\n", blk_device);
                    arg1 = "-Q^usrquota,^grpquota";
                    arg2 = "-O^quota";
                }
            } else {
                ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
                return force_check;
            }

            char *tune2fs_argv[] = {
                TUNE2FS_BIN,
                arg1,
                arg2,
                blk_device,
            };
            ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
                                          &status, true, LOG_KLOG | LOG_FILE,
                                          true, NULL, NULL, 0);
            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
            }
      out:
            close(fd);
        }
    }
    return force_check;
}

static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
{
    /* Check for the types of filesystems we know how to check */
@@ -417,7 +484,10 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_
                continue;
            }

            if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
            int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                                       &fstab->recs[i]);

            if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
                check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                         fstab->recs[i].mount_point);
            }
@@ -787,7 +857,10 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
            wait_for_file(n_blk_device, WAIT_TIMEOUT);
        }

        if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
        int force_check = do_quota(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                                   &fstab->recs[i]);

        if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) {
            check_fs(n_blk_device, fstab->recs[i].fs_type,
                     fstab->recs[i].mount_point);
        }
+30 −23
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ static struct flag_list fs_mgr_flags[] = {
    { "swapprio=",          MF_SWAPPRIO },
    { "zramsize=",          MF_ZRAMSIZE },
    { "max_comp_streams=",  MF_MAX_COMP_STREAMS },
    { "verifyatboot",       MF_VERIFYATBOOT },
    { "verify",             MF_VERIFY },
    { "noemulatedsd",       MF_NOEMULATEDSD },
    { "notrim",             MF_NOTRIM },
@@ -83,6 +84,7 @@ static struct flag_list fs_mgr_flags[] = {
    { "nofail",             MF_NOFAIL },
    { "latemount",          MF_LATEMOUNT },
    { "reservedsize=",      MF_RESERVEDSIZE },
    { "quota",              MF_QUOTA },
    { "defaults",           0 },
    { 0,                    0 },
};
@@ -586,3 +588,8 @@ int fs_mgr_is_latemount(struct fstab_rec *fstab)
{
    return fstab->fs_mgr_flags & MF_LATEMOUNT;
}

int fs_mgr_is_quota(struct fstab_rec *fstab)
{
    return fstab->fs_mgr_flags & MF_QUOTA;
}
+23 −21
Original line number Diff line number Diff line
@@ -85,8 +85,10 @@ __BEGIN_DECLS
#define MF_FORCEFDEORFBE     0x10000
#define MF_LATEMOUNT         0x20000
#define MF_NOFAIL            0x40000
#define MF_VERIFYATBOOT      0x80000
#define MF_MAX_COMP_STREAMS 0x100000
#define MF_RESERVEDSIZE     0x200000
#define MF_QUOTA            0x400000

#define DM_BUF_SIZE 4096

+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ 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_is_quota(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);

int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);