Linux fsck 机制解析
Linux fsck 机制
0. 概述
fsck的运行主要需要解决两个问题:
1、怎么样才能让系统调用fsck?
2、fsck被调用时很多情况下只会打印一些信息,怎么样才能启动完整的磁盘扫描?
1. Upstart 方式 (ubuntu 14.04 32bit)
Upstart的fsck配置概述如下:
1.1 配置fsck启动
- 1、fstab的
pass
选项
一个分区如果需要在启动的过程中做磁盘修复,需要把fstab中的pass
选项配置成1
或者2
。这样mountall命令才会对对应分区调用fsck操作;
根分区/
的pass
选项默认为1,在fstab文件中无法更改;
1.2 配置fsck运行参数
在fsck被mountall调用后,并不会对对应分区做完整的扫描。
它需要满足以下任一条件才会启动:
条件1、文件系统被标记出错"dirty";
条件2、需要满足check间隔的时间 或者 mount的次数到达限制;
条件3、使用-f
选项调用fsck;
- 1、
force-fsck
模式
使能force-fsck
模式,会强制对根分区/
进行fsck完整扫描。
它的操作有以下特点:
特点1、只会影响根分区/
,对其他分区无效;
特点2、根分区/
的pass
选项默认为1,所以fstab中的配置无影响;
特点3、会直接使用-f
选项调用fsck,会强行完整扫描,突破check时间、mount次数、错误状态的限制;
有以下几种方式可以进入force-fsck
模式:
方式1:在根目录/
下创建/forcefsck
文件。这种方式可以强制系统在启动时进入1次force-fsck
模式,在执行完强制fsck后,系统会自动删除/forcefsck
文件;
方式2:在cmdline中加入force-fsck
选项。这种方式是永久有效的,每次系统启动时都会使能force-fsck
模式;
- 2、
fsck-fix
选项
在fsck检查到错误时,怎么样应对修复?
fsck的-a
和-y
对应不同的修复策略:
opt | descripts |
---|---|
-a | Automatically repair the filesystem without any questions (use this option with caution). Note that e2fsck supports -a for backward compatibility only. This option is mapped to e2fsck’s -p option that is safe to use, unlike the -a option that some filesystem checkers support. |
-y | For some filesystem-specific checkers, the -y option will cause the fs-specific fsck to always attempt to fix any detected filesystem corruption automatically. Sometimes an expert may be able to do better driving the fsck manually. Note that not all filesystem-specific checkers implement this option. In particular fsck.minix and fsck.cramfs do not support the -y option. |
fsck默认使用-a
选项。
如果"/etc/default/rcS"文件中的变量"$FSCKFIX" = “yes”,fsck使用-y
选项。
下面是具体的分析过程。
1.3 mountall.config
updtart系统启动过程中关于磁盘挂载的流程:init -> /etc/init/mountall.conf -> mountall
。首先mountall.conf会响应startup
事件根据配置调用mountall程序,mountall会读取 /lib/init/fstab 和 /etc/fstab 里的配置按顺序挂载分区。
- mountall.conf配置
# mountall - Mount filesystems on boot
#
# This helper mounts filesystems in the correct order as the devices
# and mountpoints become available.
description "Mount filesystems on boot"
start on startup
stop on starting rcS
expect daemon
task
emits virtual-filesystems
emits local-filesystems
emits remote-filesystems
emits all-swaps
emits filesystem
emits mounting
emits mounted
script
/* (1) 从"/etc/default/rcS"导入配置 */
. /etc/default/rcS || true
/* (2) 如果根目录下有"/forcefsck"文件,设置mountall命令的"--force-fsck"选项 */
[ -f /forcefsck ] && force_fsck="--force-fsck"
/* (3) 如果变量"$FSCKFIX" = "yes",设置mountall命令的"--fsck-fix"选项 */
[ "$FSCKFIX" = "yes" ] && fsck_fix="--fsck-fix"
# Doesn't work so well if mountall is responsible for mounting /proc, heh.
/* (4) 从cmdline中解析出的"$debug_arg"选项 */
if [ -e /proc/cmdline ]; then
read line < /proc/cmdline
for arg in $line; do
case $arg in
-q|--quiet|-v|--verbose|--debug)
debug_arg=$arg
;;
esac
done < /proc/cmdline
fi
# set $LANG so that messages appearing in plymouth are translated
if [ -r /etc/default/locale ]; then
. /etc/default/locale || true
export LANG LANGUAGE LC_MESSAGES LC_ALL
fi
/* (5) 使用各种选项来调用mountall命令 */
exec mountall --daemon $force_fsck $fsck_fix $debug_arg
end script
post-stop script
/* (6) script执行完成后,删除可能存在的"/forcefsck"文件 */
rm -f /forcefsck 2>dev/null || true
end script
可以看到mountall.conf中有两个配置会影响到fsck的检查:
配置1.1:"/forcefsck"文件。
如果存在"/forcefsck"文件,传递"–force-fsck"选项给mountall命令调用:
如果传递--force-fsck
,mountall
最后会使用-f
选项来调用fsck
命令对根目录/
进行强制磁盘扫描;注意该选项只对根目录/
有效,对其他分区无效;
配置1.2:rcS文件中的"$FSCKFIX"配置。
如果"/etc/default/rcS"文件中的变量"$FSCKFIX" = “yes”,传递"–fsck-fix"选项给mountall命令调用:
如果传递--fsck-fix
,mountall
最后会使用-y
选项来调用fsck
命令;该选项的意思是如果扫描到出错,默认回答yes进行修复;否则使用-a
选项来调用fsck
命令,错误修复需要用户来回答;
1.4 mountall
关于系统启动过程中的fsck操作,第一步会进入mountall,mountall命令解析各种参数,再根据参数调用fsck
- mountall命令参数
$ mountall --help
Usage: mountall [OPTION]...
启动时挂载文件系统
Options:
--daemon Detach and run in the background
--force-fsck Force check of all filesystems
--fsck-fix Attempt to fix all fsck errors
--no-events Do not emit events after mounting filesystems
--dev-wait-time=value in seconds (Default is 30 seconds, Legal value between 1second to 2147483647 seconds)
In case of (bootwait,timeout): specify the time to wait for device to be detected
-q, --quiet reduce output to errors only
-v, --verbose increase output to include informational messages
--help display this help and exit
--version output version information and exit
mountall 默认运行在前台且不自动进行控制台分离,请使用 --daemon 参数使其成为守护进程。
Report bugs to <ubuntu-devel@lists.ubuntu.com>
- mountall命令的实现
在mountall.conf解析完选项后会调用mountall
命令,mountall
命令中继续实现对fsck
相关各项参数的解析和调用。
配置2.1:cmdline中的force-fsck
选项。
如果cmdline中存在force-fsck
选项,mountall
最后会使用-f
选项来调用fsck
命令对根目录/
进行强制磁盘扫描;注意该选项只对根目录/
有效,对其他分区无效;
mountall-2.53\src\mountall.c:
main()
{
/* Check for force-fsck on the kernel command line */
cmdline = fopen ("/proc/cmdline", "r");
if (cmdline) {
char line[4096];
if (fgets (line, sizeof line, cmdline)) {
char *tok;
for (tok = strtok (line, " "); tok;
tok = strtok (NULL, " "))
/* (1) 根据cmdline中的关键字配置force_fsck参数 */
if (! strcmp (tok, "force-fsck"))
force_fsck = 1;
}
fclose (cmdline);
}
}
需要特别注意的是,force-fsck
有2个特点:
1、它只对根目录/
有效,设置了该选项只会强制扫描根目录,对其他分区无效;
2、它会突破e2fsck中Maximum mount count
选项的限制,只要设置了force-fsck
选项,无视Maximum mount count
选项的配置;
配置2.2:fstab文件中pass
选项。
对于没有配置force-fsck
选项的场景,需要根据fstab文件中pass
选项来决定是否调用fsck
命令对对应的分区进行磁盘扫描:
/etc/fstab:
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation
UUID=a9cee914-ac8e-4f1b-8ef1-7c036b491e63 / ext4 errors=remount-ro 0 1
# swap was on /dev/sda5 during installation
UUID=a0a57bb8-ebd8-4e99-a7b8-ba94fea5dc0e none swap sw 0 0
/dev/fd0 /media/floppy0 auto rw,user,noauto,exec,utf8 0 0
/dev/sdb1 /usr/src/work ext3 defaults 0 0
UUID=f3221963-db14-477f-913f-5ff3a74f026a /home/zhoulei/data ext4 defaults 0 0
和fsck相关的是最后一个pass
选项:
0: 值为0时,永远不检查;
1: 而 / 根目录分区永远都为1。
2: 其它分区从2开始,数字越小越先检查,如果两个分区的数字相同,则同时检查。
注意:根目录/
不管fstab中pass
选项的配置,根目录分区pass
永远都为1;
mountall命令源代码中对fstab选项的解析:
mountall-2.53\src\mountall.c:
main() -> parse_fstab()
void
parse_fstab (const char *filename)
{
/* (1) fstab中的"pass"选项解析到 mntent->mnt_passno 结构体成员当中
并且赋值给 mnt->check
*/
while ((mntent = getmntent (fstab)) != NULL) {
Mount * mnt;
nih_local char *fsname = NULL;
mnt = find_mount (mntent->mnt_dir);
if (mnt && (!mnt->src || strcmp (mnt->src, filename))
&& strcmp (mntent->mnt_type, "swap")) {
update_mount (mnt,
mntent->mnt_fsname,
mntent->mnt_passno != 0,
mntent->mnt_type,
mntent->mnt_opts);
} else {
new_mount (mntent->mnt_dir,
mntent->mnt_fsname,
mntent->mnt_passno != 0,
mntent->mnt_type,
mntent->mnt_opts,
filename);
}
}
endmntent (fstab);
}
mountall命令源代码中对是否执行fsck的判断:
mountall-2.53\src\mountall.c:
void
run_fsck (Mount *mnt)
{
nih_local char **args = NULL;
size_t args_len = 0;
int fds[2];
int flags;
nih_assert (mnt != NULL);
/* (1) 对于不满足fsck条件的,直接mount完返回 */
if (mnt->ready) {
nih_debug ("%s: already ready", MOUNT_NAME (mnt));
try_mount (mnt, FALSE);
return;
/* (1.1) 对于普通分区 mnt->check > 0 时调用fsck
对于"/"根分区 force_fsck = 1 时调用fsck
*/
} else if (! mnt->check
&& (! force_fsck || strcmp (mnt->mountpoint, "/"))) {
nih_debug ("%s: no check required", MOUNT_NAME (mnt));
mnt->ready = TRUE;
try_mount (mnt, FALSE);
return;
} else if (missing_fsck (mnt)) {
nih_debug ("%s: no appropriate fsck.* present",
MOUNT_NAME (mnt));
mnt->ready = TRUE;
try_mount (mnt, FALSE);
return;
} else if (mnt->nodev
|| (! strcmp (mnt->type, "none"))) {
nih_debug ("%s: no device to check", MOUNT_NAME (mnt));
mnt->ready = TRUE;
try_mount (mnt, FALSE);
return;
} else if (mnt->mounted && (! has_option (mnt, "ro", TRUE))) {
nih_debug ("%s: mounted filesystem", MOUNT_NAME (mnt));
mnt->ready = TRUE;
try_mount (mnt, FALSE);
return;
} else if (mnt->fsck_pid > 0) {
nih_debug ("%s: already checking", MOUNT_NAME (mnt));
return;
} else if (mnt->error > ERROR_BORED) {
nih_debug ("%s still has uncleared errors", MOUNT_NAME (mnt));
return;
}
nih_info (_("checking %s"), MOUNT_NAME (mnt));
/* Create a pipe to receive progress indication */
if (pipe2 (fds, O_CLOEXEC) < 0) {
nih_fatal ("Unable to create pipe for spawned process: %s",
strerror (errno));
exit (EXIT_ERROR);
}
flags = fcntl (fds[1], F_GETFD);
if ((flags < 0)
|| (fcntl (fds[1], F_SETFD, flags &~ FD_CLOEXEC) < 0)
|| (! NIH_SHOULD (nih_io_reopen (NULL, fds[0], NIH_IO_STREAM,
(NihIoReader)fsck_reader,
NULL, NULL, mnt)))) {
close (fds[0]);
close (fds[1]);
fds[0] = fds[1] = -1;
}
/* (2) 对于满足fsck条件的,构造fsck命令的选项 args */
args = NIH_MUST (nih_str_array_new (NULL));
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "fsck"));
if (fsck_fix || mnt->fsck_fix) {
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-y"));
} else {
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-a"));
}
if (fds[1] >= 0) {
nih_local char *arg = NULL;
arg = NIH_MUST (nih_sprintf (NULL, "-C%d", fds[1]));
NIH_MUST (nih_str_array_addp (&args, NULL, &args_len, arg));
}
if (force_fsck)
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-f"));
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-t"));
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->type));
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->device));
mnt->error = ERROR_NONE;
/* (2.1) 创建新线程来执行fsck,具体参数配置在args中 */
mnt->fsck_pid = spawn (mnt, args, FALSE, run_fsck_finished);
mnt->fsck_progress = -1;
fsck_update ();
/* Close writing end, reading end is left open inside the NihIo
* structure watching it until the remote end is closed by fsck
* finishing.
*/
if (fds[1] >= 0)
close (fds[1]);
}
1.5 fsck
mountall命令的运行的过程中,会根据配置来调用fsck
命令:
- fsck命令参数
$ fsck --help
fsck,来自 util-linux 2.20.1
fsck.ext4:无效选项 -- h
Usage: fsck.ext4 [-panyrcdfvtDFV] [-b superblock] [-B blocksize]
[-I inode_buffer_blocks] [-P process_inode_size]
[-l|-L bad_blocks_file] [-C fd] [-j external_journal]
[-E extended-options] device
Emergency help:
-p Automatic repair (no questions)
-n Make no changes to the filesystem
-y Assume "yes" to all questions
-c Check for bad blocks and add them to the badblock list
-f Force checking even if filesystem is marked clean
-v Be verbose
-b superblock Use alternative superblock
-B blocksize Force blocksize when looking for superblock
-j external_journal Set location of the external journal
-l bad_blocks_file Add to badblocks list
-L bad_blocks_file Set badblocks list
$
- e2fsck命令:
fsck命令是一个总入口,它会根据具体分区的文件系统,调用具体对应的工具。例如ext2/3/4调用的是e2fsck工具。
$ ls -l /sbin/fsck*
-rwxr-xr-x 1 root root 30540 9月 3 2015 /sbin/fsck
-rwxr-xr-x 1 root root 13820 9月 3 2015 /sbin/fsck.cramfs
lrwxrwxrwx 1 root root 6 9月 10 2015 /sbin/fsck.ext2 -> e2fsck
lrwxrwxrwx 1 root root 6 9月 10 2015 /sbin/fsck.ext3 -> e2fsck
lrwxrwxrwx 1 root root 6 9月 10 2015 /sbin/fsck.ext4 -> e2fsck
lrwxrwxrwx 1 root root 6 9月 10 2015 /sbin/fsck.ext4dev -> e2fsck
-rwxr-xr-x 1 root root 54900 3月 18 2014 /sbin/fsck.fat
-rwxr-xr-x 1 root root 30292 9月 3 2015 /sbin/fsck.minix
lrwxrwxrwx 1 root root 8 5月 6 2015 /sbin/fsck.msdos -> fsck.fat
-rwxr-xr-x 1 root root 333 2月 17 2016 /sbin/fsck.nfs
lrwxrwxrwx 1 root root 8 5月 6 2015 /sbin/fsck.vfat -> fsck.fat
当你配置完fstab文件中pass
选项以后,满心欢喜的执行fsck:
$ sudo fsck /dev/sdc1
fsck,来自 util-linux 2.20.1
e2fsck 1.42.9 (4-Feb-2014)
/dev/sdc1: clean, 14/6553600 files, 1452366/26214144 blocks
你会发现fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。
ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f
选项调用fsck;
配置3.1:需要满足ext文件系统的check间隔时间,执行e2fsck才会启动真正的扫描和修复。
默认间隔为0,意味着就算执行e2fsck也不会真正的check。
$ sudo tune2fs -l /dev/sdc1
...
Last checked: Tue Nov 12 15:35:53 2019
Check interval: 0 (<none>)
...
可以使用tune2fs -i
命令来设置扫描间隔时间:
tune2fs -i 10 /dev/sdc1 10天后检查
tune2fs -i 1d /dev/sdc1 1天后检查
tune2fs -i 3w /dev/sdc1 3周后检查
tune2fs -i 6m /dev/sdc1 半年后检查
tune2fs -i 0 /dev/sdc1 禁用时间检查
配置3.2:或者满足mount次数达到限制,执行e2fsck才会启动真正的扫描和修复。
默认Maximum mount count
为-1
,意味着就算执行e2fsck也不会真正的check。
$ sudo tune2fs -l /dev/sdc1
...
Mount count: 2
Maximum mount count: -1
...
可以使用tune2fs -c
命令来设置mount次数条件:
tune2fs -c 1 /dev/sdc1 设置每mount1次就进行一次check。
tune2fs -c -l /dev/sdc1 关闭强制检查挂载次数限制。
完整的文件系统检查和修复:
$ sudo fsck /dev/sdc1
fsck,来自 util-linux 2.20.1
e2fsck 1.42.9 (4-Feb-2014)
/dev/sdc1 has been mounted 2 times without being checked, 强制检查.
第一步: 检查inode,块,和大小
第二步: 检查目录结构
第3步: 检查目录连接性
Pass 4: Checking reference counts
第5步: 检查簇概要信息
/dev/sdc1: 14/6553600 files (0.0% non-contiguous), 1452366/26214144 blocks
2. Systemd 方式 (ubuntu 16.04 64bit)
systemd下面已经抛弃了mountall命令,它使用以下的local-fs.target
关联的mount来加载分区,根据配置使用systemd-fsck-root.service
和systemd-fsck@.service
来调用fsck。
│ │ ├─local-fs.target
│ │ │ ├─-.mount
│ │ │ ├─home-root.mount
│ │ │ ├─media-ram.mount
│ │ │ ├─mnt-app.mount
│ │ │ ├─systemd-fsck-root.service
│ │ │ ├─systemd-remount-fs.service
│ │ │ ├─tmp.mount
│ │ │ ├─var-lib-machines.mount
│ │ │ ├─var-volatile-lib.service
│ │ │ └─var-volatile.mount
/lib/systemd/system/systemd-fsck-root.service:
[Unit]
Description=File System Check on Root Device
Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
Before=local-fs.target shutdown.target
ConditionPathIsReadWrite=!/
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck
TimeoutSec=0
~
/lib/systemd/system/systemd-fsck@.service:
[Unit]
Description=File System Check on %f
Documentation=man:systemd-fsck@.service(8)
DefaultDependencies=no
BindsTo=%i.device
After=%i.device systemd-fsck-root.service local-fs-pre.target
Before=shutdown.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck %f
TimeoutSec=0
2.1 普通分区的fsck
除了Root分区以外的普通分区使能fsck非常简单,直接使能fstab中的pass
选项即可:
myc@myc-virtual-machine:~$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation
UUID=bdc34999-c918-4a67-a92d-9bd7732e3820 / ext4 errors=remount-ro 0 1
# swap was on /dev/sda5 during installation
UUID=f2fc9a8d-6ed3-4e59-8265-7aff14f95b98 none swap sw 0 0
UUID=1ec003be-8d57-414f-884e-5ebcfc2e5ac6 /home/myc/data ext4 defaults 1 2
UUID=d9f51ab3-0053-4156-a175-e9732018ee16 /home/myc/vx ext4 defaults 1 2
最后的两个普通分区sdb1
和sdc1
的pass
选项被配置成了2
。
重启系统在sudo journal -b
的输出结果中查找fsck
关键字,可以在系统启动日志中可以看到fsck的情况:
11月 14 18:05:11 myc-virtual-machine systemd-fsck[743]: /dev/sdb1: clean, 328353/2621440 files, 3552241/10485504 blocks
11月 14 18:05:11 myc-virtual-machine systemd-fsck[713]: /dev/sdc1: clean, 293466/6553600 files, 5998689/26214144 blocks
2.2 Root分区的fsck
- 条件1:使能boot阶段的fsck
因为新版本的ubuntu默认是在initramfs阶段中进行Root分区的fsck,如果需要在磁盘文件系统的boot阶段进行fsck,首先需要打开使能配置:
# /lib/systemd/system/systemd-fsck-root.service
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=File System Check on Root Device
Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
Wants=systemd-fsckd.socket
Before=local-fs.target shutdown.target
After=systemd-fsckd.socket
ConditionPathIsReadWrite=!/
#ConditionPathExists=!/run/initramfs/fsck-root
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck
TimeoutSec=0
注释掉ConditionPathExists=!/run/initramfs/fsck-root
,这样才能使能。
- 条件2:cmdline中的Root分区为
ro
myc@myc-virtual-machine:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-166-generic root=UUID=bdc34999-c918-4a67-a92d-9bd7732e3820 ro quiet splash
需要为ro
,不能为rw
。
重启系统在sudo journal -b
的输出结果中查找fsck
关键字,可以在系统启动日志中可以看到fsck的情况:
11月 14 18:20:38 myc-virtual-machine systemd-fsck[404]: /dev/sda1: clean, 265631/1245184 files, 3177278/4980480 blocks
可以看到Root分区sda1
也启动了fsck。
2.3 ext文件系统的限制
和上一章一样,调用fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。
ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f
选项调用fsck;
条件1:需要满足ext文件系统的check间隔时间,执行e2fsck才会启动真正的扫描和修复。
默认间隔为0,意味着就算执行e2fsck也不会真正的check。
$ sudo tune2fs -l /dev/sdc1
...
Last checked: Tue Nov 12 15:35:53 2019
Check interval: 0 (<none>)
...
可以使用tune2fs -i
命令来设置扫描间隔时间:
tune2fs -i 10 /dev/sdc1 10天后检查
tune2fs -i 1d /dev/sdc1 1天后检查
tune2fs -i 3w /dev/sdc1 3周后检查
tune2fs -i 6m /dev/sdc1 半年后检查
tune2fs -i 0 /dev/sdc1 禁用时间检查
条件2:或者满足mount次数达到限制,执行e2fsck才会启动真正的扫描和修复。
默认Maximum mount count
为-1
,意味着就算执行e2fsck也不会真正的check。
$ sudo tune2fs -l /dev/sdc1
...
Mount count: 2
Maximum mount count: -1
...
可以使用tune2fs -c
命令来设置mount次数条件:
tune2fs -c 1 /dev/sdc1 设置每mount1次就进行一次check。
tune2fs -c -l /dev/sdc1 关闭强制检查挂载次数限制。
重启系统在sudo journal -b
的输出结果中查找fsck
关键字,可以在系统启动日志中可以看到fsck完整扫描的情况:
11月 14 18:26:49 myc-virtual-machine systemd-fsck[715]: /dev/sdc1 has been mounted 6 times without being checked, 强制检查.
11月 14 18:26:52 myc-virtual-machine systemd-fsck[715]: /dev/sdc1: 293466/6553600 files (0.1% non-contiguous), 5998689/26214144 blocks
2.4 强制fsck完整扫描
可以在cmdline中添加fsck.mode=force
选项使能所有的fsck操作进行强制完整扫描。
修改cmdline的方法:
1、首先在/etc/default/grub
中的GRUB_CMDLINE_LINUX_DEFAULT
后添加fsck.mode=force
:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash fsck.mode=force"
2、然后使用update-grub
命令更新配置;
重启系统在sudo journal -b
的输出结果中查找fsck
关键字,可以在系统启动日志中可以看到fsck完整扫描的情况:
11月 14 18:35:09 myc-virtual-machine systemd[1]: Starting File System Check on Root Device...
11月 14 18:35:10 myc-virtual-machine systemd-fsck[419]: /dev/sda1: 265631/1245184 files (0.2% non-contiguous), 3177338/4980480 blocks
11月 14 18:35:11 myc-virtual-machine systemd[1]: Starting File System Check on /dev/disk/by-uuid/d9f51ab3-0053-4156-a175-e9732018ee16...
11月 14 18:35:14 myc-virtual-machine systemd-fsck[786]: /dev/sdc1: 293466/6553600 files (0.1% non-contiguous), 5998689/26214144 blocks
11月 14 18:35:14 myc-virtual-machine systemd[1]: Started File System Check on /dev/disk/by-uuid/
11月 14 18:35:15 myc-virtual-machine systemd-fsck[785]: /dev/sdb1: 328353/2621440 files (0.1% non-contiguous), 3552241/10485504 blocks
2.5 fsck.repair
systemd-fsck 能够识别 下列cmdline:
fsck.mode=
检查模式。可设为 "auto", "force", "skip" 之一。 默认值 "auto" 表示 仅在文件系统检查工具认为确有必要的情况下, 才会实际执行真正的检查动作。"force" 表示无条件的执行检查动作。 "skip" 表示 无条件的跳过检查动作。
fsck.repair=
修复模式。可设为 "preen", "yes", "no" 之一。 默认值 "preen" 表示 自动修复文件系统检查过程中发现的可以安全修复的文件系统错误。 "yes" 表示对 fsck 询问的所有问题,一律回答"yes"。 "no" 表示对 fsck 询问的所有问题, 一律回答"no"。
3. Systemd 方式 (arm 32bit)
3.1 普通分区的fsck
除了Root分区以外的普通分区使能fsck非常简单,直接使能fstab中的pass
选项即可:
# cat /etc/fstab
# stock fstab - you probably want to override this with a machine specific one
/dev/root / auto defaults 1 1
proc /proc proc defaults 0 0
devpts /dev/pts devpts mode=0620,gid=5 0 0
usbdevfs /proc/bus/usb usbdevfs noauto 0 0
tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0
tmpfs /var/volatile tmpfs defaults,size=50M 0 0
tmpfs /media/ram tmpfs defaults,size=16M 0 0
/dev/mmcblk0p3 /mnt/app ext4 rw,sync 0 2
/dev/mmcblk0p4 /home/root ext4 rw,sync 0 2
最后的两个普通分区mmcblk0p3
和mmcblk0p4
的pass
选项被配置成了2
。
重启系统在sudo journal -b
的输出结果中查找Check
关键字,可以在系统启动日志中可以看到fsck的情况:
Oct 03 21:06:15 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p3...
Oct 03 21:06:15 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p4...
3.2 Root分区的fsck
需要把cmdline中的Root分区设置为ro
# cat /proc/cmdline
console=ttyO2,115200n8 root=PARTUUID=912ff182-02 ro rootfstype=ext4 rootwait
需要为ro
,不能为rw
。
需要修改uboot代码:
include/configs/ti_armv7_common.h:
"args_mmc=run finduuid;setenv bootargs console=${console} " \
"${optargs} " \
"root=PARTUUID=${uuid} ro " \
"rootfstype=${mmcrootfstype}\0" \
重启系统在sudo journal -b
的输出结果中查找Check
关键字,可以在系统启动日志中可以看到fsck的情况:
Oct 03 21:06:12 am57xx-evm systemd[1]: Starting File System Check on Root Device...
3.3 ext文件系统的限制
和上一章一样,调用fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。
ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f
选项调用fsck;
3.4 强制fsck完整扫描
cmdline中添加fsck.mode=force
选项使能所有的fsck操作进行强制完整扫描。
修改uboot代码:
include/configs/ti_armv7_common.h:
"args_mmc=run finduuid;setenv bootargs console=${console} " \
"${optargs} " \
"root=PARTUUID=${uuid} ro " \
"rootfstype=${mmcrootfstype} fsck.mode=force\0" \
查看cmdline:
重启系统在sudo journal -b
的输出结果中查找Check
关键字,可以在系统启动日志中可以看到fsck的情况:
Oct 03 21:06:12 am57xx-evm systemd[1]: Starting File System Check on Root Device...
Oct 03 21:06:14 am57xx-evm systemd-fsck[118]: rootfs: 62308/205504 files (0.1% non-contiguous), 573431/821248 blocks
Oct 03 21:06:17 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p3...
Oct 03 21:06:17 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p4...
本文来自博客园,作者:pwl999,转载请注明原文链接:https://www.cnblogs.com/pwl999/p/15535019.html