@revk@torvalds Hmm does this already exist? I see in the flags for open(2) there's 'O_TMPFILE' - 'The pathname argument specifies a directory; an unnamed inode will be created in that directory's filesystem. Anything written to the resulting file will be lost when the last file descriptor is closed, unless the file is given a name.......linkat(2) can be used to link the temporary file into the filesystem, making it permanent,
@penguin42@revk@torvalds
Close but no cigar I think - in order to use O_TMPFILE then linkat() to /replace/ an existing file, the existing directory entry needs to be unlink()'d which makes this a non-atomic replacement. Might be enough for RevK's purpose though (avoiding half-baked files).
@revk@penguin42@phlash It does at least make things a little better: it means you can make the critical window (where, if you crash, you leave a temporary file lying around) tiny - by creating the directory entry then immediately rename it into place - rather than the winow including the entire time taken to generate the file's content.
@revk@torvalds you could do that with an fd-based (like fchmod instead od chmod) rename, perhaps? Create the file alongside the existing one with a .tmp suffix, immediately unlink, write at your leisure, then "rename" from the fd to the name. And that frename operation might be useful for other things too! Of course, it would be even better if there's a "create unlinked file on same filesystem as specified file, without even temporarily giving it a name" operation too...
@revk@torvalds I went and looked for an frename() in the spirit of fchmod(), believing the ...at() calls to all he about using an arbitrary directory fd as the cwd in order to support per-thread effective cwds, because that's what the man page said they were for...
@revk If I were to redesign #Unix from scratch, the actions of creating a file and adding it to a directory would be separate operations.
First you'd create the file, which would give you a FD referring to it. This would be the only reference to the file - just as you get today if you first create and then unlink a file.
Then you'd write to it.
Finally you'd add it to its containing directory, under the name you want it to have - atomically replacing any existing file which had that name.
@FenTiger@revk open(2) suggests you can already do something like this, on Linux. O_TMPFILE "creates an unnamed temporary file", and says it can be made permanent with linkat. Which presumably would be atomic in exactly the way you suggest.
O_TMPFILE requires a directory so it knows what filesystem to create an inode on.
@FenTiger@revk Of course if you want to write portable software, you don't get to use any of the cool APIs like this. Or need a fallback. (FreeBSD also has some neat APIs Linux doesn't have.)
@ids1024@FenTiger that is basically what I want and totally new to me. I’ll have to have a play with that! The need to close() differently on a crash goes away as you link as last thing you do. A crash before that closes and loses the file.
@revk@torvalds Uh, that may require a lot of buffering for the replacement file in the Linux file handling code, right? I know you are thinking of config files etc., but how would the code know what size the file will be?
@Miq@torvalds Not sure, the notion of making a file not in a directory already exists. All that needs "buffering" is the path name of them file to replace on close.
@revk It appears on all the current posts of yours. The reader is a hosted instance on Miniflux that doesn't appear to be doing it with other feeds, only yours. I'll see if I can dig further.
Add comment