LWN: Comments on "Fast commits for ext4" https://lwn.net/Articles/842385/ This is a special feed containing comments posted to the individual LWN article titled "Fast commits for ext4". en-us Sat, 30 Aug 2025 06:07:33 +0000 Sat, 30 Aug 2025 06:07:33 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net What about other filesystems? https://lwn.net/Articles/864183/ https://lwn.net/Articles/864183/ andresfreund <div class="FormattedComment"> &gt; The OS/FS aren&#x27;t magic.<br> <p> In particular they have no reliable way of knowing which files (or even parts of files) are related and need constrained ordering between writes, and which are unrelated and thus can handled independently. <br> </div> Fri, 23 Jul 2021 18:01:28 +0000 What about other filesystems? https://lwn.net/Articles/864181/ https://lwn.net/Articles/864181/ andresfreund <div class="FormattedComment"> You can trust the data if you tell the OS you want to pay the price (use fsync, or O_SYNC/O_DSYNC) and you only rely on data known to be flushed after a crash.<br> <p> The alternative you&#x27;re proposing basically implies that writes cannot be buffered for any meaningful amount of time. Oh, your browser updated it&#x27;s history database? Let&#x27;s just make that wait for all temporary files being written out, the file being copied concurrently, etc. And what&#x27;s worse, do not allow any concurrent sync writes to finish (like file creation), because that would violate ordering.<br> <p> Ext3&#x27;s ordering guarantees were weaker and yet lead to horrible stalls all the time. There constantly were complaints about Firefox&#x27;s SQLite databases stalling the system etc.<br> <p> The OS/FS aren&#x27;t magic.<br> </div> Fri, 23 Jul 2021 17:55:49 +0000 What about other filesystems? https://lwn.net/Articles/864167/ https://lwn.net/Articles/864167/ andresfreund <div class="FormattedComment"> <font class="QuotedText">&gt; Do an fsync on the user-space journal. </font><br> <p> With a small bit of care fdatasync() should be enough, and will often be a lot faster (no synchronous updating of unimportant filesystem metadata like mtime, turning a single write into multiple).<br> <p> <font class="QuotedText">&gt; Anything else will not work and has never worked. Ok, especially if you are developing databases, O_DIRECT might be a viable alternative.</font><br> <p> O_DIRECT on its own does not remove the need for an fsync/fdatasync. Devices have volatile write caches, and they do loose data on power loss/reset. O_DIRECT alone only avoids issues with the OS write cache. And makes the f[data]sync cheaper, because it will often only have to send a cache flush (and transparently avoid that on devices without volatile write caches).<br> <p> Alternatively it can be combined with O_DSYNC to achieve actually durable writes - but if one isn&#x27;t careful that can tank throughput. It either adds the FUA flag to each write or does separate sync commands after each write, which can end up being more cache flushes for a workload. It can be significantly faster to do a series of writes and then a single cache flush.<br> <p> It&#x27;s hardware dependant too whether FUA or separate cache flush commands are faster :(. Dear Samsung, please fix your drives.<br> <p> My testing says that on most NVMe devices with a volatile cache DSYNC wins if the queue depth is very low and latency is king (only one roundtrip needed). fdatasync wins if there&#x27;s more than a few writes happening at once, especially if all/most need to complete before the &quot;user transaction&quot; finishes - the lower number of flushes saves more than the additional roundtrip costs.<br> <p> <font class="QuotedText">&gt; Actually database developers are probably among the first to scream in terror if a filesystem will guarantee strong ordering properties because of the immense performance penalties, which they do not want to buy.</font><br> <p> Indeed! And there&#x27;s no realistic way the FS can do better. <br> </div> Fri, 23 Jul 2021 17:43:35 +0000 What about other filesystems? https://lwn.net/Articles/864076/ https://lwn.net/Articles/864076/ Defenestrator <div class="FormattedComment"> <font class="QuotedText">&gt; And I think it is guaranteed that a rename only is done after the renamed file has hit the disk.</font><br> <p> This is often true in practice (in particular, in ext3 and in ext4 outside of early versions), but not always explicitly guaranteed. See the auto_da_alloc option added to ext4 for more info and background.<br> </div> Fri, 23 Jul 2021 13:10:08 +0000 Fast commits for ext4 https://lwn.net/Articles/845388/ https://lwn.net/Articles/845388/ mrybczyn <div class="FormattedComment"> Thank you for the comment, Jan. We&#x27;ve clarified the sentence.<br> </div> Mon, 08 Feb 2021 15:58:56 +0000 What about other filesystems? https://lwn.net/Articles/844689/ https://lwn.net/Articles/844689/ drjohnnyfever <div class="FormattedComment"> The situation on FreeBSD is actually a bit complicated. The current default configuration uses journaled soft updates (su+j) which work like traditional soft updates with the exception that there is enough metadata journaled to avoid having to run a background fsck to reclaim space from orphaned allocations. <br> <p> FreeBSD also supports proper journaling (logging) with gjournal which works at the block layer rather than in UFS itself. If I recall correctly, gjournal keeps a proper intent log of disk writes rather than just a metadata journal. It also allows you to use a separate device for the log.<br> <p> ZFS does seem to be the way forward on FreeBSD but Netflix is pretty big consumer of UFS/FFS so they have been sponsoring continued development.<br> </div> Mon, 01 Feb 2021 14:25:32 +0000 PostgreSQL might benefit from a fd-list fsync() API https://lwn.net/Articles/843509/ https://lwn.net/Articles/843509/ ringerc <div class="FormattedComment"> Yes. PostgreSQL may have many dirty FDs. Each tables or index is stored as separate file, and split into 1GB extents. I imagine that the extent splitting could be changed if there&#x27;s a benefit to doing so, but the separate files per relation not so much.<br> </div> Fri, 22 Jan 2021 01:15:37 +0000 What about other filesystems? https://lwn.net/Articles/843471/ https://lwn.net/Articles/843471/ mstone_ <div class="FormattedComment"> Yeah, the confusion here comes from comparing the current state of affairs to a past state that didn&#x27;t exist.<br> </div> Thu, 21 Jan 2021 19:42:43 +0000 What about other filesystems? https://lwn.net/Articles/843272/ https://lwn.net/Articles/843272/ anton <blockquote>All this talk about "apps should use fsync" or "apps should use fsfsync" fills me with horror, as someone who wants to write a system that relies on data integrity. Are you telling me that my app needs to be filesystem-aware, and not only that but aware of what mount options were used, so I know which commands to call to make sure that my data is safe?</blockquote> I think that the Ted Ts'o position is that you should use fsync a lot, independent of the file system; and that you should not just use it on the file you were working on, but possibly on other files; he explicitly mentions the directory that contains the file, but my expectation is that it might also affect other files, depending on the file system. E.g., some file systems have a file that contains the inodes, so why not require that the application also fsyncs that? <p>My position is pretty much the opposite: A good file system should provide decent consistency guarantees in case of an OS crash or power outage (which, BTW, is not covered by POSIX, so any claim by Ted Ts'o that POSIX requires applications to use fsync the way he likes is nonsense). And these consistency guarantees should orient themselves on the guarantees that file systems give in the non-crash case. This is the usual case, which is what programmers develop for and test against; so even if Ted Ts'o's file systems would guarantee to corrupt all non-fsynced data in case of a crash, it is unlikely that all applications would contain so many fsyncs that Ted Ts'o would not blame them on data loss. <p>Given that POSIX guarantees sequential consistency for file system operations in the non-crash case, my take is that file systems should guarantee a sequential consistent state in case of a crash; but for performance reasons, not the state at the time of the crash. You can use sync whenever you want the crash state to be consistent with the logical state, e.g., before reporting the completion of a transaction over the network. <p>Unfortunately, there is only one file system in Linux that gives such a guarantee last I looked (NILFS2), but that's because we let Linux get away with file systems that don't give such guarantees; admittedly Linux crashes so rarely these days and at least around here power outages are so rare that the itch is small. <p>Concerning whether apps should be file system aware, my take is that you should program for a filesystem that gives good guarantees, and recommend that the user should not be using other file systems (I have certainly avoided any file system maintained by Ted Ts'o since the O_PONIES discussion). Or, if you feel like accomodating bad file systems, have a flag for the application that insert an fsync of the file and its directory after every change of the file (that may satisfy Ted Ts'o for now); the user can use that flag when using a bad file system. <p>Concerning efficiency, this can be implemented efficiently, by writing the changes (data blocks and/or journal entries) to free blocks in arbitrary order, then a write barrier, then a root block that allows finding all this stuff, and once that root block reaches the platter, the recovery code will find everything. This does not even require any synchronous operation in principle, so it could be very efficient (in practice, I think that the barrier operations on existing drives are synchronous). <p>Concerning lying hardware: If the hardware lies, all the fsyncs that Ted Ts'o asks for will not help you. Just as we need file systems with decent guarantees, we need honest hardware. And I expect it exists, because otherwise database servers would be unable to guarentee consistency after crashes. Wed, 20 Jan 2021 18:51:14 +0000 What about other filesystems? https://lwn.net/Articles/843269/ https://lwn.net/Articles/843269/ anton <blockquote>Oh - and wasn't advice about how to shut a system down always "# sync; sync; sync; halt"?</blockquote> No, the advice was to type <pre> sync sync sync halt </pre> That's because sync did not block (unlike on Linux), so the time you needed to type the additional syncs and the halt was needed to finish the sync. Wed, 20 Jan 2021 17:44:42 +0000 Fast commits for ext4 https://lwn.net/Articles/843198/ https://lwn.net/Articles/843198/ viiru <div class="FormattedComment"> <font class="QuotedText">&gt; What does the system call do in other filesystems?</font><br> <p> <font class="QuotedText">&gt; If it&#x27;s an ext4 quirk then any software relying on that would already break just by virtue of moving to a </font><br> <font class="QuotedText">&gt; different filesystem.</font><br> <p> In my understanding that is exactly what it is. Ext3 shares the behavior, but for example XFS does not. This caught many application developers by surprise, but that happened a couple of decades ago and has most likely been fixed in any sensible application.<br> </div> Wed, 20 Jan 2021 07:48:21 +0000 PostgreSQL might benefit from a fd-list fsync() API https://lwn.net/Articles/843113/ https://lwn.net/Articles/843113/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Note that Pg can&#x27;t use FS-level write-order barriers after each WAL record written. It&#x27;d eliminate the latency after each fsync(), but would be grossly inefficient for this because it&#x27;d prevent reordering of non-WAL writes across barriers, and we want the FS to be free to reorder non-WAL writes as aggressively as possible (up to the next checkpoint) in order to do write combining and write deduplication.</font><br> <p> Does PG often spend time io-bound? How important really is &quot;as efficient as possible&quot; disk io?<br> <p> I would have thought this issue would actually impact me even more, given that traditionally Pick has always been &quot;don&#x27;t bother with caching, it&#x27;s faster to retrieve it from disk&quot; and Pick can also really hammer the disk.<br> <p> Cheers,<br> Wol<br> </div> Tue, 19 Jan 2021 14:55:29 +0000 PostgreSQL might benefit from a fd-list fsync() API https://lwn.net/Articles/843112/ https://lwn.net/Articles/843112/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Finally, for checkpoints PostgreSQL must fsync() all the dirty files it has open. This will force all pending writes on those files to disk, not just the writes made before the current checkpoint target position. On most Linux FSes it also flushes a bunch of other irrelevant and uninteresting files that don&#x27;t need to be durable at all.</font><br> <p> Does PG tend to have a lot of these (dirty files)? Because Pick, the database I&#x27;m thinking of, typically stores a single &quot;table&quot; in one OR MORE os files, so I could have a *lot* of dirty files open ...<br> <p> Although of course, like PG, the main thing I&#x27;m concerned about is knowing that the journal is flushed ...<br> <p> Cheers,<br> Wol<br> </div> Tue, 19 Jan 2021 14:51:28 +0000 Fast commits for ext4 https://lwn.net/Articles/843106/ https://lwn.net/Articles/843106/ jan.kara <div class="FormattedComment"> <font class="QuotedText">&gt; In the default data=ordered mode, where the journal entry is written only after flushing all pending data, delayed allocation might thus delay the writing of the &gt; journal. </font><br> <p> This is actually not quite correct. Delayed allocation just means that write(2) stores data in the page cache without actually allocating blocks on disk. This also means that the journalling machinery is completely ignorant of the write at this moment. Later, when VM decides to write out dirty pages from the page cache, filesystem allocates blocks for the pages and it is only at this point that there are filesystem metadata changes that are journalled. So it isn&#x27;t true that &quot;delayed allocation may delay writing of the journal&quot;.<br> </div> Tue, 19 Jan 2021 14:24:57 +0000 Fast commits for ext4 https://lwn.net/Articles/843100/ https://lwn.net/Articles/843100/ LtWorf <div class="FormattedComment"> What does the system call do in other filesystems?<br> <p> If it&#x27;s an ext4 quirk then any software relying on that would already break just by virtue of moving to a different filesystem.<br> </div> Tue, 19 Jan 2021 08:15:01 +0000 PostgreSQL might benefit from a fd-list fsync() API https://lwn.net/Articles/843097/ https://lwn.net/Articles/843097/ ringerc <div class="FormattedComment"> I think PostgreSQL might benefit significantly from a fsync() variant that takes a fd-list. Though the project is considering moving to syncfs() on Linux. It generally only cares about flushes to many files when it&#x27;s doing checkpoints, and ordering of individual flushes isn&#x27;t important for those. <br> <p> Pg has three major write/flush order requirements.<br> <p> 1. For WAL (its journal): WAL record writes must be flushed to disk strictly in ascending byte order in the WAL files. Not all WAL record writes must be immediately durable, but all writes prior to a durable record like a commit must complete before the durable record is flushed. PostgreSQL uses either O_DATASYNC or fdatasync() to ensure this.<br> <p> 2. Ordering of non-WAL writes with respect to their corresponding WAL record writes. Non-WAL writes such as heap pages, index pages, clog (commit state) must not be flushed to disk until the corresponding WAL writes are known to be durable. To do this, PostgreSQL buffers the data to be written in its own shared memory, delaying any write() to the OS until it knows the WAL for these writes is durable. This causes significant double-buffering waste and write latency.<br> <p> 3. Checkpoint WAL segment removal vs non-WAL writes. PostgreSQL must know that all non-WAL writes corresponding to WAL records up to a given point in the WAL are durably on disk before it removes or overwrites a WAL segment (file). PostgreSQL does this by remembering each file descriptor that was touched since the last checkpoint and fsync()ing it before removing any WAL segments.<br> <p> If this sounds inefficient to you, that&#x27;s because it is.<br> <p> The O_DATASYNC or fdatasync() after many WAL record writes can limit overall throughput of sync-sensitive writes like commit records, especially since sometimes a large volume of less critical records must be flushed before the critical record is durably flushed. WAL writing spends a lot of time waiting because there&#x27;s no API that lets us pipeline or queue up fsync()s in a non-blocking manner - except possibly helper threads for blocking calls, and they cause plenty of other issues.<br> <p> For non-WAL (heap) writes, PostgreSQL has to tie up memory for its pending writes until it knows the OS has flushed the corresponding WAL writes. Only then can it write() them, because it has no way to tell the OS that they must not hit disk before the corresponding WAL records are durable. That means it has to buffer them for longer, and double handle the writes.<br> <p> Finally, for checkpoints PostgreSQL must fsync() all the dirty files it has open. This will force all pending writes on those files to disk, not just the writes made before the current checkpoint target position. On most Linux FSes it also flushes a bunch of other irrelevant and uninteresting files that don&#x27;t need to be durable at all.<br> <p> What I&#x27;d really like to have is a way to tell the FS about write-order dependencies when PostgreSQL issues a write().<br> <p> Postgres would request a tag for each WAL record write, and then tag each write that depends on that WAL record with an ordering requirement against that WAL write tag. Then if WAL ordering was critical for a given WAL write it&#x27;d tag the next WAL write with an ordering requirement against the previous critical WAL write. So the OS would be free to write in natural order:<br> <p> * WAL record A<br> * Heap changes for A<br> * WAL record B<br> * Heap changes for B<br> <p> or reorder:<br> <p> * WAL record A<br> * WAL record B<br> * Heap changes for A and B in any combination<br> <p> but could not write heap changes for A before WAL A, or heap changes for B before WAL B if postgres specified the A before B write-order requirement.<br> <p> That&#x27;d let Pg just write everything to the OS without blocking on fsync() etc, and let the kernel&#x27;s dirty writeback and VFS/block layer sort out the ordering.<br> <p> Basically a kind of AIO with the ability to impose write ordering requirements and with a sensible interface for confirming data is durably flushed. The latter is woefully lacking in any current AIO facilities.<br> <p> It&#x27;d be necessary to guarantee that any read of a file with pending writes always returned the latest data that&#x27;s pending writeback. Otherwise Pg would have to pin each dirty buffer in its own buffer cache until it knew it was flushed by the OS anyway.<br> <p> I hope that the recent blk-mq work may well benefit PostgreSQL if the needed balance between permitting reordering and imposing necessary write-order constraints proves to be possible. <br> <p> Note that Pg can&#x27;t use FS-level write-order barriers after each WAL record written. It&#x27;d eliminate the latency after each fsync(), but would be grossly inefficient for this because it&#x27;d prevent reordering of non-WAL writes across barriers, and we want the FS to be free to reorder non-WAL writes as aggressively as possible (up to the next checkpoint) in order to do write combining and write deduplication.<br> </div> Tue, 19 Jan 2021 04:36:35 +0000 Fast commits for ext4 https://lwn.net/Articles/843084/ https://lwn.net/Articles/843084/ tytso <div class="FormattedComment"> So for decades, competently written text editors write new precious files, such as source files via:<br> <p> 1) Write the new contents of foo.c to foo.c.new<br> 2) Fsync foo.c.new --- check the error return from the fsync(2) as well as the close(2)<br> 3) Delete foo.c.bak<br> 4) Create a hard link from foo.c to foo.c.bak<br> 5) Rename foo.c.new on top of foo.c<br> <p> This doesn&#x27;t require an fsync of the directory, but it guarantees that /path/to/foo.c will either have the original contents of foo.c., or the new contents of foo.c, even if there is a crash any time during the above process. If you want portability to other Posix operating systems, including people running, say, retro versions of BSD 4.3, this is what you should do. It&#x27;s what emacs and vi does, and some of the &quot;ritual&quot;, such as making sure you check the error return from close(2), is because other wise you might lose data if you run into a quota overrun on the Andrew File System (the distributed file system developed at CMU, and used at MIT Project Athena, as well as several National Labs and financial institutions).<br> <p> That being said, rename is not a write barrier, but as part of the O_PONIES discussion, on a close(2) of an open which was opened with O_TRUNC, or on a rename(2) where the destination file is getting overwritten, the file being closed, or the source file of the rename will have an immediate write-out initiated. It&#x27;s not going to block the rename(2) operation from returning, but it narrows the race window from 30 seconds to however long it takes to accomplish the writeout, which is typically less than a second. It&#x27;s also something that was implemented informally by all of the major file systems at the time of the O_PONIES controversy, but it doesn&#x27;t necessarily account for what newer file systems (for example, like bcachefs and f2fs) might decide to do, and of course, this is not applicable for what other operating systems such as MacOS might be doing.<br> <p> The compromise is something that was designed to minimize performance impact, since users and applications also depend upon --- and get cranky --- when there are performance regressions, while still papering over most of the problems caused by careless application. From file system developers&#x27; perspective, the ultimate responsibility is on application writers if they think a particular file write is precious and must lost be lost after a system or application crash. After all, if the application is doing something really stupid, such as overwriting a precious file by using open(2) with O_TRUNC, because it&#x27;s too much of a pain to copy over ACL&#x27;s and extended attributes, so it&#x27;s simpler to just use O_TRUNC and overwrite the data file and crossing your fingers. There is absolutely no way the file system can protect against application writer stupidity, but we can try to minimize the risk of damage, while not penalizing the performance of applications which are doing the right thing, and are writing, say, a scratch file.<br> <p> <p> <p> </div> Mon, 18 Jan 2021 19:24:38 +0000 What about other filesystems? https://lwn.net/Articles/843076/ https://lwn.net/Articles/843076/ hkario <div class="FormattedComment"> precisely, the issue is not that hardware can fail and that the file system can&#x27;t promise anything in such case, the problem is that there is no specification common _to all file systems_ that says what is expected to happen under such and such scenarios<br> <p> or to put it other way round: every file system will exhibit different behaviour on power failure and every file system requires slightly different handling to get something you can reasonably expect (like, when the file system says it committed data to disk, the data is committed to disk)<br> <p> that&#x27;s no way to program stuff when dealing with such fundamental thing in computing as data storage<br> </div> Mon, 18 Jan 2021 17:47:40 +0000 What about other filesystems? https://lwn.net/Articles/843071/ https://lwn.net/Articles/843071/ smoogen <div class="FormattedComment"> From reading from your other posts on this, I think you also have to be aware of what the hardware the system has in it if you want that level of guarantee. There are large number of hardware pieces who for the sake of speed fool the OS into saying stuff was written but wasn&#x27;t. You can fsync(), sync(), and all otehr things and the hardware will write stuff in the order it wants. And yes like bufferbloat it is built into all parts of modern hardware from the cache on the harddrive, to the controller of the harddrive to the PCI bus the controller is connected to the memory subsystem. <br> <p> In the end for a lot of hardware you just have to throw away guarenteeing a lot of things because the entire industry has agreed to lie in order to give the feeling of speed. To get around this you start having to move back to Real Time hardware which is much slower (less smart caches which could break RT guarantees) but more predictable. Not the answer you probably want to hear.. but I think a good reason the kernel people don&#x27;t see the lies as a problem any more is that finding hardware post 2004 which doesn&#x27;t lie in someway to its calling system is rare. <br> </div> Mon, 18 Jan 2021 17:05:52 +0000 What about other filesystems? https://lwn.net/Articles/842956/ https://lwn.net/Articles/842956/ pbonzini <div class="FormattedComment"> <font class="QuotedText">&gt; AND YOU CAN&#x27;T EVEN RELY ON JOURNALLING because you don&#x27;t know whether the file system has written the journal before, after, or in the middle of writing the data.</font><br> <p> The filesystem is going to write data before metadata, so that you won&#x27;t have a file that&#x27;s full of zeros (or worse, full of stale data including another user&#x27;s cleartext password). With &quot;old Unix&quot; you could get a file that&#x27;s full of trash after a power failure; I sure did. So if anything journalling makes things better.<br> </div> Mon, 18 Jan 2021 13:05:00 +0000 What about other filesystems? https://lwn.net/Articles/842954/ https://lwn.net/Articles/842954/ farnz <p><tt>io_uring</tt> does provide the primitives needed; there's <tt>IORING_OP_FSYNC</tt> (with <tt>IORING_FSYNC_DATASYNC</tt> to weaken from fsync to fdatasync) and <tt>IORING_OP_SYNC_FILE_RANGE</tt> for flushing caches asynchronously, and the <tt>IOSQE_IO_DRAIN</tt> and <tt>IOSQE_IO_LINK</tt> flags to order <tt>io_uring</tt> operations with respect to each other so that you can issue the fsync after all the related writes have been done. Mon, 18 Jan 2021 10:45:18 +0000 What about other filesystems? https://lwn.net/Articles/842953/ https://lwn.net/Articles/842953/ farnz <p>No, because even on ancient systems, you had elevator reordering for performance, and no guarantees about metadata writes; in the event of a crash, you simply did not know the state of the update or the transaction log, as even if you wrote them in a careful order, the elevator could reorder writes to disk, and the metadata writes might be reordered, too. <p>In other words, as soon as there's a kernel panic or a power failure, all bets are off on an old UNIX system. This wasn't an issue with reliable systems, but as reliability went down (no dedicated power supplies, no UPSes etc), it became an issue again. Mon, 18 Jan 2021 10:29:39 +0000 What about other filesystems? https://lwn.net/Articles/842949/ https://lwn.net/Articles/842949/ NYKevin <div class="FormattedComment"> Well, you can also use aio_fsync(3), but that&#x27;s basically just a crappier version of &quot;use a thread pool.&quot;<br> <p> IMHO this is a broader issue with aio(7) and not a problem with fsync in particular.<br> </div> Mon, 18 Jan 2021 07:16:42 +0000 What about other filesystems? https://lwn.net/Articles/842948/ https://lwn.net/Articles/842948/ joib <div class="FormattedComment"> I believe io_uring supports fsync, so that would be a way to do an asynchronous fsync on somewhat modern Linux.<br> </div> Mon, 18 Jan 2021 05:34:39 +0000 What about other filesystems? https://lwn.net/Articles/842941/ https://lwn.net/Articles/842941/ NYKevin <div class="FormattedComment"> The process that SQLite uses is documented in <a href="https://sqlite.org/atomiccommit.html">https://sqlite.org/atomiccommit.html</a> in a very high level of detail.<br> <p> TL;DR: They make a copy (&quot;rollback journal&quot;) of the data they are about to overwrite, fsync that copy, overwrite the data, fsync the database itself, and finally delete the rollback journal.<br> </div> Sun, 17 Jan 2021 22:13:36 +0000 What about other filesystems? https://lwn.net/Articles/842939/ https://lwn.net/Articles/842939/ Wol <div class="FormattedComment"> mmmm<br> <p> The risk of a corrupted filesystem hasn&#x27;t changed.<br> <p> But if the application writes a journal before doing an update, then provided there&#x27;s no collateral damage it can recover from a crash mid transaction on an old unix system.<br> <p> On a new system, it can&#x27;t be sure whether the transaction log is okay and the update is damaged, or the transaction log is damaged and the transaction is lost, or even worse the transaction log is damaged and the transaction is partially complete!<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 21:23:48 +0000 What about other filesystems? https://lwn.net/Articles/842938/ https://lwn.net/Articles/842938/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Actually database developers are probably among the first to scream in terror if a filesystem will guarantee strong ordering properties</font><br> <p> I did say the *appearance* of strong ordering guarantees :-)<br> <p> <font class="QuotedText">&gt; If the filesystem gets corrupted, then all user data is lost, so indeed the journal is there to protect the data.</font><br> <p> But if the data in flight is corrupted, then the only way to get the system back to a sane (for the user) state may be &quot;format, recover backup&quot;. Yes making sure the filesystem is itself consistent is important but it&#x27;s only part of the picture. If I can&#x27;t trust the state of the data, I need to recover from backup.<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 21:18:25 +0000 What about other filesystems? https://lwn.net/Articles/842937/ https://lwn.net/Articles/842937/ matthias <div class="FormattedComment"> <font class="QuotedText">&gt;&gt; Actually this was very well what could happen and still can happen with non-journaling filesystems. Plugging the power-cord in the wrong moment and you have a broken filesystem that cannot not be mounted. With a bit of luck you can get your files back with fsck. Fortunately, the situation improved. In a journaling filesystem you should in any way only loose data in modification.</font><br> <p> <font class="QuotedText">&gt;And this is pretty much the perfect example of what is wrong with the current setup. The filesystem journal is there to protect the filesystem, to hell with the user&#x27;s data. </font><br> <p> If the filesystem gets corrupted, then all user data is lost, so indeed the journal is there to protect the data.<br> <p> <font class="QuotedText">&gt;So HOW as a database developer am I supposed to protect my database (other than writing to a raw partition!) if I can&#x27;t trust the filesystem to protect my user-space journal!</font><br> <p> You can trust it. Do an fsync on the user-space journal. Anything else will not work and has never worked. Ok, especially if you are developing databases, O_DIRECT might be a viable alternative. And writing to a raw partition also does not guarantee that the writes are in order. You still have to flush the cashes to ensure that something actually has hit the disk, or use synchronous IO from the beginning.<br> <p> <font class="QuotedText">&gt;That&#x27;s why ext3 journal=&quot;ordered&quot; was so good - it gave the APPLICATION DEVELOPERS the guarantee that, after a crash, writes *appeared* to have been written to disk in the order that they were made. That&#x27;s ALL a developer needs!</font><br> <p> This is clearly wrong. data=ordered only ensures that data is written before related meta-data. Writes to different files are not guaranteed to be ordered. Overwriting a file is not guaranteed to be ordered. The blocks can hit the disk in a random order. The things that are guaranteed by data=ordered is that when appending a file the new data hits the disk before the new blocks are added to the inode, i.e., it is not possible that the file contains garbage instead of the new data. And I think it is guaranteed that a rename only is done after the renamed file has hit the disk. This of course helps for those people that update data by the create new file, rename model. But there is not much that really helps for databases.<br> <p> <font class="QuotedText">&gt;(Oh, and I don&#x27;t think my work on raid would help that, even if raid could provide those guarantees which I hope it can, that an application could rely on it unless the filesystem ALSO provided those guarantees.)</font><br> <p> The work on raid is essential, as of course all layers below the filesystem have to provide certain data safety features. Especially the filesystem requires some kind of transactional semantics for its own journal.<br> <p> Best,<br> Matthias<br> <p> P.S.: Actually database developers are probably among the first to scream in terror if a filesystem will guarantee strong ordering properties because of the immense performance penalties, which they do not want to buy. At least the big systems know pretty well which data has which ordering requirements, which data should be in memory cache or will likely not be used again soon and want to control all these aspects themselves. If they do not use a raw partition from the beginning, they will just use the filesystem to reserve a bunch of blocks and then use synchronous IO.<br> </div> Sun, 17 Jan 2021 21:03:20 +0000 What about other filesystems? https://lwn.net/Articles/842936/ https://lwn.net/Articles/842936/ matthias <div class="FormattedComment"> <font class="QuotedText">&gt;&gt; Taking code that didn&#x27;t require fsync (because it didn&#x27;t (sic) exist) and, in the words of zlynx, saying that &quot;it&#x27;s broken&quot; makes all ISO C code that needs data safety broken, which seems extreme.</font><br> <font class="QuotedText">&gt;Actually, I think that&#x27;s called a regression, is it not? And one of Linus&#x27; absolute rules is &quot;no regressions&quot;, isn&#x27;t it?</font><br> There is no regression. The code works as good as back in the days. Back in the days it was clear, that the data is only safe is the system is working properly, including no power outages. If you make sure that your system never crashes, the old code will work fine. If the system crashes, the old code might loose data, but this was always the case with this code. If you want additional guarantees (like no data loss in case of power loss), you have to use fsync. <br> <p> Best,<br> Matthias<br> </div> Sun, 17 Jan 2021 20:31:46 +0000 What about other filesystems? https://lwn.net/Articles/842935/ https://lwn.net/Articles/842935/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Actually this was very well what could happen and still can happen with non-journaling filesystems. Plugging the power-cord in the wrong moment and you have a broken filesystem that cannot not be mounted. With a bit of luck you can get your files back with fsck. Fortunately, the situation improved. In a journaling filesystem you should in any way only loose data in modification.</font><br> <p> And this is pretty much the perfect example of what is wrong with the current setup. The filesystem journal is there to protect the filesystem, to hell with the user&#x27;s data. So HOW as a database developer am I supposed to protect my database (other than writing to a raw partition!) if I can&#x27;t trust the filesystem to protect my user-space journal!<br> <p> That&#x27;s why ext3 journal=&quot;ordered&quot; was so good - it gave the APPLICATION DEVELOPERS the guarantee that, after a crash, writes *appeared* to have been written to disk in the order that they were made. That&#x27;s ALL a developer needs!<br> <p> (Oh, and I don&#x27;t think my work on raid would help that, even if raid could provide those guarantees which I hope it can, that an application could rely on it unless the filesystem ALSO provided those guarantees.)<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 17:58:39 +0000 What about other filesystems? https://lwn.net/Articles/842934/ https://lwn.net/Articles/842934/ Wol <div class="FormattedComment"> What I find hard to understand is, if the database (SQLite, whatever) is using linux syscalls, how does it know the data has actually been written? Or does it do loads of sync()s, and then pause all writes for ten seconds or so waiting for the data to flush, etc etc.<br> <p> I can see how databases can provide 99.999% reliability. I&#x27;m active on the raid list. I know all about disk timeouts, disks lying, how long things take to get flushed, etc etc. I simply do not see how an application can guarantee safety.<br> <p> As for &quot;why should it be in the kernel&quot; - because LOTS of developers will benefit from the ability to reason about the state of a system in a crash scenario. Why should all the database developers be forced to duplicate each others&#x27; work?<br> <p> And frankly, if I commit something to the filesystem for saving, surely I should be able to ask the filesystem &quot;have you saved it?&quot; AND BE ABLE TO RELY ON THE ANSWER! (Yep, I know disks lie, and I don&#x27;t expect the file system necessarily to deal with that, but it really should be held responsible for its own actions!)<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 17:40:18 +0000 What about other filesystems? https://lwn.net/Articles/842933/ https://lwn.net/Articles/842933/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Taking code that didn&#x27;t require fsync (because it didn&#x27;t (sic) exist) and, in the words of zlynx, saying that &quot;it&#x27;s broken&quot; makes all ISO C code that needs data safety broken, which seems extreme.</font><br> <p> Actually, I think that&#x27;s called a regression, is it not? And one of Linus&#x27; absolute rules is &quot;no regressions&quot;, isn&#x27;t it?<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 17:28:33 +0000 What about other filesystems? https://lwn.net/Articles/842931/ https://lwn.net/Articles/842931/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; 2. I did not claim that old code was &quot;broken,&quot; merely that it was at risk of losing data. My point is that both the application developer and the sysadmin would have been aware of that problem, and would take appropriate steps to remediate it (such as making regular backups, building a RAID, or whatever else makes sense). Everyone should still be taking those steps today, because as you say, nothing is 100% reliable.</font><br> <p> RAID is useless if it can&#x27;t guarantee that stuff has been safely saved to disk ... which it can&#x27;t if the linux layers provide no guarantees ...<br> <p> Backups are pretty much useless BY DEFINITION, because if the data is corrupted while saving to disk (which is what we&#x27;re discussing here), then it&#x27;s not been around long enough to be saved to backup.<br> <p> Come on, all I&#x27;m asking for is the ABILITY TO REASON about what is happening, so I can provide my own guarantees. &quot;The system may or may not have saved this data in the event of a crash&quot; is merely the filesystem guys saying &quot;not our problem&quot;, and the references to the SQLite guys jumping through hoops to make certain is the perfect example of them having to do somebody else&#x27;s job, because surely it&#x27;s the filesystem&#x27;s guys&#x27; job to make sure that data entrusted to the filesystem is actually safely saved by the filesystem.<br> <p> If I can have some guarantee that &quot;this data is saved before that data starts to be written&quot;, then at least I can reason about it.<br> <p> And yes, I know making all filesystems provide these sort of guarantees may be fun - I&#x27;m on the raid mailing list - I know - because I read all the messages and glance at all the patches and all that stuff (and don&#x27;t understand much of it :-) - but when (I know, I know) I find the time to start really digging in to it, I want the raid layer to provide exactly those guarantees.<br> <p> And why can&#x27;t we say &quot;these are the guarantees we *intend* to provide&quot;, and make it a requirement that anything new *does* provide them! If I provide a &quot;flush&quot; in the raid code, I can then pass it on to the next layer down, and then when it says it&#x27;s done it I can then pass success back up (or E_NOTSUPPORTED if I can&#x27;t pass it down). But this is exactly another of those *new* things they&#x27;re trying to get into the linux block layer, isn&#x27;t it - the ability to pass error codes back to the caller other than the most basic of &quot;succeeded&quot; or &quot;failed&quot;, isn&#x27;t it? If they can get that in, surely they can get my &quot;flush&quot; in, can&#x27;t they?<br> <p> Cheers,<br> Wol<br> </div> Sun, 17 Jan 2021 17:25:08 +0000 What about other filesystems? https://lwn.net/Articles/842926/ https://lwn.net/Articles/842926/ NYKevin <div class="FormattedComment"> 1. Modern filesystems are much safer than old filesystems, by default. When was the last time you had to run fsck on boot?<br> 2. I did not claim that old code was &quot;broken,&quot; merely that it was at risk of losing data. My point is that both the application developer and the sysadmin would have been aware of that problem, and would take appropriate steps to remediate it (such as making regular backups, building a RAID, or whatever else makes sense). Everyone should still be taking those steps today, because as you say, nothing is 100% reliable.<br> 3. Safety and speed are a tradeoff. But since we can&#x27;t get to 100% safety, the primary value of safety is extrinsic: a safer system causes us to spend less time and resources on recovery (e.g. sitting around waiting for fsck to complete so I can boot my machine). So safety is itself a form of speed, and we can directly compare the time spent on recovery to the time spent on disk I/O - and as it turns out, once you make fsck obsolete, the disk I/O is a lot bigger for most people under most circumstances.<br> </div> Sun, 17 Jan 2021 09:33:17 +0000 What about other filesystems? https://lwn.net/Articles/842922/ https://lwn.net/Articles/842922/ dvdeug <div class="FormattedComment"> Linux can&#x27;t save you if the computer fails due to any number of physical problems. It has always been the case that &quot;you might lose data&quot;. The change is that older Unixes don&#x27;t require you to do anything special to achieve maximal data safety offered, whereas modern systems require you to do something special for the OS to try its best. Arguably (as Wol does), going from ordered behavior to complex reordering is a downgrade in the promised level of support.<br> <p> Taking code that didn&#x27;t require fsync (because it doesn&#x27;t exist) and, in the words of zlynx, saying that &quot;it&#x27;s broken&quot; makes all ISO C code that needs data safety broken, which seems extreme. From my perspective, filesystem developers got the ability to increase safety by default or speed by default, and chose speed. That doesn&#x27;t really upset me, so much as the fact that the word &quot;pony&quot; gets pulled out and one side gets painted as unreasonable, instead of it getting painted as a tradeoff and argued on that basis.<br> </div> Sun, 17 Jan 2021 08:16:23 +0000 What about other filesystems? https://lwn.net/Articles/842920/ https://lwn.net/Articles/842920/ NYKevin <div class="FormattedComment"> It depends. Let&#x27;s go through these:<br> <p> - For fsync()&#x27;ing multiple files, the standard answer is &quot;use a thread pool.&quot; This is also the standard answer to &quot;I want asynchronous I/O like on Windows,&quot; so no surprise there.<br> - As the article mentions, they are discussing an &quot;fsync multiple files&quot; syscall, which will (probably) further alleviate this problem (if it actually happens).<br> - I&#x27;m not aware of any syscall called &quot;fsfsync(),&quot; so I assume you meant syncfs(2). That function is not in POSIX, so all we have to go on is the note in that man page, which explicitly states that &quot;sync() or syncfs() provide the same guarantees as fsync() called on every file in the system or filesystem respectively.&quot;<br> - POSIX says that sync(2) is not required to wait for the writes to complete before returning (unlike fsync()). As noted above, POSIX does not specify syncfs() at all.<br> - Arguably, a conforming implementation could implement sync() as a no-op, because POSIX says it causes outstanding data &quot;to be scheduled for writing out&quot; - but it was *already* scheduled for writing out.<br> - Therefore, if you want to be pedantically POSIX-correct, you should not use sync(2) at all, because it gets you exactly nothing according to the standard.<br> - Since syncfs() is already Linux-specific, you can rely on its Linux-specific guarantees, if you are in a position to call it in the first place.<br> </div> Sun, 17 Jan 2021 04:41:21 +0000 What about other filesystems? https://lwn.net/Articles/842915/ https://lwn.net/Articles/842915/ orib <div class="FormattedComment"> <font class="QuotedText">&gt; All this talk about &quot;apps should use fsync&quot; or &quot;apps should use fsfsync&quot; fills me with horror, as someone who wants to write a system that relies on data integrity. Are you telling me that my app needs to be filesystem-aware, and not only that but aware of what mount options were used, so I know which commands to call to make sure that my data is safe?</font><br> <p> No, the opposite: your app needs to be aware of the *STANDARDS* that the filesystem is attempting to conform to, rather than what the implementation of the day happens to do.<br> </div> Sun, 17 Jan 2021 00:53:03 +0000 What about other filesystems? https://lwn.net/Articles/842912/ https://lwn.net/Articles/842912/ Wol <div class="FormattedComment"> <font class="QuotedText">&gt; Why should fsbarrier() be any different in this regard than fsync(). Neither of the two requires the system to cripple performance. And both of them can be implemented by just forcing a global filesystem sync. The performance of fsync is getting much better, as the developers actually use the freedom they have. But I am wondering why you expect filesystem developers to implement the (from a filesystem perspective) much harder fsbarrier() call more efficiently than the relatively straightforward fsync() call. fsbarrier() would probably require a major rewrite of the VFS layer to even be able to compute the list of files that are effected by such a call. Chances are good that developers will use similar shortcuts as they have done for fsync() for decades and performance of the whole system will cripple with such a call.</font><br> <p> So let&#x27;s say I want to guarantee - let&#x27;s say ten or twenty - files have all flushed before I start writing the next file, can I do those fsync()s in parallel? Without having to spawn 20 threads and then wait on them all? Whatever, that&#x27;s a lot of work.<br> <p> And with an fsfsync, again does that provide the ordering guarantee? I&#x27;ve heard that yes it guarantees everything that&#x27;s been written gets flushed, but does it put a hard barrier in (like my fsbarrier()), or does it just stall all new writes until all the old writes have been flushed, or does it just guarantee that everything written before the fsfsync is flushed but it doesn&#x27;t stop newer writes being merged forwards and being caught up in the flush?<br> <p> Because if fsfsync() puts that barrier in, I&#x27;m simply changing a synchronous fsfsync() to an asynchronous fsbarrier(), if it&#x27;s the second option it&#x27;s causing a performance impact on the system, and if it&#x27;s the third option then my app has to do a synchronous call with the performance impact that implies.<br> <p> Cheers,<br> Wol<br> </div> Sat, 16 Jan 2021 21:42:40 +0000 What about other filesystems? https://lwn.net/Articles/842909/ https://lwn.net/Articles/842909/ matthias <div class="FormattedComment"> <font class="QuotedText">&gt;AND YOU CAN&#x27;T EVEN RELY ON JOURNALLING because you don&#x27;t know whether the file system has written the journal before, after, or in the middle of writing the data.</font><br> <p> Journalling was primarily invented to ensure the integrity of the filesystem. I.e., to avoid a total loss of the filesystem in case of power loss/crash.<br> <p> <font class="QuotedText">&gt; Really, all I want is something like fsbarrier(), which GUARANTEES that stuff written after it is written after stuff that was written before it. </font><br> <p> This would be quite nice. fsync() only guarantees ordering for data written to the given file descriptor. fsbarrier() would probably be easier to use for the app developer. No need to call it for every involved file descriptor. And yes, in many cases guaranteeing ordering would be enough. No need to actually force the data to the disk before the syscall can return.<br> <p> <font class="QuotedText">&gt; I don&#x27;t give a monkeys whether the filesystem batches, parallelises, or what ever other O_PONIES writes, provided I can reason that this call makes sure my stuff hits the disk in the order I expect.</font><br> <font class="QuotedText">&gt; If I want to trash my application&#x27;s performance with excessive use of fsbarrier(), that&#x27;s my problem. If the OS expects me to trash EVERYONE ELSE&#x27;S performance with excessive use of fsync() or fsfsync(), then that&#x27;s a BIG problem for the OS!</font><br> <p> Why should fsbarrier() be any different in this regard than fsync(). Neither of the two requires the system to cripple performance. And both of them can be implemented by just forcing a global filesystem sync. The performance of fsync is getting much better, as the developers actually use the freedom they have. But I am wondering why you expect filesystem developers to implement the (from a filesystem perspective) much harder fsbarrier() call more efficiently than the relatively straightforward fsync() call. fsbarrier() would probably require a major rewrite of the VFS layer to even be able to compute the list of files that are effected by such a call. Chances are good that developers will use similar shortcuts as they have done for fsync() for decades and performance of the whole system will cripple with such a call.<br> <p> <font class="QuotedText">&gt; Oh - and wasn&#x27;t advice about how to shut a system down always &quot;# sync; sync; sync; halt&quot;? So all of us old hands expect sync() to do a filesystem flush? And do you really expect me as a developer to do that after most writes when I expect something like that to bring the system to its knees?</font><br> <p> sync guarantees a full filesystem flush. No changes there. That is indeed a bit of overkill if you just require ordering. fsync used to be quite inefficient as well, but it is getting better in this regard. And I know nobody who suggests to use sync in normal apps. fsync should be enough if used correctly.<br> <p> Best,<br> Matthias<br> </div> Sat, 16 Jan 2021 21:10:06 +0000 What about other filesystems? https://lwn.net/Articles/842911/ https://lwn.net/Articles/842911/ NYKevin <div class="FormattedComment"> The fundamental problem with this argument is that the API you describe can be (and has been) implemented in userspace (in the form of SQLite, as well as numerous &quot;real&quot; databases). Therefore, if you want to argue in favor of doing this in kernel space, it is not enough to argue that a new API would be &quot;better&quot; in various ways. You need to *specifically* address one question: Why should anyone re-implement already working userspace code in the kernel? Would it provide some performance advantage? Would it somehow enable you to do things that you can&#x27;t currently do? Or would it just be &quot;more convenient?&quot; If the latter, how is that the kernel&#x27;s problem?<br> </div> Sat, 16 Jan 2021 20:49:23 +0000