Add a flags parameter to the ffs_sbget() function that reads UFS superblocks.

Rather than trying to shoehorn flags into the requested superblock
address, create a separate flags parameter to the ffs_sbget()
function in sys/ufs/ffs/ffs_subr.c. The ffs_sbget() function is
used both in the kernel and in user-level utilities through export
to the sbget() function in the libufs(3) library (see sbget(3)
for details). The kernel uses ffs_sbget() when mounting UFS
filesystems, in the glabel(8) and gjournal(8) GEOM utilities,
and in the standalone library used when booting the system
from a UFS root filesystem.

The ffs_sbget() function reads the superblock located at the byte
offset specified by its sblockloc parameter. The value UFS_STDSB
may be specified for sblockloc to request that the standard
location for the superblock be read.

The two existing options are now flags:

UFS_NOHASHFAIL will note if the check hash is wrong but will still
   return the superblock. This is used by the bootstrap code to
   give the system a chance to come up so that fsck can be run to
   correct the problem.

UFS_NOMSG indicates that superblock inconsistency error messages
   should not be printed. It is used by programs like fsck that
   want to print their own error message and programs like glabel(8)
   that just want to know if a UFS filesystem exists on a partition.

One additional flag is added:

UFS_NOCSUM causes only the superblock itself to be returned, but does
   not read in any auxiliary data structures like the cylinder group
   summary information. It is used by clients like glabel(8) that
   just want to check for possible filesystem types. Using UFS_NOCSUM
   skips the superblock checks for csum data which allows superblocks
   that have corrupted csum data to be read and used.

The validate_sblock() function checks that the superblock has not
been corrupted in a way that can crash or hang the system. Unless
the UFS_NOMSG flag is specified, it will print out any errors that
it finds. Prior to this commit, validate_sblock() returned as soon
as it found an inconsistency so would print at most one message.
It now does all its checks so when UFS_NOMSG has not been specified
will print out everything that it finds inconsistent.

Sponsored by: The FreeBSD Foundation
This commit is contained in:
Kirk McKusick 2022-07-30 22:44:01 -07:00
parent dc9e68ad01
commit b21582ee03
19 changed files with 159 additions and 97 deletions

View File

@ -65,7 +65,8 @@ struct uufsd {
int d_ccg; /* current cylinder group */
int d_lcg; /* last cylinder group (in d_cg) */
const char *d_error; /* human readable disk error */
off_t d_sblockloc; /* where to look for the superblock */
off_t d_sblockloc; /* where to look for the superblock */
int d_lookupflags; /* flags to superblock lookup */
int d_mine; /* internal flags */
#define d_fs d_sbunion.d_fs
#define d_sb d_sbunion.d_sb
@ -111,7 +112,7 @@ void ffs_fragacct(struct fs *, int, int32_t [], int);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_sbget(void *, struct fs **, off_t, char *,
int ffs_sbget(void *, struct fs **, off_t, int, char *,
int (*)(void *, off_t, void **, int));
int ffs_sbput(void *, struct fs *, off_t,
int (*)(void *, off_t, void *, int));
@ -150,7 +151,7 @@ int putinode(struct uufsd *);
int sbread(struct uufsd *);
int sbwrite(struct uufsd *, int);
/* low level superblock read/write functions */
int sbget(int, struct fs **, off_t);
int sbget(int, struct fs **, off_t, int);
int sbput(int, struct fs *, int);
/*

View File

@ -53,6 +53,15 @@ static int handle_disk_read(struct uufsd *, struct fs *, int);
/*
* Read the standard superblock.
*
* The following option flags can be or'ed into disk->d_lookupflags:
*
* UFS_NOMSG indicates that superblock inconsistency error messages
* should not be printed.
*
* UFS_NOCSUM causes only the superblock itself to be returned, but does
* not read in any auxillary data structures like the cylinder group
* summary information.
*/
int
sbread(struct uufsd *disk)
@ -60,7 +69,7 @@ sbread(struct uufsd *disk)
struct fs *fs;
int error;
error = sbget(disk->d_fd, &fs, disk->d_sblockloc);
error = sbget(disk->d_fd, &fs, disk->d_sblockloc, disk->d_lookupflags);
return (handle_disk_read(disk, fs, error));
}
@ -149,14 +158,24 @@ static int use_pread(void *devfd, off_t loc, void **bufp, int size);
static int use_pwrite(void *devfd, off_t loc, void *buf, int size);
/*
* The following two functions read a superblock. Their flags
* parameter are made up of the following or'ed together options:
*
* UFS_NOMSG indicates that superblock inconsistency error messages
* should not be printed.
*
* UFS_NOCSUM causes only the superblock itself to be returned, but does
* not read in any auxillary data structures like the cylinder group
* summary information.
*
* Read a superblock from the devfd device allocating memory returned
* in fsp. Also read the superblock summary information.
* in fsp.
*/
int
sbget(int devfd, struct fs **fsp, off_t sblockloc)
sbget(int devfd, struct fs **fsp, off_t sblockloc, int flags)
{
return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread));
return (ffs_sbget(&devfd, fsp, sblockloc, flags, "user", use_pread));
}
/*
@ -196,8 +215,10 @@ sbput(int devfd, struct fs *fs, int numaltwrite)
if (numaltwrite == 0)
return (0);
savedactualloc = fs->fs_sblockactualloc;
savedcsp = fs->fs_csp;
fs->fs_csp = NULL;
if (fs->fs_si != NULL) {
savedcsp = fs->fs_csp;
fs->fs_csp = NULL;
}
for (i = 0; i < numaltwrite; i++) {
fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i)));
if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc,
@ -208,7 +229,8 @@ sbput(int devfd, struct fs *fs, int numaltwrite)
}
}
fs->fs_sblockactualloc = savedactualloc;
fs->fs_csp = savedcsp;
if (fs->fs_si != NULL)
fs->fs_csp = savedcsp;
return (0);
}

View File

@ -27,7 +27,7 @@
.In ufs/ffs/fs.h
.In libufs.h
.Ft int
.Fn sbget "int devfd" "struct fs **fsp" "off_t sblockloc"
.Fn sbget "int devfd" "struct fs **fsp" "off_t sblockloc" "int flags"
.Ft int
.Fn sbput "int devfd" "struct fs *fs" "int numaltwrite"
.Ft int
@ -60,7 +60,27 @@ file descriptor that references the filesystem disk,
reads the superblock located at the byte offset specified by
.Va sblockloc
into the allocated buffer.
If successful, it returns a pointer to the buffer containing the superblock in
The value
.Cm UFS_STDSB
may be specified for
.Va sblockloc
to request that the standard location for the superblock be read.
Flags are specified by
.Em or Ns 'ing
the following values:
.Pp
.Bl -tag -width UFS_NOHASHFAIL
.It Cm UFS_NOHASHFAIL
Will note if the check hash is wrong but will still return the superblock.
.It Cm UFS_NOMSG
Indicates that superblock inconsistency error messages should not be printed.
.It Cm UFS_NOCSUM
Causes only the superblock itself to be returned, but does not read in any auxiliary data structures like the cylinder group summary information.
.El
.Pp
If successful,
.Fn sbget
returns a pointer to the buffer containing the superblock in
.Va fsp .
The
.Fn sbget

View File

@ -168,7 +168,8 @@ again: if ((ret = stat(name, &st)) < 0) {
disk->d_ufs = 0;
disk->d_error = NULL;
disk->d_si = NULL;
disk->d_sblockloc = STDSB;
disk->d_sblockloc = UFS_STDSB;
disk->d_lookupflags = 0;
if (oname != name) {
name = strdup(name);

View File

@ -457,7 +457,7 @@ main(int argc, char *argv[])
msgtail("to %s\n", tape);
sync();
if ((ret = sbget(diskfd, &sblock, STDSB)) != 0) {
if ((ret = sbget(diskfd, &sblock, UFS_STDSB, UFS_NOCSUM)) != 0) {
switch (ret) {
case ENOENT:
warn("Cannot find file system superblock");

View File

@ -135,7 +135,7 @@ main(int argc, char *argv[])
eval |= 1;
continue;
}
disk.d_sblockloc = STDSB_NOHASHFAIL;
disk.d_lookupflags |= UFS_NOHASHFAIL;
if (sbread(&disk) == -1) {
ufserr(name);
eval |= 1;
@ -314,9 +314,6 @@ dumpfs(const char *name, int dosb)
afs.fs_volname, (uintmax_t)afs.fs_swuid,
(uintmax_t)afs.fs_providersize);
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
afs.fs_csp = calloc(1, afs.fs_cssize);
if (bread(&disk, fsbtodb(&afs, afs.fs_csaddr), afs.fs_csp, afs.fs_cssize) == -1)
goto err;
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
if (i && i % 4 == 0)

View File

@ -252,18 +252,20 @@ int
readsb(int listerr)
{
off_t super;
int bad, ret;
int bad, ret, flags;
struct fs *fs;
super = bflag ? bflag * dev_bsize :
sbhashfailed ? STDSB_NOHASHFAIL_NOMSG : STDSB_NOMSG;
super = bflag ? bflag * dev_bsize : UFS_STDSB;
flags = sbhashfailed ? UFS_NOHASHFAIL | UFS_NOMSG : UFS_NOMSG;
readcnt[sblk.b_type]++;
while ((ret = sbget(fsreadfd, &fs, super)) != 0) {
while ((ret = sbget(fsreadfd, &fs, super, flags)) != 0) {
switch (ret) {
case EINTEGRITY:
if (bflag || super == STDSB_NOHASHFAIL_NOMSG)
if (bflag || (super == UFS_STDSB &&
flags == (UFS_NOHASHFAIL | UFS_NOMSG)))
return (0);
super = STDSB_NOHASHFAIL_NOMSG;
super = UFS_STDSB;
flags = UFS_NOHASHFAIL | UFS_NOMSG;
sbhashfailed = 1;
continue;
case ENOENT:

View File

@ -112,7 +112,7 @@ fsirand(char *device)
struct fs *sblock;
ino_t inumber;
ufs2_daddr_t dblk;
int devfd, n, cg, ret;
int devfd, n, cg;
u_int32_t bsize = DEV_BSIZE;
if ((devfd = open(device, printonly ? O_RDONLY : O_RDWR)) < 0) {
@ -124,10 +124,10 @@ fsirand(char *device)
dp2 = NULL;
/* Read in master superblock */
if ((ret = sbget(devfd, &sblock, STDSB)) != 0) {
switch (ret) {
if ((errno = sbget(devfd, &sblock, UFS_STDSB, UFS_NOCSUM)) != 0) {
switch (errno) {
case ENOENT:
warn("Cannot find file system superblock");
warnx("Cannot find file system superblock");
return (1);
default:
warn("Unable to read file system superblock");

View File

@ -1455,7 +1455,7 @@ main(int argc, char **argv)
/*
* Read the current superblock, and take a backup.
*/
if ((ret = sbget(fsi, &fs, STDSB)) != 0) {
if ((ret = sbget(fsi, &fs, UFS_STDSB, 0)) != 0) {
switch (ret) {
case ENOENT:
errx(1, "superblock not recognized");

View File

@ -321,7 +321,7 @@ chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg)
}
}
sync();
if ((ret = sbget(fi, &fs, STDSB)) != 0) {
if ((ret = sbget(fi, &fs, UFS_STDSB, UFS_NOCSUM)) != 0) {
switch (ret) {
case ENOENT:
warn("Cannot find file system superblock");

View File

@ -152,7 +152,7 @@ static int search_directory(char *, struct open_file *, ino_t *);
static int ufs_use_sa_read(void *, off_t, void **, int);
/* from ffs_subr.c */
int ffs_sbget(void *, struct fs **, off_t, char *,
int ffs_sbget(void *, struct fs **, off_t, int, char *,
int (*)(void *, off_t, void **, int));
/*
@ -530,7 +530,7 @@ ufs_open(const char *upath, struct open_file *f)
if (mnt == NULL) {
/* read super block */
twiddle(1);
if ((rc = ffs_sbget(f, &fs, STDSB_NOHASHFAIL, "stand",
if ((rc = ffs_sbget(f, &fs, UFS_STDSB, UFS_NOHASHFAIL, "stand",
ufs_use_sa_read)) != 0) {
goto out;
}

View File

@ -73,7 +73,8 @@ g_journal_ufs_dirty(struct g_consumer *cp)
fs = NULL;
if (SBLOCKSIZE % cp->provider->sectorsize != 0 ||
ffs_sbget(cp, &fs, STDSB, M_GEOM, g_use_g_read_data) != 0) {
ffs_sbget(cp, &fs, UFS_STDSB, UFS_NOCSUM, M_GEOM, g_use_g_read_data)
!= 0) {
GJ_DEBUG(0, "Cannot find superblock to mark file system %s "
"as dirty.", cp->provider->name);
KASSERT(fs == NULL,

View File

@ -139,8 +139,9 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh
label[0] = '\0';
fs = NULL;
if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs,
STDSB_NOHASHFAIL_NOMSG, M_GEOM, g_use_g_read_data) != 0) {
if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs, UFS_STDSB,
UFS_NOHASHFAIL | UFS_NOCSUM | UFS_NOMSG, M_GEOM, g_use_g_read_data)
!= 0) {
KASSERT(fs == NULL,
("g_label_ufs_taste_common: non-NULL fs %p\n", fs));
return;
@ -172,8 +173,6 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh
break;
}
out:
g_free(fs->fs_csp);
g_free(fs->fs_si);
g_free(fs);
}

View File

@ -90,7 +90,7 @@ int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
ufs2_daddr_t, int, int, int, struct ucred *, struct buf **);
int ffs_reload(struct mount *, int);
int ffs_sbget(void *, struct fs **, off_t, struct malloc_type *,
int ffs_sbget(void *, struct fs **, off_t, int, struct malloc_type *,
int (*)(void *, off_t, void **, int));
int ffs_sbput(void *, struct fs *, off_t, int (*)(void *, off_t, void *,
int));

View File

@ -125,7 +125,7 @@ ffs_update_dinode_ckhash(struct fs *fs, struct ufs2_dinode *dip)
* the superblock and its associated data.
*/
static off_t sblock_try[] = SBLOCKSEARCH;
static int readsuper(void *, struct fs **, off_t, int, int,
static int readsuper(void *, struct fs **, off_t, int,
int (*)(void *, off_t, void **, int));
static int validate_sblock(struct fs *, int);
@ -149,7 +149,7 @@ static int validate_sblock(struct fs *, int);
* The administrator must complete newfs before using this volume.
*/
int
ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
ffs_sbget(void *devfd, struct fs **fsp, off_t sblock, int flags,
struct malloc_type *filltype,
int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
{
@ -163,18 +163,23 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
fs = NULL;
*fsp = NULL;
if (altsblock >= 0) {
if ((error = readsuper(devfd, &fs, altsblock, 1, 0,
readfunc)) != 0) {
if (sblock != UFS_STDSB) {
if ((error = readsuper(devfd, &fs, sblock,
flags | UFS_ALTSBLK, readfunc)) != 0) {
if (fs != NULL)
UFS_FREE(fs, filltype);
return (error);
}
} else {
for (i = 0; sblock_try[i] != -1; i++) {
if ((error = readsuper(devfd, &fs, sblock_try[i], 0,
altsblock, readfunc)) == 0)
if ((error = readsuper(devfd, &fs, sblock_try[i],
flags, readfunc)) == 0) {
if ((flags & UFS_NOCSUM) != 0) {
*fsp = fs;
return (0);
}
break;
}
if (fs != NULL) {
UFS_FREE(fs, filltype);
fs = NULL;
@ -243,8 +248,8 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
* Return zero on success or an errno on failure.
*/
static int
readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
int chkhash, int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int flags,
int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
{
struct fs *fs;
int error, res;
@ -263,10 +268,10 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
* that will be accessed. Here we fail the lookup so that we can
* retry with the correct location for the UFS1 superblock.
*/
if (fs->fs_magic == FS_UFS1_MAGIC && !isaltsblk &&
if (fs->fs_magic == FS_UFS1_MAGIC && (flags & UFS_ALTSBLK) == 0 &&
fs->fs_bsize == SBLOCK_UFS2 && sblockloc == SBLOCK_UFS2)
return (ENOENT);
if ((error = validate_sblock(fs, isaltsblk)) != 0)
if ((error = validate_sblock(fs, flags)) > 0)
return (error);
/*
* If the filesystem has been run on a kernel without
@ -281,15 +286,16 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
fs->fs_metackhash &= CK_SUPPORTED;
fs->fs_flags &= FS_SUPPORTED;
if (fs->fs_ckhash != (ckhash = ffs_calc_sbhash(fs))) {
if (chkhash == STDSB_NOMSG)
return (EINTEGRITY);
if (chkhash == STDSB_NOHASHFAIL_NOMSG)
if ((flags & (UFS_NOMSG | UFS_NOHASHFAIL)) ==
(UFS_NOMSG | UFS_NOHASHFAIL))
return (0);
if ((flags & UFS_NOMSG) != 0)
return (EINTEGRITY);
#ifdef _KERNEL
res = uprintf("Superblock check-hash failed: recorded "
"check-hash 0x%x != computed check-hash 0x%x%s\n",
fs->fs_ckhash, ckhash,
chkhash == STDSB_NOHASHFAIL ? " (Ignored)" : "");
(flags & UFS_NOHASHFAIL) != 0 ? " (Ignored)" : "");
#else
res = 0;
#endif
@ -301,12 +307,10 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
printf("Superblock check-hash failed: recorded "
"check-hash 0x%x != computed check-hash "
"0x%x%s\n", fs->fs_ckhash, ckhash,
chkhash == STDSB_NOHASHFAIL ?
" (Ignored)" : "");
if (chkhash == STDSB)
return (EINTEGRITY);
/* chkhash == STDSB_NOHASHFAIL */
return (0);
(flags & UFS_NOHASHFAIL) ? " (Ignored)" : "");
if ((flags & UFS_NOHASHFAIL) != 0)
return (0);
return (EINTEGRITY);
}
/* Have to set for old filesystems that predate this field */
fs->fs_sblockactualloc = sblockloc;
@ -318,34 +322,40 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
/*
* Verify the filesystem values.
*/
#define ILOG2(num) (fls(num) - 1)
#define ILOG2(num) (fls(num) - 1)
#define MPRINT if (prtmsg) printf
#undef CHK
#define CHK(lhs, op, rhs, fmt) \
if (lhs op rhs) { \
printf("UFS%d superblock failed: %s (" #fmt ") %s %s (" \
MPRINT("UFS%d superblock failed: %s (" #fmt ") %s %s (" \
#fmt ")\n", fs->fs_magic == FS_UFS1_MAGIC ? 1 : 2, \
#lhs, (intmax_t)lhs, #op, #rhs, (intmax_t)rhs); \
return (ENOENT); \
if (error == 0) \
error = ENOENT; \
}
#define CHK2(lhs1, op1, rhs1, lhs2, op2, rhs2, fmt) \
if (lhs1 op1 rhs1 && lhs2 op2 rhs2) { \
printf("UFS%d superblock failed: %s (" #fmt ") %s %s (" \
MPRINT("UFS%d superblock failed: %s (" #fmt ") %s %s (" \
#fmt ") && %s (" #fmt ") %s %s (" #fmt ")\n", \
fs->fs_magic == FS_UFS1_MAGIC ? 1 : 2, #lhs1, \
(intmax_t)lhs1, #op1, #rhs1, (intmax_t)rhs1, #lhs2, \
(intmax_t)lhs2, #op2, #rhs2, (intmax_t)rhs2); \
return (ENOENT); \
if (error == 0) \
error = ENOENT; \
}
static int
validate_sblock(struct fs *fs, int isaltsblk)
validate_sblock(struct fs *fs, int flags)
{
u_long i, sectorsize;
u_int64_t maxfilesize, sizepb;
int error, prtmsg;
error = 0;
sectorsize = dbtob(1);
prtmsg = ((flags & UFS_NOMSG) == 0);
if (fs->fs_magic == FS_UFS2_MAGIC) {
if (!isaltsblk) {
if ((flags & UFS_ALTSBLK) == 0) {
CHK(fs->fs_sblockloc, !=, SBLOCK_UFS2, %#jx);
CHK2(fs->fs_sblockactualloc, !=, SBLOCK_UFS2,
fs->fs_sblockactualloc, !=, 0, %jd);
@ -358,7 +368,7 @@ validate_sblock(struct fs *fs, int isaltsblk)
CHK(fs->fs_inopb, !=, fs->fs_bsize / sizeof(struct ufs2_dinode),
%jd);
} else if (fs->fs_magic == FS_UFS1_MAGIC) {
if (!isaltsblk) {
if ((flags & UFS_ALTSBLK) == 0) {
CHK(fs->fs_sblockloc, >, SBLOCK_UFS1, %jd);
CHK(fs->fs_sblockactualloc, >, SBLOCK_UFS1, %jd);
}
@ -459,6 +469,13 @@ validate_sblock(struct fs *fs, int isaltsblk)
CHK(fs->fs_size, <, 8 * fs->fs_frag, %jd);
CHK(fs->fs_size, <=, (fs->fs_ncg - 1) * fs->fs_fpg, %jd);
CHK(fs->fs_size, >, fs->fs_ncg * fs->fs_fpg, %jd);
/*
* If we are not requested to read in the csum data stop here
* as the correctness of the remaining values is only important
* to bound the space needed to be allocated to hold the csum data.
*/
if ((flags & UFS_NOCSUM) != 0)
return (error);
CHK(fs->fs_csaddr, <, 0, %jd);
CHK(fs->fs_cssize, !=,
fragroundup(fs, fs->fs_ncg * sizeof(struct csum)), %jd);
@ -490,7 +507,7 @@ validate_sblock(struct fs *fs, int isaltsblk)
CHK2(fs->fs_maxcontig, ==, 0, fs->fs_contigsumsize, !=, 0, %jd);
CHK2(fs->fs_maxcontig, >, 1, fs->fs_contigsumsize, !=,
MIN(fs->fs_maxcontig, FS_MAXCONTIG), %jd);
return (0);
return (error);
}
/*

View File

@ -913,7 +913,7 @@ ffs_mountfs(struct vnode *odevvp, struct mount *mp, struct thread *td)
struct g_consumer *cp;
struct mount *nmp;
struct vnode *devvp;
int candelete, canspeedup;
int candelete, canspeedup, flags;
off_t loc;
fs = NULL;
@ -958,10 +958,12 @@ ffs_mountfs(struct vnode *odevvp, struct mount *mp, struct thread *td)
goto out;
}
/* fetch the superblock and summary information */
loc = STDSB;
loc = UFS_STDSB;
flags = 0;
if ((mp->mnt_flag & (MNT_ROOTFS | MNT_FORCE)) != 0)
loc = STDSB_NOHASHFAIL;
if ((error = ffs_sbget(devvp, &fs, loc, M_UFSMNT, ffs_use_bread)) != 0)
flags = UFS_NOHASHFAIL;
if ((error = ffs_sbget(devvp, &fs, loc, flags, M_UFSMNT, ffs_use_bread))
!= 0)
goto out;
fs->fs_flags &= ~FS_UNCLEAN;
if (fs->fs_clean == 0) {

View File

@ -79,26 +79,30 @@
{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
/*
* Request standard superblock location in ffs_sbget().
*
* STDSB will fail if the superblock has a check hash and it is wrong.
*
* STDSB_NOHASHFAIL will note that the check hash is wrong but will
* still return the superblock. This is used by the bootstrap code
* to give the system a chance to come up so that fsck can be run
* to correct the problem.
*
* STDSB_NOMSG is the same as STDSB but the kernel does not print an
* error message. It is used by programs like fsck that want to
* print their own error message.
*
* STDSB_NOHASHFAIL_NOMSG is the same as STDSB_NOHASHFAIL but the kernel
* does not print an error message. It is used by clients like glabel
* that just want to check for possible filesystem types.
*/
#define STDSB -1 /* Fail if check-hash is bad */
#define STDSB_NOHASHFAIL -2 /* Ignore check-hash failure */
#define STDSB_NOMSG -3 /* STDSB with no kernel message */
#define STDSB_NOHASHFAIL_NOMSG -4 /* STDSB_NOHASHFAIL with no message */
#define UFS_STDSB -1 /* Search standard places for superblock */
/*
* UFS_NOMSG indicates that superblock inconsistency error messages
* should not be printed. It is used by programs like fsck that
* want to print their own error message.
*
* UFS_NOCSUM causes only the superblock itself to be returned, but does
* not read in any auxiliary data structures like the cylinder group
* summary information. It is used by clients like glabel that just
* want to check for possible filesystem types. Using UFS_NOCSUM
* skips the superblock checks for csum data which allows superblocks
* that have corrupted csum data to be read and used.
*
* UFS_NOHASHFAIL will note that the check hash is wrong but will still
* return the superblock. This is used by the bootstrap code to
* give the system a chance to come up so that fsck can be run to
* correct the problem.
*/
#define UFS_NOHASHFAIL 0x0001 /* Ignore check-hash failure */
#define UFS_NOMSG 0x0004 /* Print no error message */
#define UFS_NOCSUM 0x0008 /* Read just the superblock without csum */
#define UFS_ALTSBLK 0x1000 /* Flag used internally */
/*
* Max number of fragments per block. This value is NOT tweakable.

View File

@ -50,11 +50,9 @@ fstyp_ufs(FILE *fp, char *label, size_t labelsize)
{
struct fs *fs;
switch (sbget(fileno(fp), &fs, STDSB)) {
switch (sbget(fileno(fp), &fs, UFS_STDSB, UFS_NOCSUM)) {
case 0:
strlcpy(label, fs->fs_volname, labelsize);
free(fs->fs_csp);
free(fs->fs_si);
free(fs);
return (0);
case ENOENT:

View File

@ -550,7 +550,7 @@ quot(char *name, char *mp)
close(fd);
return;
}
switch (sbget(fd, &fs, STDSB)) {
switch (errno = sbget(fd, &fs, UFS_STDSB, UFS_NOCSUM)) {
case 0:
break;
case ENOENT:
@ -567,8 +567,6 @@ quot(char *name, char *mp)
printf(" (%s)",mp);
putchar('\n');
(*func)(fd, fs, name);
free(fs->fs_csp);
free(fs->fs_si);
free(fs);
close(fd);
}