From: scjones@thor.sdrc.com (Larry Jones)
Newsgroups: comp.unix.sysv386
Subject: ISC 2.2 Fix for inode bug
Date: 11 Apr 92 22:24:56 GMT
Organization: SDRC, Cincinnati

Finally, here's the message I posted long ago with the fix for
ISC 2.2 and 2.2.1:

Well, despite rumors to the contrary, the dreaded System V inode
bug isn't quite fixed in ISC 2.2 or 2.2.1.  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.

#! /bin/sh
in=${1:-/etc/conf/pack.d/s5/Driver.o}
out=${2:-/tmp/Driver.o}

# check that we have the right Driver.o file

case "`mcs -p $in`" in

*"inode bug fix")
	echo "Patch already applied!"
	exit 1
	;;

*"INTERACTIVE UNIX System, Upgrade Version 2.2.1")
	if [ x"`sum $in`" != x"30589 96 $in" ]; then
		echo "sum failed"
		exit 1
	fi
	if [ x"`sum -r $in`" != x"17287    96 $in" ]; then
		echo "sum -r failed"
		exit 1
	fi
	;;

*"INTERACTIVE UNIX System, Update Version SSU.1a to Kernel Configuration Version 2.2")
	if [ x"`sum $in`" != x"36164 96 $in" ]; then
		echo "sum failed"
		exit 1
	fi
	if [ x"`sum -r $in`" != x"01942    96 $in" ]; then
		echo "sum -r failed"
		exit 1
	fi
	;;

*"INTERACTIVE UNIX System, Kernel Configuration Version 2.2")
	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
	;;

*)
	echo "Unknown version -- can't patch"
	exit 1
	;;
esac

# 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$$
	mcs -a '@(#)Driver.o: inode bug fix' $out
	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