diff options
Diffstat (limited to 'fs_mgr')
-rw-r--r-- | fs_mgr/fs_mgr.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 0361ab8..e51c9cf 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -58,6 +58,12 @@ static struct flag_list mount_flags[] = { { "ro", MS_RDONLY }, { "rw", 0 }, { "remount", MS_REMOUNT }, + { "bind", MS_BIND }, + { "rec", MS_REC }, + { "unbindable", MS_UNBINDABLE }, + { "private", MS_PRIVATE }, + { "slave", MS_SLAVE }, + { "shared", MS_SHARED }, { "defaults", 0 }, { 0, 0 }, }; @@ -167,7 +173,7 @@ out: * then return an empty buffer. This effectively ignores lines that are too long. * On EOF, return null. */ -static char *getline(char *buf, int size, FILE *file) +static char *fs_getline(char *buf, int size, FILE *file) { int cnt = 0; int eof = 0; @@ -241,7 +247,7 @@ static struct fstab_rec *read_fstab(char *fstab_path) } entries = 0; - while (getline(line, sizeof(line), fstab_file)) { + while (fs_getline(line, sizeof(line), fstab_file)) { /* if the last character is a newline, shorten the string by 1 byte */ len = strlen(line); if (line[len - 1] == '\n') { @@ -268,7 +274,7 @@ static struct fstab_rec *read_fstab(char *fstab_path) fseek(fstab_file, 0, SEEK_SET); cnt = 0; - while (getline(line, sizeof(line), fstab_file)) { + while (fs_getline(line, sizeof(line), fstab_file)) { /* if the last character is a newline, shorten the string by 1 byte */ len = strlen(line); if (line[len - 1] == '\n') { @@ -358,13 +364,34 @@ static void free_fstab(struct fstab_rec *fstab) free(fstab); } -static void check_fs(char *blk_dev, char *type) +static void check_fs(char *blk_dev, char *type, char *target) { pid_t pid; int status; + int ret; + long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; + char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; /* Check for the types of filesystems we know how to check */ if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) { + /* + * First try to mount and unmount the filesystem. We do this because + * the kernel is more efficient than e2fsck in running the journal and + * processing orphaned inodes, and on at least one device with a + * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes + * to do what the kernel does in about a second. + * + * After mounting and unmounting the filesystem, run e2fsck, and if an + * error is recorded in the filesystem superblock, e2fsck will do a full + * check. Otherwise, it does nothing. If the kernel cannot mount the + * filesytsem due to an error, e2fsck is still run to do a full check + * fix the filesystem. + */ + ret = mount(blk_dev, target, type, tmpmnt_flags, tmpmnt_opts); + if (! ret) { + umount(target); + } + INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev); pid = fork(); if (pid > 0) { @@ -434,7 +461,7 @@ int fs_mgr_mount_all(char *fstab_file) } if (fstab[i].fs_mgr_flags & MF_CHECK) { - check_fs(fstab[i].blk_dev, fstab[i].type); + check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); } mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type, @@ -496,11 +523,11 @@ int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_m /* We found our match */ /* First check the filesystem if requested */ if (fstab[i].fs_mgr_flags & MF_WAIT) { - wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); + wait_for_file(n_blk_dev, WAIT_TIMEOUT); } if (fstab[i].fs_mgr_flags & MF_CHECK) { - check_fs(fstab[i].blk_dev, fstab[i].type); + check_fs(n_blk_dev, fstab[i].type, fstab[i].mnt_point); } /* Now mount it where requested */ |