Re: Strange diff behaviour

From: Andy Valencia <vandys_at_nospam.org>
Date: Thu Oct 22 1998 - 18:58:28 PDT

["Juan Jose Villaplana Querol" <villapla@si.uji.es> writes:]

> I think I was not clear in my previous e-mail, diff stops working
> only for the files located in the executable's directory. The
> executable may be a "Hello world" written in C, any executable
> copied from /vsta/bin to this directory, ...

Ah, now I can guess what's biting you.

If you diff "f1" and "f2", could you try putting:

    sleep 20000 < f1 &
    sleep 20000 < f2 &

and then run the diff on "f1" and "f2"? I bet you'll get the correct diff
output.

(Arcane filesystem rambles follow.)

This goes *way* back in DOS filesystem hassles. Basically, DOS is funny in
that (1) a directory may or may not exist in terms of filesystem allocation
blocks (the root doesn't, but all subdirs do), and (2) a file may or may not
correspond to any allocated blocks. In particular, a zero-length file has
no clusters and is only known by its directory entry.

diff tries to optimize by looking at the inode number of files which it'll
compare. The DOS server as written just uses the "struct node" pointer as
the inode number, which guarantees inode number uniqueness only until last
close of the file. So I bet what you're hitting is that "diff" stat's one
file, gets an inode number, closes the file, and stat's the next one. The
DOS server happens to use the same malloc()'ed block, therefore the
successively opened files appear to get the same inode number. Bleh.

I've just fixed it in my source. Inode number is now the cluster number of
the directory containing the file (or 0 for root) shifted left 16 bits,
OR'ed in with the directory entry offset. This will have to be revisited
for FAT-32.

This also interacts with an old bug, where if you ran an executable, and
then mv'ed it, you could no longer remove that executable. There's an
interesting problem where if your file needs to be named by its directory
entry, then your "inode number" changes when you change the name of the file
(well, move it to a new directory or directory slot). Inode number is the
connection used to coordinate between the kernel page cache for an
executable and the filesystem server which fills in the contents of these
pages. I've added code to unhash the file during the rename if it was an
executable which had been previously run, so that there's no kernel state to
remain consistent with. It's not good enough to insist there's no open
references to a file which will be renamed--GNU "ar" holds an open file
descriptor to a newly built library while it renames it from foo.a_supersede
to foo.a.

I've coded this all up, and it appears to work right. I should probably
push out a 1.6.2 as there seems to be enough interesting fixes accumulated
from 1.6.1.

                                                        Andy
Received on Thu Oct 22 14:56:02 1998

This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:55 PDT