fs_mgr: support to reserved some blocks for an ext2/3/4 partition.
These reserved blocks used to root or claim to CAP_SYS_RESOURCES process. Change-Id: I4893bdb08399bf31a7640d4a63f4952cd636576f Merged-In: I4893bdb08399bf31a7640d4a63f4952cd636576f Signed-off-by: liminghao <liminghao@xiaomi.com>
This commit is contained in:
parent
dbfb20bda4
commit
9a0fd1d5d3
108
fs_mgr/fs_mgr.c
108
fs_mgr/fs_mgr.c
|
@ -22,6 +22,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/swap.h>
|
||||
|
@ -38,6 +39,7 @@
|
|||
#include <ext4_utils/ext4_sb.h>
|
||||
#include <ext4_utils/ext4_utils.h>
|
||||
#include <ext4_utils/wipe.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/loop.h>
|
||||
#include <logwrap/logwrap.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
@ -50,8 +52,9 @@
|
|||
#define KEY_IN_FOOTER "footer"
|
||||
|
||||
#define E2FSCK_BIN "/system/bin/e2fsck"
|
||||
#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
|
||||
#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
|
||||
#define MKSWAP_BIN "/system/bin/mkswap"
|
||||
#define TUNE2FS_BIN "/system/bin/tune2fs"
|
||||
|
||||
#define FSCK_LOG_FILE "/dev/fscklogs/log"
|
||||
|
||||
|
@ -180,6 +183,99 @@ static void check_fs(char *blk_device, char *fs_type, char *target)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Function to read the primary superblock */
|
||||
static int read_super_block(int fd, struct ext4_super_block *sb)
|
||||
{
|
||||
off64_t ret;
|
||||
|
||||
ret = lseek64(fd, 1024, SEEK_SET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = read(fd, sb, sizeof(*sb));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != sizeof(*sb))
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
|
||||
{
|
||||
return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
|
||||
le32_to_cpu(es->s_blocks_count_lo);
|
||||
}
|
||||
|
||||
static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
|
||||
{
|
||||
return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
|
||||
le32_to_cpu(es->s_r_blocks_count_lo);
|
||||
}
|
||||
|
||||
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 */
|
||||
if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !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 {
|
||||
INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);
|
||||
|
||||
int status = 0;
|
||||
int ret = 0;
|
||||
unsigned long reserved_blocks = 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;
|
||||
}
|
||||
reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
|
||||
unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
|
||||
if (reserved_threshold < reserved_blocks) {
|
||||
WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
|
||||
reserved_blocks = reserved_threshold;
|
||||
}
|
||||
|
||||
if (ext4_r_blocks_count(&sb) == reserved_blocks) {
|
||||
INFO("Have reserved same blocks\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[16] = {0};
|
||||
snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
|
||||
char *tune2fs_argv[] = {
|
||||
TUNE2FS_BIN,
|
||||
buf,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_trailing_slashes(char *n)
|
||||
{
|
||||
int len;
|
||||
|
@ -325,6 +421,12 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_
|
|||
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_RESERVEDSIZE) {
|
||||
do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
|
||||
&fstab->recs[i]);
|
||||
}
|
||||
|
||||
if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
|
||||
*attempted_idx = i;
|
||||
mounted = 1;
|
||||
|
@ -690,6 +792,10 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
|
|||
fstab->recs[i].mount_point);
|
||||
}
|
||||
|
||||
if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
|
||||
do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
|
||||
}
|
||||
|
||||
if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
|
||||
int rc = fs_mgr_setup_verity(&fstab->recs[i]);
|
||||
if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
|
||||
|
|
|
@ -33,6 +33,7 @@ struct fs_mgr_flag_values {
|
|||
int swap_prio;
|
||||
int max_comp_streams;
|
||||
unsigned int zram_size;
|
||||
uint64_t reserved_size;
|
||||
unsigned int file_encryption_mode;
|
||||
};
|
||||
|
||||
|
@ -81,6 +82,7 @@ static struct flag_list fs_mgr_flags[] = {
|
|||
{ "slotselect", MF_SLOTSELECT },
|
||||
{ "nofail", MF_NOFAIL },
|
||||
{ "latemount", MF_LATEMOUNT },
|
||||
{ "reservedsize=", MF_RESERVEDSIZE },
|
||||
{ "defaults", 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
@ -107,6 +109,20 @@ static uint64_t calculate_zram_size(unsigned int percentage)
|
|||
return total;
|
||||
}
|
||||
|
||||
static uint64_t parse_size(const char *arg)
|
||||
{
|
||||
char *endptr;
|
||||
uint64_t size = strtoull(arg, &endptr, 10);
|
||||
if (*endptr == 'k' || *endptr == 'K')
|
||||
size *= 1024LL;
|
||||
else if (*endptr == 'm' || *endptr == 'M')
|
||||
size *= 1024LL * 1024LL;
|
||||
else if (*endptr == 'g' || *endptr == 'G')
|
||||
size *= 1024LL * 1024LL * 1024LL;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int parse_flags(char *flags, struct flag_list *fl,
|
||||
struct fs_mgr_flag_values *flag_vals,
|
||||
char *fs_options, int fs_options_len)
|
||||
|
@ -216,6 +232,11 @@ static int parse_flags(char *flags, struct flag_list *fl,
|
|||
flag_vals->zram_size = calculate_zram_size(val);
|
||||
else
|
||||
flag_vals->zram_size = val;
|
||||
} else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
|
||||
/* The reserved flag is followed by an = and the
|
||||
* reserved size of the partition. Get it and return it.
|
||||
*/
|
||||
flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -360,6 +381,7 @@ struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
|
|||
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
|
||||
fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
|
||||
fstab->recs[cnt].zram_size = flag_vals.zram_size;
|
||||
fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
|
||||
fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
|
||||
cnt++;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ __BEGIN_DECLS
|
|||
#define MF_LATEMOUNT 0x20000
|
||||
#define MF_NOFAIL 0x40000
|
||||
#define MF_MAX_COMP_STREAMS 0x100000
|
||||
#define MF_RESERVEDSIZE 0x200000
|
||||
|
||||
#define DM_BUF_SIZE 4096
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ struct fstab_rec {
|
|||
int swap_prio;
|
||||
int max_comp_streams;
|
||||
unsigned int zram_size;
|
||||
uint64_t reserved_size;
|
||||
unsigned int file_encryption_mode;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue