Have fsck_ffs(8) properly correct superblock check-hash failures.

Part of the problem was that fsck_ffs would read the superblock
multiple times complaining and repairing the superblock check hash
each time and then at the end failing to write out the superblock
with the corrected check hash. This fix reads the superblock just
once and if the check hash is corrected ensures that the fixed
superblock gets written.

Tested by:    Peter Holm
PR:           245916
MFC after:    1 week
Sponsored by: Netflix
This commit is contained in:
Kirk McKusick 2022-02-04 11:46:36 -08:00
parent 930a7c2ac6
commit c0bfa109b9
5 changed files with 261 additions and 247 deletions

View file

@ -356,6 +356,7 @@ extern char preen; /* just fix normal inconsistencies */
extern char rerun; /* rerun fsck. Only used in non-preen mode */
extern int returntosingle; /* 1 => return to single user mode on exit */
extern char resolved; /* cleared if unresolved changes => not clean */
extern int sbhashfailed; /* when reading superblock check hash failed */
extern char havesb; /* superblock has been read */
extern char skipclean; /* skip clean file systems if preening */
extern int fsmodified; /* 1 => write done to file system */

View file

@ -250,6 +250,7 @@ cglookup(int cg)
if (cgp == NULL) {
if (sujrecovery)
errx(EEXIT,"Ran out of memory during journal recovery");
flush(fswritefd, &cgblk);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
return (&cgblk);
}
@ -564,7 +565,7 @@ ckfini(int markclean)
cmd.size = markclean ? -1 : 1;
if (sysctlbyname("vfs.ffs.setflags", 0, 0,
&cmd, sizeof cmd) == -1)
rwerror("SET FILE SYSTEM FLAGS", FS_UNCLEAN);
pwarn("CANNOT SET FILE SYSTEM DIRTY FLAG\n");
if (!preen) {
printf("\n***** FILE SYSTEM MARKED %s *****\n",
markclean ? "CLEAN" : "DIRTY");
@ -575,6 +576,7 @@ ckfini(int markclean)
printf("\n***** FILE SYSTEM STILL DIRTY *****\n");
rerun = 1;
}
bkgrdflag = 0;
}
if (debug && cachelookups > 0)
printf("cache with %d buffers missed %d of %d (%d%%)\n",

View file

@ -96,6 +96,7 @@ char preen; /* just fix normal inconsistencies */
char rerun; /* rerun fsck. Only used in non-preen mode */
int returntosingle; /* 1 => return to single user mode on exit */
char resolved; /* cleared if unresolved changes => not clean */
int sbhashfailed; /* when reading superblock check hash failed */
char havesb; /* superblock has been read */
char skipclean; /* skip clean file systems if preening */
int fsmodified; /* 1 => write done to file system */
@ -155,8 +156,9 @@ fsckinit(void)
resolved = 0;
havesb = 0;
fsmodified = 0;
fsreadfd = 0;
fswritefd = 0;
sbhashfailed = 0;
fsreadfd = -1;
fswritefd = -1;
maxfsblock = 0;
maxino = 0;
lfdir = 0;

View file

@ -75,6 +75,8 @@ static int restarts;
static void usage(void) __dead2;
static intmax_t argtoimax(int flag, const char *req, const char *str, int base);
static int checkfilesys(char *filesys);
static int setup_bkgrdchk(struct statfs *mntp, int sbrdfailed, char **filesys);
static int openfilesys(char *dev);
static int chkdoreload(struct statfs *mntp);
static struct statfs *getmntpt(const char *);
@ -181,6 +183,11 @@ main(int argc, char *argv[])
if (!argc)
usage();
if (bkgrdflag && cvtlevel > 0) {
pfatal("CANNOT CONVERT A SNAPSHOT\n");
exit(EEXIT);
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void)signal(SIGINT, catch);
if (ckclean)
@ -237,18 +244,10 @@ checkfilesys(char *filesys)
ufs2_daddr_t n_ffree, n_bfree;
struct dups *dp;
struct statfs *mntp;
struct stat snapdir;
struct group *grp;
struct iovec *iov;
char errmsg[255];
int ofsmodified;
int iovlen;
intmax_t blks, files;
size_t size;
int sbreadfailed, ofsmodified;
iov = NULL;
iovlen = 0;
errmsg[0] = '\0';
fsutilinit();
fsckinit();
@ -272,10 +271,12 @@ checkfilesys(char *filesys)
* exit status will cause a foreground check to be run.
*/
sblock_init();
sbreadfailed = 0;
if (openfilesys(filesys) == 0 || readsb(0) == 0)
sbreadfailed = 1;
if (bkgrdcheck) {
if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
if (sbreadfailed)
exit(3); /* Cannot read superblock */
close(fsreadfd);
/* Earlier background failed or journaled */
if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ))
exit(4);
@ -293,7 +294,7 @@ checkfilesys(char *filesys)
/*
* If file system is gjournaled, check it here.
*/
if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
if (sbreadfailed)
exit(3); /* Cannot read superblock */
if (bkgrdflag == 0 &&
(nflag || (fswritefd = open(filesys, O_WRONLY)) < 0)) {
@ -307,107 +308,30 @@ checkfilesys(char *filesys)
pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
exit(0);
}
if ((sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
if ((sblock.fs_flags &
(FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
bufinit();
gjournal_check(filesys);
if (chkdoreload(mntp) == 0)
exit(0);
exit(4);
} else {
pfatal("UNEXPECTED INCONSISTENCY, CANNOT RUN "
"FAST FSCK\n");
pfatal("FULL FSCK NEEDED, CANNOT RUN FAST "
"FSCK\n");
}
}
close(fsreadfd);
close(fswritefd);
fswritefd = -1;
}
/*
* If we are to do a background check:
* Get the mount point information of the file system
* create snapshot file
* return created snapshot file
* if not found, clear bkgrdflag and proceed with normal fsck
*/
if (bkgrdflag) {
/* Get the mount point information of the file system */
if (mntp == NULL) {
bkgrdflag = 0;
pfatal("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n");
} else if ((mntp->f_flags & MNT_SOFTDEP) == 0) {
bkgrdflag = 0;
pfatal("NOT USING SOFT UPDATES, CANNOT RUN IN "
"BACKGROUND\n");
} else if ((mntp->f_flags & MNT_RDONLY) != 0) {
bkgrdflag = 0;
pfatal("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n");
} else if ((fsreadfd = open(filesys, O_RDONLY)) >= 0) {
if (readsb(0) != 0) {
if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ)) {
bkgrdflag = 0;
pfatal(
"UNEXPECTED INCONSISTENCY, CANNOT RUN IN BACKGROUND\n");
}
if ((sblock.fs_flags & FS_UNCLEAN) == 0 &&
skipclean && ckclean) {
/*
* file system is clean;
* skip snapshot and report it clean
*/
pwarn(
"FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
goto clean;
}
}
close(fsreadfd);
}
if (bkgrdflag) {
snprintf(snapname, sizeof snapname, "%s/.snap",
mntp->f_mntonname);
if (stat(snapname, &snapdir) < 0) {
if (errno != ENOENT) {
bkgrdflag = 0;
pfatal(
"CANNOT FIND SNAPSHOT DIRECTORY %s: %s, CANNOT RUN IN BACKGROUND\n",
snapname, strerror(errno));
} else if ((grp = getgrnam("operator")) == NULL ||
mkdir(snapname, 0770) < 0 ||
chown(snapname, -1, grp->gr_gid) < 0 ||
chmod(snapname, 0770) < 0) {
bkgrdflag = 0;
pfatal(
"CANNOT CREATE SNAPSHOT DIRECTORY %s: %s, CANNOT RUN IN BACKGROUND\n",
snapname, strerror(errno));
}
} else if (!S_ISDIR(snapdir.st_mode)) {
bkgrdflag = 0;
pfatal(
"%s IS NOT A DIRECTORY, CANNOT RUN IN BACKGROUND\n",
snapname);
}
}
if (bkgrdflag) {
snprintf(snapname, sizeof snapname,
"%s/.snap/fsck_snapshot", mntp->f_mntonname);
build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
build_iovec(&iov, &iovlen, "from", snapname,
(size_t)-1);
build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname,
(size_t)-1);
build_iovec(&iov, &iovlen, "errmsg", errmsg,
sizeof(errmsg));
build_iovec(&iov, &iovlen, "update", NULL, 0);
build_iovec(&iov, &iovlen, "snapshot", NULL, 0);
while (nmount(iov, iovlen, mntp->f_flags) < 0) {
if (errno == EEXIST && unlink(snapname) == 0)
continue;
bkgrdflag = 0;
pfatal("CANNOT CREATE SNAPSHOT %s: %s %s\n",
snapname, strerror(errno), errmsg);
break;
}
if (bkgrdflag != 0)
filesys = snapname;
switch (setup_bkgrdchk(mntp, sbreadfailed, &filesys)) {
case -1: /* filesystem clean */
goto clean;
case 0: /* cannot do background, give up */
exit(EEXIT);
case 1: /* doing background check, preen rules apply */
preen = 1;
break;
}
}
@ -648,6 +572,187 @@ checkfilesys(char *filesys)
return (rerun ? ERERUN : 0);
}
/*
* If we are to do a background check:
* Get the mount point information of the file system
* If already clean, return -1
* Check that kernel supports background fsck
* Find or create the snapshot directory
* Create the snapshot file
* Open snapshot
* If anything fails print reason and return 0 which exits
*/
static int
setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
{
struct stat snapdir;
struct group *grp;
struct iovec *iov;
char errmsg[255];
int iovlen;
long size;
/* Get the mount point information of the file system */
if (mntp == NULL) {
pwarn("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if ((mntp->f_flags & MNT_RDONLY) != 0) {
pwarn("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if ((mntp->f_flags & MNT_SOFTDEP) == 0) {
pwarn("NOT USING SOFT UPDATES, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if (sbreadfailed) {
pwarn("SUPERBLOCK READ FAILED, CANNOT RUN IN BACKGROUND\n");
return (0);
}
if ((sblock.fs_flags & FS_NEEDSFSCK) != 0) {
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) {
/*
* file system is clean;
* skip snapshot and report it clean
*/
pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
return (-1);
}
/* Check that kernel supports background fsck */
size = MIBSIZE;
if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0||
sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0||
sysctlnametomib("vfs.ffs.setsize", setsize, &size) < 0 ||
sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0||
sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 ||
sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) {
pwarn("KERNEL LACKS BACKGROUND FSCK SUPPORT\n");
return (0);
}
/*
* When kernel lacks runtime bgfsck superblock summary
* adjustment functionality, it does not mean we can not
* continue, as old kernels will recompute the summary at
* mount time. However, it will be an unexpected softupdates
* inconsistency if it turns out that the summary is still
* incorrect. Set a flag so subsequent operation can know this.
*/
bkgrdsumadj = 1;
if (sysctlnametomib("vfs.ffs.adjndir", adjndir, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnbfree", adjnbfree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnifree", adjnifree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnffree", adjnffree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnumclusters", adjnumclusters,
&size) < 0) {
bkgrdsumadj = 0;
pwarn("KERNEL LACKS RUNTIME SUPERBLOCK SUMMARY ADJUSTMENT "
"SUPPORT\n");
}
/* Find or create the snapshot directory */
snprintf(snapname, sizeof snapname, "%s/.snap",
mntp->f_mntonname);
if (stat(snapname, &snapdir) < 0) {
if (errno != ENOENT) {
pwarn("CANNOT FIND SNAPSHOT DIRECTORY %s: %s, CANNOT "
"RUN IN BACKGROUND\n", snapname, strerror(errno));
return (0);
}
if ((grp = getgrnam("operator")) == NULL ||
mkdir(snapname, 0770) < 0 ||
chown(snapname, -1, grp->gr_gid) < 0 ||
chmod(snapname, 0770) < 0) {
pwarn("CANNOT CREATE SNAPSHOT DIRECTORY %s: %s, "
"CANNOT RUN IN BACKGROUND\n", snapname,
strerror(errno));
return (0);
}
} else if (!S_ISDIR(snapdir.st_mode)) {
pwarn("%s IS NOT A DIRECTORY, CANNOT RUN IN BACKGROUND\n",
snapname);
return (0);
}
/* Create the snapshot file */
iov = NULL;
iovlen = 0;
errmsg[0] = '\0';
snprintf(snapname, sizeof snapname, "%s/.snap/fsck_snapshot",
mntp->f_mntonname);
build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
build_iovec(&iov, &iovlen, "from", snapname, (size_t)-1);
build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1);
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
build_iovec(&iov, &iovlen, "update", NULL, 0);
build_iovec(&iov, &iovlen, "snapshot", NULL, 0);
/* Create snapshot, removing old snapshot it it exists */
while (nmount(iov, iovlen, mntp->f_flags) < 0) {
if (errno == EEXIST && unlink(snapname) == 0)
continue;
pwarn("CANNOT CREATE SNAPSHOT %s: %s %s\n", snapname,
strerror(errno), errmsg);
return (0);
}
/* Open snapshot */
if (openfilesys(snapname) == 0) {
unlink(snapname);
pwarn("CANNOT OPEN SNAPSHOT %s: %s, CANNOT RUN IN "
"BACKGROUND\n", snapname, strerror(errno));
return (0);
}
free(sblock.fs_csp);
free(sblock.fs_si);
havesb = 0;
*filesys = snapname;
cmd.version = FFS_CMD_VERSION;
cmd.handle = fsreadfd;
return (1);
}
/*
* Open a device or file to be checked by fsck.
*/
static int
openfilesys(char *dev)
{
struct stat statb;
int saved_fsreadfd;
if (stat(dev, &statb) < 0) {
pfatal("CANNOT STAT %s: %s\n", dev, strerror(errno));
return (0);
}
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) {
pfatal("BACKGROUND FSCK LACKS A SNAPSHOT\n");
exit(EEXIT);
}
if (bkgrdflag != 0) {
cursnapshot = statb.st_ino;
} else {
pfatal("%s IS NOT A DISK DEVICE\n", dev);
if (reply("CONTINUE") == 0)
return (0);
}
}
saved_fsreadfd = fsreadfd;
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
fsreadfd = saved_fsreadfd;
pfatal("CANNOT OPEN %s: %s\n", dev, strerror(errno));
return (0);
}
if (saved_fsreadfd != -1)
close(saved_fsreadfd);
return (1);
}
static int
chkdoreload(struct statfs *mntp)
{

View file

@ -76,98 +76,39 @@ static int chkrecovery(int devfd);
int
setup(char *dev)
{
long cg, asked, i, j;
long bmapsize;
struct stat statb;
long cg, bmapsize;
struct fs proto;
size_t size;
havesb = 0;
fswritefd = -1;
cursnapshot = 0;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
if (bkgrdflag) {
unlink(snapname);
bkgrdflag = 0;
}
/*
* We are expected to have an open file descriptor
*/
if (fsreadfd < 0)
return (0);
}
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) {
unlink(snapname);
printf("background fsck lacks a snapshot\n");
exit(EEXIT);
/*
* If we do not yet have a superblock, read it in looking
* for alternates if necessary.
*/
if (havesb == 0 && readsb(1) == 0) {
skipclean = 0;
if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
return(0);
if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
return (0);
for (cg = 0; cg < proto.fs_ncg; cg++) {
bflag = fsbtodb(&proto, cgsblock(&proto, cg));
if (readsb(0) != 0)
break;
}
if ((statb.st_flags & SF_SNAPSHOT) != 0 && cvtlevel == 0) {
cursnapshot = statb.st_ino;
} else {
if (cvtlevel == 0 ||
(statb.st_flags & SF_SNAPSHOT) == 0) {
if (preen && bkgrdflag) {
unlink(snapname);
bkgrdflag = 0;
}
pfatal("%s is not a disk device", dev);
if (reply("CONTINUE") == 0) {
if (bkgrdflag) {
unlink(snapname);
bkgrdflag = 0;
}
return (0);
}
} else {
if (bkgrdflag) {
unlink(snapname);
bkgrdflag = 0;
}
pfatal("cannot convert a snapshot");
exit(EEXIT);
}
if (cg >= proto.fs_ncg) {
printf("SEARCH FOR ALTERNATE SUPER-BLOCK FAILED. "
"YOU MUST USE THE\n-b OPTION TO FSCK TO SPECIFY "
"THE LOCATION OF AN ALTERNATE\nSUPER-BLOCK TO "
"SUPPLY NEEDED INFORMATION; SEE fsck_ffs(8).\n");
bflag = 0;
return(0);
}
}
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
if (bkgrdflag) {
unlink(snapname);
bkgrdflag = 0;
}
printf("Can't open %s: %s\n", dev, strerror(errno));
return (0);
}
if (bkgrdflag) {
unlink(snapname);
size = MIBSIZE;
if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0||
sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0||
sysctlnametomib("vfs.ffs.setsize", setsize, &size) < 0 ||
sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0||
sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 ||
sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) {
pfatal("kernel lacks background fsck support\n");
exit(EEXIT);
}
/*
* When kernel is lack of runtime bgfsck superblock summary
* adjustment functionality, it does not mean we can not
* continue, as old kernels will recompute the summary at
* mount time. However, it will be an unexpected softupdates
* inconsistency if it turns out that the summary is still
* incorrect. Set a flag so subsequent operation can know
* this.
*/
bkgrdsumadj = 1;
if (sysctlnametomib("vfs.ffs.adjndir", adjndir, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnbfree", adjnbfree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnifree", adjnifree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnffree", adjnffree, &size) < 0 ||
sysctlnametomib("vfs.ffs.adjnumclusters", adjnumclusters, &size) < 0) {
bkgrdsumadj = 0;
pwarn("kernel lacks runtime superblock summary adjustment support");
}
cmd.version = FFS_CMD_VERSION;
cmd.handle = fsreadfd;
fswritefd = -1;
pwarn("USING ALTERNATE SUPERBLOCK AT %jd\n", bflag);
bflag = 0;
}
if (preen == 0)
printf("** %s", dev);
@ -180,33 +121,16 @@ setup(char *dev)
}
if (preen == 0)
printf("\n");
/*
* Read in the superblock, looking for alternates if necessary
*/
if (readsb(1) == 0) {
skipclean = 0;
if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
return(0);
if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
return (0);
for (cg = 0; cg < proto.fs_ncg; cg++) {
bflag = fsbtodb(&proto, cgsblock(&proto, cg));
if (readsb(0) != 0)
break;
if (sbhashfailed != 0) {
pwarn("SUPERBLOCK CHECK HASH FAILED");
if (fswritefd == -1)
pwarn("OPENED READONLY SO CANNOT CORRECT CHECK HASH\n");
else if (preen || reply("CORRECT CHECK HASH") != 0) {
if (preen)
printf(" (CORRECTED)\n");
sblock.fs_clean = 0;
sbdirty();
}
if (cg >= proto.fs_ncg) {
printf("%s %s\n%s %s\n%s %s\n",
"SEARCH FOR ALTERNATE SUPER-BLOCK",
"FAILED. YOU MUST USE THE",
"-b OPTION TO FSCK TO SPECIFY THE",
"LOCATION OF AN ALTERNATE",
"SUPER-BLOCK TO SUPPLY NEEDED",
"INFORMATION; SEE fsck_ffs(8).");
bflag = 0;
return(0);
}
pwarn("USING ALTERNATE SUPERBLOCK AT %jd\n", bflag);
bflag = 0;
}
if (skipclean && ckclean && sblock.fs_clean) {
pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
@ -247,30 +171,6 @@ setup(char *dev)
fswritefd != -1 && chkrecovery(fsreadfd) == 0 &&
reply("SAVE DATA TO FIND ALTERNATE SUPERBLOCKS") != 0)
saverecovery(fsreadfd, fswritefd);
/*
* read in the summary info.
*/
asked = 0;
sblock.fs_csp = Calloc(1, sblock.fs_cssize);
if (sblock.fs_csp == NULL) {
printf("cannot alloc %u bytes for cg summary info\n",
(unsigned)sblock.fs_cssize);
goto badsb;
}
for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
size = MIN(sblock.fs_cssize - i, sblock.fs_bsize);
readcnt[sblk.b_type]++;
if (blread(fsreadfd, (char *)sblock.fs_csp + i,
fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
size) != 0 && !asked) {
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
asked++;
}
}
/*
* allocate and initialize the necessary maps
*/
@ -320,13 +220,17 @@ readsb(int listerr)
int bad, ret;
struct fs *fs;
super = bflag ? bflag * dev_bsize : STDSB_NOHASHFAIL;
super = bflag ? bflag * dev_bsize :
sbhashfailed ? STDSB_NOHASHFAIL_NOMSG : STDSB_NOMSG;
readcnt[sblk.b_type]++;
if ((ret = sbget(fsreadfd, &fs, super)) != 0) {
while ((ret = sbget(fsreadfd, &fs, super)) != 0) {
switch (ret) {
case EINVAL:
/* Superblock check-hash failed */
return (0);
case EINTEGRITY:
if (bflag || super == STDSB_NOHASHFAIL_NOMSG)
return (0);
super = STDSB_NOHASHFAIL_NOMSG;
sbhashfailed = 1;
continue;
case ENOENT:
if (bflag)
printf("%jd is not a file system "