Subject: Re: ffs compat problem since ffs2
To: Manuel Bouyer <bouyer@antioche.eu.org>
From: Luke Mewburn <lukem@NetBSD.org>
List: tech-kern
Date: 09/26/2003 08:35:30
On Sat, Sep 06, 2003 at 12:30:26AM +0200, Manuel Bouyer wrote:
  | since ffsv2 was introduced, we have a problem where an old NetBSD
  | kernel fails to use filesystems which have been mounted R/W by a new
  | kernel (PR 21283) I tracked this down to the new kernel setting the
  | FS_FLAGS_UPDATED flag in the superblock, which unfortunably happens
  | to be the old FS_SWAPPED flag. And old kernel will keep this flag
  | after mount, and swap the filesystem when it shouldn't.
  | 
  | I agree that the (old) kernel should have filtered this flag at
  | mount time, but unfortunably it doesn't and it's too late to fix it.

Yes.  However, your fix doesn't work correctly either...

Recently I experienced some lossage with a new kernel on an older
-current system (looked like FS corruption), and upon further
investigation, determined that a -current GENERIC kernel works
but my custom cut-down kernel with FFS_EI did not.

I also noticed that dumpfs was printing the wrong results.
See below for more info...


  | FS_FLAGS_UPDATED is used to tell the kernel that the superblock has been
  | updated to the new world. It's used in 3 places:

Actually, it's used in more than just the kernel.

Further investigation reveals that FS_SWAPPED and FS_FLAGS_UPDATED
are used in more than just src/sys/ufs ...

   FS_FLAGS_UPDATED
	sys/ufs/ffs/ffs_vfsops.c
		set in fs_old_flags
		tested in fs_old_flags
		fs_flags gets all fs_old_flags except FS_FLAGS_UPDATED
	sys/ufs/ffs/fs.h
		defined
	sbin/fsck_ffs/utilities.c
		tested in fs_old_flags
	sbin/newfs/mkfs.c
		set in fs_old_flags
	usr.sbin/dumpfs/dumpfs.c
		tested in fs_old_flags
	usr.sbin/makefs/ffs/mkfs.c
		set in fs_old_flags

   FS_SWAPPED
	sys/ufs/ffs/ffs_vfsops.c
		set in fs_flags
		cleared in fs_flags
	sys/ufs/ffs/fs.h
		defined
	sys/ufs/ufs/ufs_bswap.h
		tested as part of UFS_FSNEEDSWAP()
	usr.sbin/makefs/ffs/mkfs.c
		set in fs_flags (for ffs_write_superblock() ?)




  | One obvious way of doing it would be to change FS_FLAGS_UPDATED to 0x40,
  | but this will likely cause compat problems with the others BSDs.
  |
  | [...]
  |
  | I think we could remove checks of FS_FLAGS_UPDATED in our kernel, and
  | not set FS_FLAGS_UPDATED if we're not using any of the new features
  | (basically, if fs->fs_flags contains only FS_UNCLEAN and FS_DOSOFTDEP)
  |
  | [...]
  |
  | So it looks like we don't need to set FS_FLAGS_UPDATED for v1
  | filesystem on NetBSD. But unfortunably, not doing this may cause
  | compatibility problems with others BSD.


Given that fsck_ffs & dumpfs currently test FS_FLAGS_UPDATED,
we need to do one of:

   a)	Renumber FS_FLAGS_UPDATED to 0x40 and reinstate FS_FLAGS_UPDATED
    	setting in fs_old_flags in the kernel.

	This should retain backwards compat with NetBSD 1.6.x prior
	to your recent ``fs_flags &= ~FS_SWAPPED'' fix & pullup.

	This isn't compatible with the "other BSDs", but neither
	is our current situation anyway...

	We can ask the "other BSDs" (i.e, Kirk :) to reserve 0x40 in
	their fs_flags and not use it going forward.


    b)	Implement a new macro, something like:

		#define FS_UPDATED_UFS1(fs) \
			(((fs)->fs_magic == FS_UFS1_MAGIC)
			&& ((fs)->fs_maxbsize == (fs)->fs_bsize))

	Use that instead of "(foo.fs_old_flags & FS_FLAGS_UPDATED) == 0"

	Deprecate FS_FLAGS_UPDATED except as a place-holder (maybe
	rename it in fs.h ?)


    c)	Revert the recent changes and set FS_FLAGS_UPDATED in the
	kernel, with FS_FLAGS_UPDATED being 0x80.

	Leave the FS_SWAPPED fixes in -current and the head of the
	-1-6 branch.


I'm leaning towards `a)' at this point.