Subject: panics in ext2fs filesystem code (wrong inode number range)
To: NetBSD Current Users <current-users@netbsd.org>
From: Barry Bouwsma <NOSPAM@Net.BSD.Linux.dk>
List: current-users
Date: 11/17/2006 12:12:54
[This message was composed some months ago, but I think is still
 relevant.  Don't reply to me as I'm almost never online now]


Hej,

I've had two different panics with an ext2fs filesystem and the
[what had been] latest -current kernel from mid-august.

The first was a readily-repeatable dup alloc panic.  When a newly-
created file can no longer fit in the cg, a quadtratic search followed
by a brute force search for a free inode is attempted.  In my case,
this resulted in inode 32 being allocated, and the next attempt to
allocate an inode again attempted to allocate inode 32.

I believe the root of the problem may be due to setting the preferred
inode to `0' when calling any of the fallback allocation strategies.
This 0 is then converted to -1.  By restoring it to 0, I'm able to
successfully exhaust all available inodes in my ext2fs filesystem
without a panic.  There may be a different reason; see below.

The next panic occurred when removing all the files created to fill
the filesystem, with a `range' error.  The NetBSD ext2fs code checks
if the inode number is >= the maximum number of inodes.  However, the
panic occurred when removing inode 2176 out of 2176.  Apparently, the
ext2fs inode numbering goes from 1 to MAX, not to MAX-1, which may
also be related to the first panic (where the previously-existing
inodes seemed to be somewhat randomly taken from various cg's rather
than being allocated to fill a cg).

Changing the range check to allow the max number of inodes resulted
in a successful deletion of all the inodes successfully created to
fill the fs.

If the ext2fs code is written based on the assumption of inodes from
0 to MAX-1 rather than from 1 to MAX, there may well be other related
bugs lurking elsewhere in the ext2fs code (possibly in fsck_ext2fs),
that I haven't taken the time to try to wrap my brain around, about,
and across.  Someone with intimate familiarity with the NetBSD ext2fs
and general UFS code should take a look at this instead.

There are no doubt a number of ways to fix the first problem --
perhaps replacing the `ipref' value of 0 with 1 in all the calls to
hashalloc for inodes.  I took the easy way out, not knowing what the
code was supposed to be doing, of correcting -1 to 0 after ipref was
adjusted by -1.


I've chosen not to send my ugly patches, in the hope that someone
with far more intimate knowledge of the ufs/ext2fs filesystems and an
overall grasp of the code (that I don't have) would better understand
the problem and come up with a correct solution.  However, here's
what I've done, for reference:
NOT A COMPLETE PATCH  @@ -441,9 +453,21 @@
        ipref--; /* to avoid a lot of (ipref -1) */
+       if (ipref == -1) ipref = 0;  /* XXX HACK */
        fs = ip->i_e2fs;
also...  @@ -554,7 +583,11 @@
        fs = pip->i_e2fs;
-       if ((u_int)ino >= fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
+       if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
                panic("ifree: range: dev = 0x%x, ino = %llu, fs = %s",

The panics can be reproduced by taking a native-Linux ext2fs
filesystem of not-too-big size, mounting rw on NetBSD-current,
and touching files until one runs out of inodes; then the
second panic is triggered by trying to remove the highest-
number inode after one successfully runs out of inodes (or
just rm everything).


Apologies if this is no longer a problem, and for not being able
to follow-up or sending this as a pr.


thanks
barry bouwsma