Improve fsck handling
r0l1 opened this issue · 0 comments
r0l1 commented
Quote from fsck man:
The exit code returned by fsck is the sum of the following conditions:
0 - No errors
1 - File system errors corrected
2 - System should be rebooted
4 - File system errors left uncorrected
8 - Operational error
16 - Usage or syntax error
32 - Fsck canceled by user request
128 - Shared library error
The exit code returned when multiple file systems are checked is the bit-wise OR of the exit codes for each file system that is checked.
Current code:
func fsck(dev string) error {
if _, err := os.Stat("/usr/bin/fsck"); !os.IsNotExist(err) {
cmd := exec.Command("/usr/bin/fsck", "-y", dev)
if verbosityLevel >= levelDebug {
cmd.Stdout = os.Stdout
}
if err := cmd.Run(); err != nil {
if err, ok := err.(*exec.ExitError); ok {
if err.ExitCode()&^0x1 != 0 {
// bit 1 means errors were corrected successfully which is good
return unwrapExitError(err)
}
return nil
}
return fmt.Errorf("fsck for %s: unknown error %v", dev, err)
}
}
return nil
}
My personal improved code
- Use fsck.ext4, because otherwise the incompatible busybox fsck will be used.
- Bitwise checking should not be required, because we do not check multiple devices at once.
- Ensure to check for exit code 2 and reboot
- Hint: I enforce a fsck operation and removed the file exists check.
// TODO: check which filesystem type it is and select the correct fsck utility.
func fsck(dev string) (err error) {
output, err := exec.Command("/usr/bin/fsck.ext4", "-y", dev).CombinedOutput()
if err == nil {
debug("fsck output: %s", string(output))
return
}
if err, ok := err.(*exec.ExitError); ok {
switch err.ExitCode() {
case 0:
return nil
case 1: // File system errors corrected
severe("fsck corrected filesystem errors: %s", string(output))
return nil
case 2: // File system errors corrected, system should be rebooted
severe("fsck corrected filesystem errors: %s", string(output))
syscall.Sync()
fmt.Println("Reboot required")
time.Sleep(3 * time.Second)
return syscall.Reboot(syscall.LINUX_REBOOT_CMD_RESTART)
}
}
return fmt.Errorf("fsck for %s: unknown error %v\n%s", dev, err, string(output))
}