aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/journal/g_journal_ufs.c2
-rw-r--r--sys/geom/label/g_label_ufs.c2
-rw-r--r--sys/ufs/ffs/ffs_extern.h6
-rw-r--r--sys/ufs/ffs/ffs_subr.c35
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c7
5 files changed, 39 insertions, 13 deletions
diff --git a/sys/geom/journal/g_journal_ufs.c b/sys/geom/journal/g_journal_ufs.c
index de0dbd83d48b..028c68079482 100644
--- a/sys/geom/journal/g_journal_ufs.c
+++ b/sys/geom/journal/g_journal_ufs.c
@@ -72,7 +72,7 @@ g_journal_ufs_dirty(struct g_consumer *cp)
fs = NULL;
if (SBLOCKSIZE % cp->provider->sectorsize != 0 ||
- ffs_sbget(cp, &fs, -1, M_GEOM, g_use_g_read_data) != 0) {
+ ffs_sbget(cp, &fs, STDSB, 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 b247eaad827d..4c4d43cad0f7 100644
--- a/sys/geom/label/g_label_ufs.c
+++ b/sys/geom/label/g_label_ufs.c
@@ -77,7 +77,7 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int wh
fs = NULL;
if (SBLOCKSIZE % pp->sectorsize != 0 ||
- ffs_sbget(cp, &fs, -1, M_GEOM, g_use_g_read_data) != 0) {
+ ffs_sbget(cp, &fs, STDSB, M_GEOM, g_use_g_read_data) != 0) {
KASSERT(fs == NULL,
("g_label_ufs_taste_common: non-NULL fs %p\n", fs));
return;
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index d3f6cb597b9a..16f517d5f12e 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -126,6 +126,12 @@ void process_deferred_inactive(struct mount *mp);
#define FFSR_UNSUSPEND 0x0002
/*
+ * Request standard superblock location in ffs_sbget
+ */
+#define STDSB -1 /* Fail if check-hash is bad */
+#define STDSB_NOHASHFAIL -2 /* Ignore check-hash failure */
+
+/*
* Definitions for TRIM interface
*
* Special keys and recommended hash table size
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index e4dbd730b186..64354bbd5383 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -51,6 +51,11 @@ struct malloc_type;
#define UFS_MALLOC(size, type, flags) malloc(size)
#define UFS_FREE(ptr, type) free(ptr)
#define UFS_TIME time(NULL)
+/*
+ * Request standard superblock location in ffs_sbget
+ */
+#define STDSB -1 /* Fail if check-hash is bad */
+#define STDSB_NOHASHFAIL -2 /* Ignore check-hash failure */
#else /* _KERNEL */
#include <sys/systm.h>
@@ -139,14 +144,14 @@ ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
ip->i_gid = dip2->di_gid;
return (0);
}
-#endif /* KERNEL */
+#endif /* _KERNEL */
/*
* These are the low-level functions that actually read and write
* the superblock and its associated data.
*/
static off_t sblock_try[] = SBLOCKSEARCH;
-static int readsuper(void *, struct fs **, off_t, int,
+static int readsuper(void *, struct fs **, off_t, int, int,
int (*)(void *, off_t, void **, int));
/*
@@ -177,21 +182,25 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
int i, error, size, blks;
uint8_t *space;
int32_t *lp;
+ int chkhash;
char *buf;
fs = NULL;
*fsp = NULL;
- if (altsblock != -1) {
- if ((error = readsuper(devfd, &fs, altsblock, 1,
+ chkhash = 1;
+ if (altsblock >= 0) {
+ if ((error = readsuper(devfd, &fs, altsblock, 1, chkhash,
readfunc)) != 0) {
if (fs != NULL)
UFS_FREE(fs, filltype);
return (error);
}
} else {
+ if (altsblock == STDSB_NOHASHFAIL)
+ chkhash = 0;
for (i = 0; sblock_try[i] != -1; i++) {
if ((error = readsuper(devfd, &fs, sblock_try[i], 0,
- readfunc)) == 0)
+ chkhash, readfunc)) == 0)
break;
if (fs != NULL) {
UFS_FREE(fs, filltype);
@@ -255,7 +264,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
*/
static int
readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
- int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
+ int chkhash, int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
{
struct fs *fs;
int error, res;
@@ -285,8 +294,9 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
if (fs->fs_ckhash != (ckhash = ffs_calc_sbhash(fs))) {
#ifdef _KERNEL
res = uprintf("Superblock check-hash failed: recorded "
- "check-hash 0x%x != computed check-hash 0x%x\n",
- fs->fs_ckhash, ckhash);
+ "check-hash 0x%x != computed check-hash 0x%x%s\n",
+ fs->fs_ckhash, ckhash,
+ chkhash == 0 ? " (Ignored)" : "");
#else
res = 0;
#endif
@@ -297,7 +307,14 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
if (res == 0)
printf("Superblock check-hash failed: recorded "
"check-hash 0x%x != computed check-hash "
- "0x%x\n", fs->fs_ckhash, ckhash);
+ "0x%x%s\n", fs->fs_ckhash, ckhash,
+ chkhash == 0 ? " (Ignored)" : "");
+ if (chkhash == 0) {
+ fs->fs_flags |= FS_NEEDSFSCK;
+ fs->fs_fmod = 1;
+ return (0);
+ }
+ fs->fs_fmod = 0;
return (EINVAL);
}
/* Have to set for old filesystems that predate this field */
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 9670d6217e86..7cb81cfa450a 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -774,6 +774,7 @@ ffs_mountfs(devvp, mp, td)
struct g_consumer *cp;
struct mount *nmp;
int candelete;
+ off_t loc;
fs = NULL;
ump = NULL;
@@ -810,9 +811,11 @@ ffs_mountfs(devvp, mp, td)
goto out;
}
/* fetch the superblock and summary information */
- if ((error = ffs_sbget(devvp, &fs, -1, M_UFSMNT, ffs_use_bread)) != 0)
+ loc = STDSB;
+ if ((mp->mnt_flag & MNT_ROOTFS) != 0)
+ loc = STDSB_NOHASHFAIL;
+ if ((error = ffs_sbget(devvp, &fs, loc, M_UFSMNT, ffs_use_bread)) != 0)
goto out;
- fs->fs_fmod = 0;
/* none of these types of check-hashes are maintained by this kernel */
fs->fs_metackhash &= ~(CK_INODE | CK_INDIR | CK_DIR);
/* no support for any undefined flags */