Skip to content

Commit 996d40f

Browse files
Kirk McKusickKirk McKusick
authored andcommitted
Various new check-hash checks have been added to the UFS filesystem
over various major releases. Superblock check hashes were added for the 12 release and cylinder-group and inode check hashes will appear in the 13 release. When a disk with a UFS filesystem is writably mounted, the kernel clears the feature flags for anything that it does not support. For example, if a UFS disk from a 12-stable kernel is mounted on an 11-stable system, the 11-stable kernel will clear the flag in the filesystem superblock that indicates that superblock check-hashs are being maintained. Thus if the disk is later moved back to a 12-stable system, the 12-stable system will know to ignore its incorrect check-hash. If the only filesystem modification done on the earlier kernel is to run a utility such as growfs(8) that modifies the superblock but neither updates the check-hash nor clears the feature flag indicating that it does not support the check-hash, the disk will fail to mount if it is moved back to its original newer kernel. This patch moves the code that clears the filesystem feature flags from the mount code (ffs_mountfs()) to the code that reads the superblock (ffs_sbget()). As ffs_sbget() is used by the kernel mount code and is imported into libufs(3), all the filesystem utilities will now also clear these flags when they make modifications to the filesystem. As suggested by John Baldwin, fsck_ffs(8) has been changed to accept and repair bad superblock check-hashes rather than refusing to run. This change allows fsck to recover filesystems that have been impacted by utilities older than those created after this change and is a sensible thing to do in any event. Reported by: John Baldwin (jhb@) MFC after: 2 weeks Sponsored by: Netflix
1 parent 6cb13a3 commit 996d40f

File tree

4 files changed

+10
-7
lines changed

4 files changed

+10
-7
lines changed

sbin/fsck_ffs/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ readsb(int listerr)
330330
int bad, ret;
331331
struct fs *fs;
332332

333-
super = bflag ? bflag * dev_bsize : STDSB;
333+
super = bflag ? bflag * dev_bsize : STDSB_NOHASHFAIL;
334334
readcnt[sblk.b_type]++;
335335
if ((ret = sbget(fsreadfd, &fs, super)) != 0) {
336336
switch (ret) {

sys/ufs/ffs/ffs_subr.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,15 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsblock,
165165

166166
fs = NULL;
167167
*fsp = NULL;
168-
chkhash = 1;
169168
if (altsblock >= 0) {
170-
if ((error = readsuper(devfd, &fs, altsblock, 1, chkhash,
169+
if ((error = readsuper(devfd, &fs, altsblock, 1, 0,
171170
readfunc)) != 0) {
172171
if (fs != NULL)
173172
UFS_FREE(fs, filltype);
174173
return (error);
175174
}
176175
} else {
176+
chkhash = 1;
177177
if (altsblock == STDSB_NOHASHFAIL)
178178
chkhash = 0;
179179
for (i = 0; sblock_try[i] != -1; i++) {
@@ -277,6 +277,12 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
277277
*/
278278
if ((fs->fs_flags & FS_METACKHASH) == 0)
279279
fs->fs_metackhash = 0;
280+
/*
281+
* Clear any check-hashes that are not maintained
282+
* by this kernel. Also clear any unsupported flags.
283+
*/
284+
fs->fs_metackhash &= CK_SUPPORTED;
285+
fs->fs_flags &= FS_SUPPORTED;
280286
if (fs->fs_ckhash != (ckhash = ffs_calc_sbhash(fs))) {
281287
#ifdef _KERNEL
282288
res = uprintf("Superblock check-hash failed: recorded "

sys/ufs/ffs/ffs_vfsops.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,10 +1070,6 @@ ffs_mountfs(odevvp, mp, td)
10701070
loc = STDSB_NOHASHFAIL;
10711071
if ((error = ffs_sbget(devvp, &fs, loc, M_UFSMNT, ffs_use_bread)) != 0)
10721072
goto out;
1073-
/* none of these types of check-hashes are maintained by this kernel */
1074-
fs->fs_metackhash &= ~(CK_INDIR | CK_DIR);
1075-
/* no support for any undefined flags */
1076-
fs->fs_flags &= FS_SUPPORTED;
10771073
fs->fs_flags &= ~FS_UNCLEAN;
10781074
if (fs->fs_clean == 0) {
10791075
fs->fs_flags |= FS_UNCLEAN;

sys/ufs/ffs/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ CTASSERT(sizeof(struct fs) == 1376);
501501
#define CK_INODE 0x0004 /* inodes */
502502
#define CK_INDIR 0x0008 /* indirect blocks */
503503
#define CK_DIR 0x0010 /* directory contents */
504+
#define CK_SUPPORTED 0x0007 /* supported flags, others cleared at mount */
504505
/*
505506
* The BX_FSPRIV buffer b_xflags are used to track types of data in buffers.
506507
*/

0 commit comments

Comments
 (0)