When an EXT4 file system is running low on free space (or when it is switched via the “nodelalloc” mount option), EXT4’s delayed allocation mode can be disabled. This can result in a significant performance hit, but now awaits a patch for what should land in Linux 5.20 with the restoration of that performance when delayed assignment is disabled.
EXT4’s delayed allocation “delalloc” mode allows you to postpone the mapping of new file data blocks to disl blocks until the rewrite time. The delayed allocation is said to help reduce file system fragmentation and reduce CPU cycles spent on block allocation. EXT4 delayed allocation is activated by default, except when there is a shortage of free disk space or by using the mounting option to deactivate it – this is in cases where a performance fix / improvement is on the way.
SUSE Linux engineer Jan Kara has contributed a patch to improve write performance when delalloc is disabled. Jan explains, “When delayed allocation is disabled (either through mounting option or because we are running out of free space), ext4_write_begin () allocates blocks with EXT4_GET_BLOCKS_IO_CREATE_EXT flag. With this flag, extension merge is disabled, and since ext4_write_begin () is called for each page separately, we end up with a * mass * of 1 block extensions in the scope tree, and the following writeback writes 1 block at a time, resulting in very poor write throughput (4 MB / say instead of 200 MB / s). In these days where ext4_get_block_unwritten () is only used by ext4_write_begin (), ext4_page_mkwrite () and embedded data conversion, we can safely allow scope merging from these paths, as the following writeback will still occur at different limits. Then use EXT4_GET_BLOCKS_CREATE_UNRIT_EXT instead, which restores performance.“
It’s a simple one-line change that now queues in EXT4’s “dev” code. In turn, this should probably show up on Linux 5.20 later this summer.