I am dealing with a situation where I want to save state persistently for an application that has many processes and many threads within those processes. Normally this would require a heavy use of locking to ensure that there are no conflicts.

I wish to avoid this by saving the data into a file with the O_APPEND mode. This way as long as I ensure that the data is <4KiB writes to the file will be atomic. If I make use of append only data structures then I have a lock free solution.

However in order for this to work I need to know the location of the data within the file after I have written to that file. The problem that I am running into is that I am unable to find a system call that writes into a file and then tells me the offset within that file that was written to.

I can use a write followed by a seek to discover this location. However this is not safe if another thread is sharing the same file descriptor so would require me to protect the write with a mutex which goes against my efforts to avoid locks.

Examining the man pages for write, writev, pwrite and prwritev has not shown anything that would carry out a write and then tell me the offset after the write as a single systems call and I'm fully aware that there may not be. Have I over looked something?

  • 1
    Do ypu have any base for the claim that writes < 4k will be atomic? afaik only pipes have such a minimum atomic write guarantee. Anyways, 1) O_APPEND doesn't work right on nfs 2) on linux, the splice() and copy_file_range() syscalls have an interface as you describe, but they take input from another file, not from a buffer.
    – user313992
    May 29, 2019 at 8:45
  • It would be interesting to know though why locking is so bad and should be avoided at all costs. It's just 2 extra syscalls.
    – user313992
    May 29, 2019 at 8:52
  • I'm basing the claim on a great deal of testing. And yes O_APPEND doesn't work right on nfs, along with almost everything else :). May 29, 2019 at 10:56
  • 1
    That is hardly convincing. And nfs is just fine. There is lot a difference between writing something that you're going to force upon other people (where that would be completely unacceptable), or a personal project where getting it over the finish line and getting the results that you want is more than satisfactory. But in the latter case I would just create a huge sparse file via truncate(), mmap it, and "write" to it with memcpy (synchronized via mutexes, of course).
    – user313992
    May 29, 2019 at 12:10
  • This is slightly an appeal to authority but Linus think o_append should work that way yarchive.net/comp/linux/wakekill.html . Your mention of copy_file_range has given me an idea. Create a in memory file as a buffer. Then copy from that file into the append file. May 29, 2019 at 23:25


You must log in to answer this question.

Browse other questions tagged .