Support background fsck_ffs(8) on filesystems using journaled soft updates

An earlier addition of code to fsck_ffs(8) allowed it to support
snapshots when running with journalled soft updates. Further
functionality has now been added to fsck_ffs(8) to allow it to use
snapshots to run in background on live filesystems running with
journaled soft updates. This commit enables the use of this functionality.

Tested-by:    Peter Holm
Sponsored-by: The FreeBSD Foundation
MFC-after:    2 weeks
This commit is contained in:
Kirk McKusick 2023-08-01 13:16:11 -07:00
parent ff3d1a3f9d
commit 344b5bf825
2 changed files with 30 additions and 14 deletions

View File

@ -274,9 +274,16 @@ checkfilesys(char *filesys)
if (bkgrdcheck) {
if (sbreadfailed)
exit(3); /* Cannot read superblock */
/* Earlier background failed or journaled */
if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ))
exit(4);
if ((sblock.fs_flags & FS_NEEDSFSCK) == FS_NEEDSFSCK)
exit(4); /* Earlier background failed */
if ((sblock.fs_flags & FS_SUJ) == FS_SUJ) {
maxino = sblock.fs_ncg * sblock.fs_ipg;
maxfsblock = sblock.fs_size;
bufinit();
preen = 1;
if (suj_check(filesys) == 0)
exit(4); /* Journal good, run it now */
}
if ((sblock.fs_flags & FS_DOSOFTDEP) == 0)
exit(5); /* Not running soft updates */
size = MIBSIZE;
@ -350,7 +357,7 @@ checkfilesys(char *filesys)
/*
* Determine if we can and should do journal recovery.
*/
if ((sblock.fs_flags & FS_SUJ) == FS_SUJ) {
if (bkgrdflag == 0 && (sblock.fs_flags & FS_SUJ) == FS_SUJ) {
if ((sblock.fs_flags & FS_NEEDSFSCK) != FS_NEEDSFSCK &&
skipclean) {
sujrecovery = 1;
@ -619,10 +626,6 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
pwarn("FULL FSCK NEEDED, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if ((sblock.fs_flags & FS_SUJ) != 0) {
pwarn("JOURNALED FILESYSTEM, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if (skipclean && ckclean &&
(sblock.fs_flags & (FS_UNCLEAN|FS_NEEDSFSCK)) == 0) {
/*

View File

@ -2135,7 +2135,9 @@ suj_verifyino(union dinode *dp)
}
if (DIP(dp, di_modrev) != fs->fs_mtime) {
printf("Journal timestamp does not match fs mount time\n");
if (!bkgrdcheck || debug)
printf("Journal timestamp does not match "
"fs mount time\n");
return (-1);
}
@ -2436,7 +2438,9 @@ suj_check(const char *filesys)
sujino = idesc.id_parent;
irelse(&ip);
} else {
printf("Journal inode removed. Use tunefs to re-create.\n");
if (!bkgrdcheck || debug)
printf("Journal inode removed. "
"Use tunefs to re-create.\n");
sblock.fs_flags &= ~FS_SUJ;
sblock.fs_sujfree = 0;
irelse(&ip);
@ -2447,7 +2451,8 @@ suj_check(const char *filesys)
*/
ginode(sujino, &ip);
jip = ip.i_dp;
printf("** SU+J Recovering %s\n", filesys);
if (!bkgrdcheck || debug)
printf("** SU+J Recovering %s\n", filesys);
if (suj_verifyino(jip) != 0 || (!preen && !reply("USE JOURNAL"))) {
irelse(&ip);
return (-1);
@ -2456,15 +2461,23 @@ suj_check(const char *filesys)
* Build a list of journal blocks in jblocks before parsing the
* available journal blocks in with suj_read().
*/
printf("** Reading %jd byte journal from inode %ju.\n",
DIP(jip, di_size), (uintmax_t)sujino);
if (!bkgrdcheck || debug)
printf("** Reading %jd byte journal from inode %ju.\n",
DIP(jip, di_size), (uintmax_t)sujino);
suj_jblocks = jblocks_create();
blocks = ino_visit(jip, sujino, suj_add_block, 0);
if (blocks != numfrags(fs, DIP(jip, di_size))) {
printf("Sparse journal inode %ju.\n", (uintmax_t)sujino);
if (!bkgrdcheck || debug)
printf("Sparse journal inode %ju.\n",
(uintmax_t)sujino);
irelse(&ip);
return (-1);
}
/* If journal is valid then do journal check rather than background */
if (bkgrdcheck) {
irelse(&ip);
return (0);
}
irelse(&ip);
suj_read();
jblocks_destroy(suj_jblocks);