3 ms·
> But its not concurrently accessed memory - unlike memory you often want filesystem operations to run asynchronously. Well, but it is. Files can be opened mul
by the8472 6y ago
> But its not concurrently accessed memory - unlike memory you often want filesystem operations to run asynchronously.
Well, but it is. Files can be opened multiple times and file descriptors can be shared between any number of processes and threads. mmap, atomics and msync also give you granular access.
Most people might not use it that way, but the thing is that it can be used that way. Just like RAM can be accessed randomly from many threads but higher-level languages limit what you're allowed to do concurrently. It's the same fast-but-unsafe-guts, use safe abstractions thing.
> I'm thinking about the 95% of applications out there which want to use the filesystem to save user data to disk
Those 95% of the applications aren't necessarily those doing 95% of the write IO though. Looking at the activity on my system then most of the write traffic is a) logging (including messaging) b) firefox occasioally showing 1GB/s places.sqlite spikes (hah) c) temporary files d) docker e) p2p storage.
For logging O_APPEND's atomicity promise may be good enough. I don't think text editors need transactions either, they only need file-level atomic replace which can be handled by a single library function. Such functions should be available in more libraries, I can agree with that.
> Why should the kernel maintain an API for this? Because the default, obvious way people use the filesystem should be correct.
Why the kernel and not libc? Or some other userspace lib for that matter.
> I'd be happy for an argument that the posix filesystem is too low level to be used to directly store user data.
That might be a matter of perspective. open/write/close is perfectly fine if all you do is move 100s of RAW photos from your SD card to your file server. There's no rewrite-in-place happening, it's a one-time thing that at worst would leave you with one incompletely copied file if the PC crashes shortly after copying. And the SD card wasn't a bastion of reliability anyway.
Docker layers and containers are quite discardable and I wouldn't even mind if they had 0 durability.
git, sqlite and postgres already seem to be doing the right thing.
Whether document processing software does, I don't know but I assume they put some effort into it with all their autosaving features. But, as mentioned above, all they really need is nicer standard libs not a new kernel API.
That doesn't leave that many things I deem critical.
Perhaps it is a little annoying if some of the configuration text files of various GUI applications get lost in a crash but on the other hand I wouldn't want them to fsync my preferences every time I tick a checkbox so I'd only want atomicity but not synchronous durability.
> - Most programmers don't even bother to use fsync. Anything which starts with "you can solve the trivial problem of saving a file in this super complex way" is a nonstarter and will almost never be used.
If people can't even be bothered to fsync then why would they be bothered to wrap IO into a transaction? After all APIs still would have to continue to work in non-transactional mode for performance and backwards-compatibility reasons so there would be no pressure on people to use transactions.
Maybe this also is a documentation problem since many developers don't seem to be aware of the non-durable-by-default behavior and different steps needed to get atomicity or durability. Man pages and standard libraries lack a high level overview of filesystem semantics. Some of it is noted in fsync() for example but not in rename()
- josephg 6y agoYeah if the current behaviour was well documented, and easy to use tooling existed in libc or something I’d be much happier. I think it could be optimized better in the kernel, but slow by default is better than wrong by default.
- the8472 6y agoPerhaps io_uring is a way forward. Today you can already batch a bunch of IO calls and chain them together so that the next is only excuted when the previous one succeeds. With some additional hints journaling and similar filesystems could try putting such a batch into a separate transaction group. That would give you some crash all-or-nothing behavior but no rollback on error. It would also be on a best-effort basis, might only support some systemcalls etc. Then the situation could be improved piece by piece.