diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h index 5045117b5d7d..cb8774454b38 100644 --- a/lib/libufs/libufs.h +++ b/lib/libufs/libufs.h @@ -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); /* diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c index 9ba012400f1d..5708d50aa4f9 100644 --- a/lib/libufs/sblock.c +++ b/lib/libufs/sblock.c @@ -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); } diff --git a/lib/libufs/sbread.3 b/lib/libufs/sbread.3 index e97469f86873..f579fc7ffdf1 100644 --- a/lib/libufs/sbread.3 +++ b/lib/libufs/sbread.3 @@ -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 diff --git a/lib/libufs/type.c b/lib/libufs/type.c index ac5b8d17e84c..80b26cdb9c84 100644 --- a/lib/libufs/type.c +++ b/lib/libufs/type.c @@ -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); diff --git a/sbin/dump/main.c b/sbin/dump/main.c index 8752f2c1bea5..779db5fb4b43 100644 --- a/sbin/dump/main.c +++ b/sbin/dump/main.c @@ -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"); diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c index 7f2acdf435ea..6a586ffb95ec 100644 --- a/sbin/dumpfs/dumpfs.c +++ b/sbin/dumpfs/dumpfs.c @@ -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) diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index 0f0d9b61a076..0daac100499a 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -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: diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c index c4db8848f18b..90305416f556 100644 --- a/sbin/fsirand/fsirand.c +++ b/sbin/fsirand/fsirand.c @@ -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"); diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 69e6f04dd4c2..4a8d935d91c7 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -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"); diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c index 9a01be11d9d0..1e656d2a5811 100644 --- a/sbin/quotacheck/quotacheck.c +++ b/sbin/quotacheck/quotacheck.c @@ -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"); diff --git a/stand/libsa/ufs.c b/stand/libsa/ufs.c index 12703a3e18aa..de3dbe58789b 100644 --- a/stand/libsa/ufs.c +++ b/stand/libsa/ufs.c @@ -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; } diff --git a/sys/geom/journal/g_journal_ufs.c b/sys/geom/journal/g_journal_ufs.c index dec28e547f82..dc9604abae22 100644 --- a/sys/geom/journal/g_journal_ufs.c +++ b/sys/geom/journal/g_journal_ufs.c @@ -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, diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c index 0de09ec93896..691f875cf6cc 100644 --- a/sys/geom/label/g_label_ufs.c +++ b/sys/geom/label/g_label_ufs.c @@ -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); } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index fdc08dc6aafb..54820fc5b3ce 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -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)); diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c index 502ef79c7bd3..611f1989e8f9 100644 --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -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); } /* diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b41c162dea7d..2944d0c5077d 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -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) { diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index 8c0047f17caf..81cb416b383d 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -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. diff --git a/usr.sbin/fstyp/ufs.c b/usr.sbin/fstyp/ufs.c index e4de1283e769..69ce90d600f2 100644 --- a/usr.sbin/fstyp/ufs.c +++ b/usr.sbin/fstyp/ufs.c @@ -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: diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c index fa1ee1c65fe7..7e84dd79e148 100644 --- a/usr.sbin/quot/quot.c +++ b/usr.sbin/quot/quot.c @@ -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); }