Xref: utzoo news.misc:4968 news.software.b:5084 comp.sources.bugs:2433 comp.bugs.sys5:1289 comp.unix.i386:6452 Path: utzoo!utstat!news-server.csri.toronto.edu!cs.utexas.edu!texbell!nuchat!buster!rli From: rli@buster.irby.com (Buster Irby) Newsgroups: news.misc,news.software.b,comp.sources.bugs,comp.bugs.sys5,comp.unix.i386 Subject: Re: Out of inodes while unbatching news Keywords: Help! Message-ID: <1990Jul03.160752.24309@buster.irby.com> Date: 3 Jul 90 16:07:52 GMT References: <586@fnx.UUCP> <1990Jul03.111044.17761@virtech.uucp> Reply-To: rli@buster.irby.com Distribution: na Organization: Buster irby Lines: 151 cpcahil@virtech.uucp (Conor P. Cahill) writes: >In article <586@fnx.UUCP> del@fnx.UUCP (Dag Erik Lindberg) writes: >> >> [story of running out of inodes deleted] >> >>The details: The system is a Mylex 20 Mhz w/64k cache, 8 MB memory, ATI >>VGA wonder. I have unbatched news with no serial ports installed in the >>system, same problem. I have tried a DTC RLL card, WD 7000 FASST SCSI card, >>Adaptec 1542 SCSI, and all have shown the same problem. I am currently >>running ISC Unix. I have stripped down the system to just the video card >>and the disk controller to try to find this problem. >The only pertinent portion of this is the Operating system and you don't >specify the version. >This inode thing is a known bug that as far as I know was fixed in version >2.0.2 of 386/ix (I have been running news on a partition without running >out of inodes for a year). No, it did not. I ran 2.0.2 for only a few days before the bug reared its ugly head. Included below is the patch I received from T. William Wells. I applied it and it fixed the problem (Thanks again Bill). The problem does however appear to have been fixed in version 2.2. ------------------------inode.fix---------------------- From: uunet!twwells.com!bill (T. William Wells) Date: 16 Oct 89 18:54:06 EDT (Mon) Subject: Inode bug fix for ISC 2.0.2 Since I've got so many requests for the fix for the inode bug for ISC 2.0.2, I decided to post it. Sorry I've been so slothful on this; various things popped up and I wasn't able to get it all together. In case you want to know what this is: there is a kernel bug that, on occasion, and particularly if you are running a newsfeed, will cause the file system to think that there are no more free inodes, thus preventing creation of new files. Running fsck fixes the inode count but doesn't prevent the problem from occuring again. The problem is this: there is a "free inode cache" stored in the superblock for each file system; this block is kept in memory when the file system is mounted, thus the inode cache permits rapid allocation of inodes. When the cache is emptied, the kernel tries to read more inodes from the disk to fill the cache and then retries the allocate. If the kernel is unable to read more inodes from the disk, it assumes that there are no more free inodes. There is an optimization in the allocation code, which depends on the condition that the lowest free inode is always in the inode cache. What it does is to start the disk read from that lowest inode, instead of the first inode. This means that the inode table doesn't have to always be fully read, for what could be a significant savings in allocating inodes. (Consider what might happen when almost all inodes are in use.) However, the kernel does not maintain that condition properly. It is possible for the kernel to forget the lowest inode, with the effect that the kernel tries to read from some place too far in the inode table, and maybe discovers that there are no free inodes. When that happens, the kernel clears the available inode count, and the file system is essentially kaput. The right fix for this would be to always maintain that condition. However, a binary patch for that would be tricky at best, and maybe impossible. A patch that is possible is to have the allocation routine try from the beginning of the inode table whenever it fails to read inodes from the disk, relying on the free inode count to tell when the table is empty. This changes the condition that must be maintained to: the free inode count must always be accurate. (Having the free inode count never be larger than the actual number of free inodes is sufficient for the patch to not cause problems.) I made a similar patch for Microport SysV/386 3.0e and have been running it for most of this year without problems. I was asked to solve this for Interactive 2.0.2 and did so. However, I did the work on my Microport system, and the enclosed shell script works on that; it ought to work on an Interactive system but I've not tried this. With that caveat, here is what you do to patch your kernel. First, run the shell script. Make sure that it behaved correctly. Then save a copy of your good kernel and /etc/conf/pack.d/s5/Driver.o. If you are really paranoid, back up your whole system, though this shouldn't be necessary. Replace the Driver.o file with the one on /tmp. Finally, rebuild your kernel. That particular bug should never bite you again. Further kernel builds will have the bug fixed as well. If you have any problems, send me e-mail. I'll try to get back to you quicker than I did with this! If the patch causes some nasty kind of crash, please post immediately in hopes that others will read your message before having tried the patch. 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"50880 81 $in" ]; then echo "sum failed" exit 1 fi if [ x"`sum -r $in`" != x"33908 81 $in" ]; then echo "sum -r failed" exit 1 fi # copy the file and make an appropriate fix { dd ibs=1 obs=1k count=1977 dd bs=19 count=1 of=/dev/null echo '\074\0144\017\0204\0327\0376\0377\0377\0146\c' echo '\0307\0207\0324\00\00\00\0144\00\0353\0151\c' dd bs=16k } <$in >$out # compare the list of differences against the expected differences cat <<\+ >/tmp/fix$$ 1978 75 74 1980 0 17 1981 0 204 1982 0 327 1983 164 376 1984 14 377 1985 146 377 1986 307 146 1987 207 307 1988 324 207 1989 0 324 1992 144 0 1993 0 144 1994 353 0 1995 152 353 1996 220 151 + 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 --- Bill { uunet | novavax | ankh | sunvice } !twwells!bill bill@twwells.com -- Buster Irby buster!rli