Subject: Re: funlink() for fun!
To: NetBSD Kernel Technical Discussion List <tech-kern@NetBSD.org>
From: Greywolf <greywolf@starwolf.com>
List: tech-kern
Date: 07/11/2003 16:20:43
Thus spake Greg A. Woods ("GAW> ") sometime Today...

GAW> Unlink(2) may specifically also operate on files as well as the link in
GAW> the parent directory, and it will always also operate on the file if
GAW> that file has only one link.

No, it doesn't.  The only thing that happens to the file, per se, is a
side effect of the deletion of all physical entries associated with a
record of the data.   The operation of unlink(2) is only associated with
a file in that said file is a special type of file called a directory.
Otherwise, all that happens is the link count of the node representing
the file drops to zero, the last physical entry which names that inode
is removed, and, unless another process is holding open a file descriptor
associated with that inode, the data blocks of that inode are unallocated
and the inode is cleared.

Strictly speaking, this has *nothing* to do with the file and *everything*
to do with the file's metadata.  Sure, the end result is that the data is
lost, but when you have cleared all physical references to the metadata,
what else are you supposed to do? :-)

To pinball off in another direction and re-iterate:  The only way that a
funlink() call can hope to work is to maintain a table of (vno_t **)
around which contain offsets into dirs represented by other (vno_t *), and
if you need to funlink() a file, you can at least get the offsets of all
the links, visit the dirs associated with them, clear their entries and
remove the (vno_t **) from the table.  We wouldn't even need to know pathnames
if we knew dir vps and offsets into them for the entries.

There's some details I am missing, I'm sure, but anyone reading this who
does anything with fs internals will probably get the concept.  I ran it
by a few people yesterday and they seemed to understand it well enough,
even if the design isn't fully fleshed out.

Whether or not we need funlink(2), though, remains to be seen.
I rather suspect we really don't.

Other things to consider:

Where does access(2) win over *stat(2)?  I don't understand that at all.
Is it because it saves the copyout into the (struct stat *)?  How
expensive is that in the grand scheme of things?

faccess(2) would be moot, wouldn't it, given fstat(2)?

How about flink(2), for an open fd?  Now, *THAT* could be useful for an
applicable filesystem object.  I see it most useful for error recovery.
Obviously it would not work for input streams, but for plain files, it
could be useful.  Of course, if you have said applicable fd open for reading,
it's probably just as easy to set up an open/write-while-read routine
to handle the same thing, essentially, but if you have an fd which is not
open for reading on a (S_IFREG) object which has somehow been completely
unlinked and all you have is the fd - provided, too, that you can arrange
a place to relink! - then you could do flink(fd, path); and be done.

Just a thought.



				--*greywolf;
--
NetBSD:  Don't login as root, use the su command.