[comp.unix.i386] inode bug not quite fixed in ISC 2.2

scjones@thor.UUCP (Larry Jones) (07/29/90)

Well, despite rumors to the contrary, the dreaded System V inode
bug isn't quite fixed in ISC 2.2.  Someone did make a valiant
attempt, but they didn't quite get it.  Thanks to all of the
other people who have posted on this subject before (particularly
Bill Wells and Mayer Ilovitz), I was able to analyze the problem
and come up with a definitive fix.  The critical section of code
now looks something like:

	Read inodes into cache
	If cache not completely full then
		Set sentinal in cache
		Set place to start reading to inode 0
	If cache not empty, go allocate inode and return
	If the total number of free inodes == 0 or
	place to start reading is inode 0 then
		Out of inodes error
	Set place to start reading to inode 0
	Go read more inodes

Where this fails is when it reads all the way to the end of the
inode list without finding any free inodes to put in the cache.
Since the cache is not completely full, it sets the sentinal and
also sets the place to start reading to zero.  If there was at
least one inode found and put into the cache, it would go and
allocate it and, when the cache empties, it will start reading at
inode zero and hence find any other free inodes.  However, when
there were none found, even if there are still free inodes, it
thinks there aren't because the place to start reading is set to
zero.  The problem is not the test since, if it had really read
from inode zero without finding any free inodes, there aren't
any and the free inode count in the superblock is wrong.  The
problem is setting the place to start reading when the cache
isn't completely filled.  There's no reason to do it anymore
since the failure code sets it and rereads.  So the fix is to
simply remove that assignment.

So, here's how to fix it once and for all.  First, run the
following shell script to create /tmp/Driver.o and make sure that
it worked correctly.  Save a copy of your kernel and
/etc/conf/pack.d/s5/Driver.o.  Move /tmp/Driver.o to
/etc/conf/pack.d/s5/Driver.o and rebuild your kernel.  The inode
bug is now really and truely gone.

If anyone has problems, you can send me email and I'll try to
help out.

# ----- cut here -----
:
in=/etc/conf/pack.d/s5/Driver.o
out=/tmp/Driver.o

# check that we have the right Driver.o file

if [ x"`sum $in`" != x"24406 96 $in" ]; then
	echo "sum failed"
	exit 1
fi
if [ x"`sum -r $in`" != x"27711    96 $in" ]; then
	echo "sum -r failed"
	exit 1
fi

# copy the file and make an appropriate fix

{
	dd ibs=1 obs=1k count=2141
	dd bs=9 count=1 of=/dev/null
	echo '\0353\0007\0220\0220\0220\0220\0220\0220\0220\c'
	dd bs=16k
} <$in >$out

# compare the list of differences against the expected differences

cat <<\+ >/tmp/fix$$
  2142 146 353
  2143 307   7
  2144 207 220
  2145 326 220
  2146   0 220
  2147   0 220
  2148   0 220
  2149   0 220
  2150   0 220
+
if cmp -l $in $out | cmp -s - /tmp/fix$$; then
	rm /tmp/fix$$
	exit 0
else
	rm /tmp/fix$$
	echo "patch failed"
	exit 1
fi
----
Larry Jones                         UUCP: uunet!sdrc!thor!scjones
SDRC                                      scjones@thor.UUCP
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"This probably just goes to show something, but I sure don't know what."
-Calvin