ext4: Add multi-fsblock atomic write support with bigalloc
Subsystems (3)
Ritesh Harjani (IBM)
reviewerv5 cover ext4: Add multi-fsblock atomic write support with bigalloc
This adds multi-fsblock atomic write support to ext4 using bigalloc. The major chunk of the design changes are kept in Patch-4 & 5.
v4 -> v5:
=========
1. Addressed review comments and added Acked-by from Darrick.
2. Changed a minor WARN_ON(1) at one place to WARN_ON_ONCE(1) in patch-5 in ext4_iomap_begin(). Ideally we may never hit it.
3. Added force commit related info in the Documentation section where mixed mapping details are mentioned.
[v4]: https://lore.kernel.org/linux-ext4/[email protected]/
v3 -> v4:
=========
1. Added force txn commit in ext4_iomap_alloc(), in case we ended up allocating and converting unwritten to written conversion during allocation time. This happens when the underlying region has mixed mapping [1].
2. Addressed review comments from Darrick and Ojaswin.
3. Ran few data integrity tests on actual nvme device supporting atomic writes.
[v2]: https://lore.kernel.org/linux-ext4/[email protected]/
[1]: https://lore.kernel.org/linux-ext4/[email protected]/T/#m9f6607cc0e65e9fd29e675c5c15b3a03ff02110e
v2 -> v3:
=========
1. Improved error handling at several places.
2. Further fixed some worst case journal credits estimation.
3. Added better checks in the slow path allocation loop for atomic writes.
v3 testing so far:
===============
- This has survived "quick" & "auto" group testing with bigalloc on x86 and Power.
- We have also tested atomic write related tests using fio and some data integrity tests with sudden power off during writes on scsi_debug module. (Will clean up these tests and try to post them out soon!)
Appreciate any review comments / feedback!
v1 -> v2:
==========
1. Handled review comments from Ojaswin to optimize the ext4_map_block() calls in ext4_iomap_alloc().
2. Fixed the journal credits calculation for both:
- during block allocation in ext4_iomap_alloc()
- during dio completion in ->end_io callback.
Earlier we were starting multiple txns in ->end_io callback for unwritten to written conversion. But since in case of atomic writes, we want a single jbd2 txn, hence made the necessary changes there.
[v2]: https://lore.kernel.org/linux-ext4/[email protected]/
Ritesh Harjani (IBM) (7):
ext4: Document an edge case for overwrites
ext4: Check if inode uses extents in ext4_inode_can_atomic_write()
ext4: Make ext4_meta_trans_blocks() non-static for later use
ext4: Add support for EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS
ext4: Add multi-fsblock atomic write support with bigalloc
ext4: Enable support for ext4 multi-fsblock atomic write using bigalloc
ext4: Add atomic block write documentation
.../filesystems/ext4/atomic_writes.rst | 225 +++++++++++++ Documentation/filesystems/ext4/overview.rst | 1 + fs/ext4/ext4.h | 26 +- fs/ext4/extents.c | 99 ++++++ fs/ext4/file.c | 7 +- fs/ext4/inode.c | 315 ++++++++++++++++-- fs/ext4/super.c | 7 +- 7 files changed, 655 insertions(+), 25 deletions(-) create mode 100644 Documentation/filesystems/ext4/atomic_writes.rst
--
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 1/7 ext4: Document an edge case for overwrites
ext4_iomap_overwrite_begin() clears the flag for IOMAP_WRITE before calling ext4_iomap_begin(). Document this above ext4_map_blocks() call as it is easy to miss it when focusing on write paths alone.
--- fs/ext4/inode.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/ext4/inode.c +4 -0
@@ -3436,6 +3436,10 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length, } ret =ext4_iomap_alloc (inode, &map, flags); }else { +/* +* This can be called for overwrites path from +* ext4_iomap_overwrite_begin(). +*/ ret =ext4_map_blocks (NULL , inode, &map,0 ); }
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 2/7 ext4: Check if inode uses extents in ext4_inode_can_atomic_write()
In reply to Ritesh Harjani (IBM)EXT4 only supports doing atomic write on inodes which uses extents, so add a check in ext4_inode_can_atomic_write() which gets called during open.
--- fs/ext4/ext4.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ext4/ext4.h +3 -1
@@ -3847,7 +3847,9 @@ static inline int ext4_buffer_uptodate(struct buffer_head *bh)static inline bool ext4_inode_can_atomic_write (struct inode *inode) { -return S_ISREG (inode->i_mode) &&EXT4_SB (inode->i_sb)->s_awu_min >0 ; +return S_ISREG (inode->i_mode) && +ext4_test_inode_flag (inode,EXT4_INODE_EXTENTS ) && +EXT4_SB (inode->i_sb)->s_awu_min >0 ; } extern int ext4_block_write_begin(handle_t *handle, struct folio *folio,
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 3/7 ext4: Make ext4_meta_trans_blocks() non-static for later use
In reply to Ritesh Harjani (IBM)Let's make ext4_meta_trans_blocks() non-static for use in later functions during ->end_io conversion for atomic writes. We will need this function to estimate journal credits for a special case. Instead of adding another wrapper around it, let's make this non-static.
--- fs/ext4/ext4.h | 2 ++ fs/ext4/inode.c | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-)
fs/ext4/ext4.h +2 -0
@@ -3039,6 +3039,8 @@ extern void ext4_set_aops(struct inode *inode);extern int ext4_writepage_trans_blocks (struct inode *);extern int ext4_normal_submit_inode_data_buffers (struct jbd2_inode *jinode);extern int ext4_chunk_trans_blocks (struct inode *,int nrblocks); +extern int ext4_meta_trans_blocks (struct inode *inode,int lblocks, +int pextents);extern int ext4_zero_partial_blocks (handle_t *handle,struct inode *inode,loff_t lstart,loff_t lend);extern vm_fault_t ext4_page_mkwrite (struct vm_fault *vmf);
fs/ext4/inode.c +1 -5
@@ -142,9 +142,6 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, new_size); } -static int ext4_meta_trans_blocks (struct inode *inode,int lblocks, -int pextents); -/* * Test whether an inode is a fast symlink. * A fast symlink has its symlink data stored in ext4_inode_info->i_data.
@@ -5777,8 +5774,7 @@ static int ext4_index_trans_blocks(struct inode *inode, int lblocks,* * Also account for superblock, inode, quota and xattr blocks */ -static int ext4_meta_trans_blocks (struct inode *inode,int lblocks, -int pextents) +int ext4_meta_trans_blocks (struct inode *inode,int lblocks,int pextents) {ext4_group_t groups, ngroups =ext4_get_groups_count (inode->i_sb);int gdpblocks;
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 4/7 ext4: Add support for EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS
In reply to Ritesh Harjani (IBM)There can be a case where there are contiguous extents on the adjacent leaf nodes of on-disk extent trees. So when someone tries to write to this contiguous range, ext4_map_blocks() call will split by returning 1 extent at a time if this is not already cached in extent_status tree cache (where if these extents when cached can get merged since they are contiguous).
This is fine for a normal write however in case of atomic writes, it can't afford to break the write into two. Now this is also something that will only happen in the slow write case where we call ext4_map_blocks() for each of these extents spread across different leaf nodes. However, there is no guarantee that these extent status cache cannot be reclaimed before the last call to ext4_map_blocks() in ext4_map_blocks_atomic_write_slow().
Hence this patch adds support of EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS. This flag checks if the requested range can be fully found in extent status cache and return. If not, it looks up in on-disk extent tree via ext4_map_query_blocks(). If the found extent is the last entry in the leaf node, then it goes and queries the next lblk to see if there is an adjacent contiguous extent in the adjacent leaf node of the on-disk extent tree.
Even though there can be a case where there are multiple adjacent extent entries spread across multiple leaf nodes. But we only read an adjacent leaf block i.e. in total of 2 extent entries spread across 2 leaf nodes. The reason for this is that we are mostly only going to support atomic writes with upto 64KB or maybe max upto 1MB of atomic write support.
--- fs/ext4/ext4.h | 18 ++++++++- fs/ext4/extents.c | 12 ++++++ fs/ext4/inode.c | 97 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 115 insertions(+), 12 deletions(-)
fs/ext4/ext4.h +17 -1
@@ -256,9 +256,19 @@ struct ext4_allocation_request {#define EXT4_MAP_UNWRITTEN BIT(BH_Unwritten)#define EXT4_MAP_BOUNDARY BIT(BH_Boundary)#define EXT4_MAP_DELAYED BIT(BH_Delay) +/* +* This is for use in ext4_map_query_blocks() for a special case where we can +* have a physically and logically contiguous blocks split across two leaf +* nodes instead of a single extent. This is required in case of atomic writes +* to know whether the returned extent is last in leaf. If yes, then lookup for +* next in leaf block in ext4_map_query_blocks_next_in_leaf(). +* - This is never going to be added to any buffer head state. +* - We use the next available bit after BH_BITMAP_UPTODATE. +*/ +#define EXT4_MAP_QUERY_LAST_IN_LEAF BIT(BH_BITMAP_UPTODATE + 1)#define EXT4_MAP_FLAGS (EXT4_MAP_NEW | EXT4_MAP_MAPPED |\ EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\ - EXT4_MAP_DELAYED) + EXT4_MAP_DELAYED | EXT4_MAP_QUERY_LAST_IN_LEAF)struct ext4_map_blocks {ext4_fsblk_t m_pblk;
@@ -725,6 +735,12 @@ enum {#define EXT4_GET_BLOCKS_IO_SUBMIT 0x0400/* Caller is in the atomic contex, find extent if it has been cached */ #define EXT4_GET_BLOCKS_CACHED_NOWAIT 0x0800 +/* +* Atomic write caller needs this to query in the slow path of mixed mapping +* case, when a contiguous extent can be split across two adjacent leaf nodes. +* Look EXT4_MAP_QUERY_LAST_IN_LEAF. +*/ +#define EXT4_GET_BLOCKS_QUERY_LAST_IN_LEAF 0x1000/* * The bit position of these flags must not overlap with any of the
fs/ext4/extents.c +12 -0
@@ -4433,6 +4433,18 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, allocated = map->m_len;ext4_ext_show_leaf (inode, path); out: +/* +* We never use EXT4_GET_BLOCKS_QUERY_LAST_IN_LEAF with CREATE flag. +* So we know that the depth used here is correct, since there was no +* block allocation done if EXT4_GET_BLOCKS_QUERY_LAST_IN_LEAF is set. +* If tomorrow we start using this QUERY flag with CREATE, then we will +* need to re-calculate the depth as it might have changed due to block +* allocation. +*/ +if (flags &EXT4_GET_BLOCKS_QUERY_LAST_IN_LEAF ) +if (!err && ex && (ex ==EXT_LAST_EXTENT (path[depth].p_hdr))) + map->m_flags |=EXT4_MAP_QUERY_LAST_IN_LEAF ; +ext4_free_ext_path (path); trace_ext4_ext_map_blocks_exit(inode, flags, map,
fs/ext4/inode.c +86 -11
145 lines not on this page · raw message
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 5/7 ext4: Add multi-fsblock atomic write support with bigalloc
In reply to Ritesh Harjani (IBM)EXT4 supports bigalloc feature which allows the FS to work in size of clusters (group of blocks) rather than individual blocks. This patch adds atomic write support for bigalloc so that systems with bs = ps can also create FS using -
mkfs.ext4 -F -O bigalloc -b 4096 -C 16384 <dev>
With bigalloc ext4 can support multi-fsblock atomic writes. We will have to adjust ext4's atomic write unit max value to cluster size. This can then support atomic write of size anywhere between [blocksize, clustersize]. This patch adds the required changes to enable multi-fsblock atomic write support using bigalloc in the next patch.
In this patch for block allocation:
we first query the underlying region of the requested range by calling ext4_map_blocks() call. Here are the various cases which we then handle depending upon the underlying mapping type:
1. If the underlying region for the entire requested range is a mapped extent, then we don't call ext4_map_blocks() to allocate anything. We don't need to even start the jbd2 txn in this case.
2. For an append write case, we create a mapped extent.
3. If the underlying region is entirely a hole, then we create an unwritten extent for the requested range.
4. If the underlying region is a large unwritten extent, then we split the extent into 2 unwritten extent of required size.
5. If the underlying region has any type of mixed mapping, then we call ext4_map_blocks() in a loop to zero out the unwritten and the hole regions within the requested range. This then provide a single mapped extent type mapping for the requested range.
Note: We invoke ext4_map_blocks() in a loop with the EXT4_GET_BLOCKS_ZERO flag only when the underlying extent mapping of the requested range is not entirely a hole, an unwritten extent, or a fully mapped extent. That is, if the underlying region contains a mix of hole(s), unwritten extent(s), and mapped extent(s), we use this loop to ensure that all the short mappings are zeroed out. This guarantees that the entire requested range becomes a single, uniformly mapped extent. It is ok to do so because we know this is being done on a bigalloc enabled filesystem where the block bitmap represents the entire cluster unit.
Note having a single contiguous underlying region of type mapped, unwrittn or hole is not a problem. But the reason to avoid writing on top of mixed mapping region is because, atomic writes requires all or nothing should get written for the userspace pwritev2 request. So if at any point in time during the write if a crash or a sudden poweroff occurs, the region undergoing atomic write should read either complete old data or complete new data. But it should never have a mix of both old and new data.
So, we first convert any mixed mapping region to a single contiguous mapped extent before any data gets written to it. This is because normally FS will only convert unwritten extents to written at the end of the write in ->end_io() call. And if we allow the writes over a mixed mapping and if a sudden power off happens in between, we will end up reading mix of new data (over mapped extents) and old data (over unwritten extents), because unwritten to written conversion never went through.
So to avoid this and to avoid writes getting torned due to mixed mapping, we first allocate a single contiguous block mapping and then do the write.
--- fs/ext4/ext4.h | 2 + fs/ext4/extents.c | 87 +++++++++++++++++++ fs/ext4/file.c | 7 +- fs/ext4/inode.c | 208 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 299 insertions(+), 5 deletions(-)
fs/ext4/ext4.h +2 -0
@@ -3728,6 +3728,8 @@ extern long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len);extern int ext4_convert_unwritten_extents (handle_t *handle,struct inode *inode,loff_t offset,ssize_t len); +extern int ext4_convert_unwritten_extents_atomic (handle_t *handle, +struct inode *inode,loff_t offset,ssize_t len);extern int ext4_convert_unwritten_io_end_vec (handle_t *handle,ext4_io_end_t *io_end); extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
fs/ext4/extents.c +87 -0
93 lines not on this page · raw message
fs/ext4/file.c +6 -1
@@ -377,7 +377,12 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,loff_t pos = iocb->ki_pos;struct inode *inode =file_inode (iocb->ki_filp); -if (!error && size && flags &IOMAP_DIO_UNWRITTEN ) + +if (!error && size && (flags &IOMAP_DIO_UNWRITTEN ) && + (iocb->ki_flags &IOCB_ATOMIC )) + error =ext4_convert_unwritten_extents_atomic (NULL , inode, pos, + size); +else if (!error && size && flags &IOMAP_DIO_UNWRITTEN ) error =ext4_convert_unwritten_extents (NULL , inode, pos, size);if (error)return error;
fs/ext4/inode.c +204 -4
262 lines not on this page · raw message
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 6/7 ext4: Enable support for ext4 multi-fsblock atomic write using bigalloc
In reply to Ritesh Harjani (IBM)Last couple of patches added the needed support for multi-fsblock atomic writes using bigalloc. This patch ensures that filesystem advertizes the needed atomic write unit min and max values for enabling multi-fsblock atomic write support with bigalloc.
--- fs/ext4/super.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
fs/ext4/super.c +5 -2
@@ -4441,13 +4441,16 @@ static int ext4_handle_clustersize(struct super_block *sb)/* * ext4_atomic_write_init: Initializes filesystem min & max atomic write units. +* With non-bigalloc filesystem awu will be based upon filesystem blocksize +* & bdev awu units. +* With bigalloc it will be based upon bigalloc cluster size & bdev awu units. * @sb: super block -* TODO: Later add support for bigalloc */ static void ext4_atomic_write_init (struct super_block *sb) {struct ext4_sb_info *sbi =EXT4_SB (sb);struct block_device *bdev = sb->s_bdev; +unsigned int clustersize =EXT4_CLUSTER_SIZE (sb);if (!bdev_can_atomic_write (bdev))return ;
@@ -4457,7 +4460,7 @@ static void ext4_atomic_write_init(struct super_block *sb) sbi->s_awu_min =max (sb->s_blocksize,bdev_atomic_write_unit_min_bytes (bdev)); - sbi->s_awu_max =min (sb->s_blocksize, + sbi->s_awu_max =min (clustersize,bdev_atomic_write_unit_max_bytes (bdev));if (sbi->s_awu_min && sbi->s_awu_max && sbi->s_awu_min <= sbi->s_awu_max) {
Signature · 1 line
2.49.0
Ritesh Harjani (IBM)
reviewerPATCH v5 7/7 ext4: Add atomic block write documentation
In reply to Ritesh Harjani (IBM)Add an initial documentation around atomic writes support in ext4.
--- .../filesystems/ext4/atomic_writes.rst | 225 ++++++++++++++++++ Documentation/filesystems/ext4/overview.rst | 1 + 2 files changed, 226 insertions(+) create mode 100644 Documentation/filesystems/ext4/atomic_writes.rst
Documentation/filesystems/ext4/atomic_writes.rst new file +225 -0
@@ -0,0 +1,225 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. _atomic_writes: + +Atomic Block Writes +------------------------- + +Introduction +~~~~~~~~~~~~ + +Atomic (untorn) block writes ensure that either the entire write is committed +to disk or none of it is. This prevents "torn writes" during power loss or +system crashes. The ext4 filesystem supports atomic writes (only with Direct +I/O) on regular files with extents, provided the underlying storage device +supports hardware atomic writes. This is supported in the following two ways: + +1. **Single-fsblock Atomic Writes**: + EXT4's supports atomic write operations with a single filesystem block since + v6.13. In this the atomic write unit minimum and maximum sizes are both set + to filesystem blocksize. + e.g. doing atomic write of 16KB with 16KB filesystem blocksize on 64KB + pagesize system is possible. + +2. **Multi-fsblock Atomic Writes with Bigalloc**: + EXT4 now also supports atomic writes spanning multiple filesystem blocks + using a feature known as bigalloc. The atomic write unit's minimum and + maximum sizes are determined by the filesystem block size and cluster size, + based on the underlying device’s supported atomic write unit limits. + +Requirements +~~~~~~~~~~~~ + +Basic requirements for atomic writes in ext4: + + 1. The extents feature must be enabled (default for ext4) + 2. The underlying block device must support atomic writes + 3. For single-fsblock atomic writes: + + 1. A filesystem with appropriate block size (up to the page size) + 4. For multi-fsblock atomic writes: + + 1. The bigalloc feature must be enabled + 2. The cluster size must be appropriately configured + +NOTE: EXT4 does not support software or COW based atomic write, which means +atomic writes on ext4 are only supported if underlying storage device supports +it. + +Multi-fsblock Implementation Details +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The bigalloc feature changes ext4 to allocate in units of multiple filesystem +blocks, also known as clusters. With bigalloc each bit within block bitmap +represents cluster (power of 2 number of blocks) rather than individual +filesystem blocks. +EXT4 supports multi-fsblock atomic writes with bigalloc, subject to the +following constraints. The minimum atomic write size is the larger of the fs +block size and the minimum hardware atomic write unit; and the maximum atomic +write size is smaller of the bigalloc cluster size and the maximum hardware +atomic write unit. Bigalloc ensures that all allocations are aligned to the +cluster size, which satisfies the LBA alignment requirements of the hardware +device if the start of the partition/logical volume is itself aligned correctly. + +Here is the block allocation strategy in bigalloc for atomic writes: + + * For regions with fully mapped extents, no additional work is needed + * For append writes, a new mapped extent is allocated + * For regions that are entirely holes, unwritten extent is created + * For large unwritten extents, the extent gets split into two unwritten + extents of appropriate requested size + * For mixed mapping regions (combinations of holes, unwritten extents, or + mapped extents), ext4_map_blocks() is called in a loop with + EXT4_GET_BLOCKS_ZERO flag to convert the region into a single contiguous + mapped extent by writing zeroes to it and converting any unwritten extents to + written, if found within the range. + +Note: Writing on a single contiguous underlying extent, whether mapped or +unwritten, is not inherently problematic. However, writing to a mixed mapping +region (i.e. one containing a combination of mapped and unwritten extents) +must be avoided when performing atomic writes. + +The reason is that, atomic writes when issued via pwritev2() with the RWF_ATOMIC +flag, requires that either all data is written or none at all. In the event of +a system crash or unexpected power loss during the write operation, the affected +region (when later read) must reflect either the complete old data or the +complete new data, but never a mix of both. + +To enforce this guarantee, we ensure that the write target is backed by +a single, contiguous extent before any data is written. This is critical because +ext4 defers the conversion of unwritten extents to written extents until the I/O +completion path (typically in ->end_io()). If a write is allowed to proceed over +a mixed mapping region (with mapped and unwritten extents) and a failure occurs +mid-write, the system could observe partially updated regions after reboot, i.e. +new data over mapped areas, and stale (old) data over unwritten extents that +were never marked written. This violates the atomicity and/or torn write +prevention guarantee. + +To prevent such torn writes, ext4 proactively allocates a single contiguous +extent for the entire requested region in ``ext4_iomap_alloc`` via +``ext4_map_blocks_atomic()``. EXT4 also force commits the current journalling +transaction in case if allocation is done over mixed mapping. This ensures any +pending metadata updates (like unwritten to written extents conversion) in this +range are in consistent state with the file data blocks, before performing the +actual write I/O. If the commit fails, the whole I/O must be aborted to prevent +from any possible torn writes. +Only after this step, the actual data write operation is performed by the iomap. + +Handling Split Extents Across Leaf Blocks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There can be a special edge case where we have logically and physically +contiguous extents stored in separate leaf nodes of the on-disk extent tree. +This occurs because on-disk extent tree merges only happens within the leaf +blocks except for a case where we have 2-level tree which can get merged and +collapsed entirely into the inode. +If such a layout exists and, in the worst case, the extent status cache entries +are reclaimed due to memory pressure, ``ext4_map_blocks()`` may never return +a single contiguous extent for these split leaf extents. + +To address this edge case, a new get block flag +``EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS flag`` is added to enhance the +``ext4_map_query_blocks()`` lookup behavior. + +This new get block flag allows ``ext4_map_blocks()`` to first check if there is +an entry in the extent status cache for the full range. +If not present, it consults the on-disk extent tree using +``ext4_map_query_blocks()``. +If the located extent is at the end of a leaf node, it probes the next logical +block (lblk) to detect a contiguous extent in the adjacent leaf. + +For now only one additional leaf block is queried to maintain efficiency, as +atomic writes are typically constrained to small sizes +(e.g. [blocksize, clustersize]). + + +Handling Journal transactions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To support multi-fsblock atomic writes, we ensure enough journal credits are +reserved during: + + 1. Block allocation time in ``ext4_iomap_alloc()``. We first query if there + could be a mixed mapping for the underlying requested range. If yes, then we + reserve credits of up to ``m_len``, assuming every alternate block can be + an unwritten extent followed by a hole. + + 2. During ``->end_io()`` call, we make sure a single transaction is started for + doing unwritten-to-written conversion. The loop for conversion is mainly + only required to handle a split extent across leaf blocks. + +How to +------ + +Creating Filesystems with Atomic Write Support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First check the atomic write units supported by block device. +See :ref:`atomic_write_bdev_support` for more details. + +For single-fsblock atomic writes with a larger block size +(on systems with block size < page size): + +.. code-block:: bash + + # Create an ext4 filesystem with a 16KB block size + # (requires page size >= 16KB) + mkfs.ext4 -b 16384 /dev/device + +For multi-fsblock atomic writes with bigalloc: + +.. code-block:: bash + + # Create an ext4 filesystem with bigalloc and 64KB cluster size + mkfs.ext4 -F -O bigalloc -b 4096 -C 65536 /dev/device + +Where ``-b`` specifies the block size, ``-C`` specifies the cluster size in bytes, +and ``-O bigalloc`` enables the bigalloc feature. + +Application Interface +~~~~~~~~~~~~~~~~~~~~~ + +Applications can use the ``pwritev2()`` system call with the ``RWF_ATOMIC`` flag +to perform atomic writes: + +.. code-block:: c + + pwritev2(fd, iov, iovcnt, offset, RWF_ATOMIC); + +The write must be aligned to the filesystem's block size and not exceed the +filesystem's maximum atomic write unit size. +See ``generic_atomic_write_valid()`` for more details. + +``statx()`` system call with ``STATX_WRITE_ATOMIC`` flag can provides following +details: + + * ``stx_atomic_write_unit_min``: Minimum size of an atomic write request. + * ``stx_atomic_write_unit_max``: Maximum size of an atomic write request. + * ``stx_atomic_write_segments_max``: Upper limit for segments. The number of + separate memory buffers that can be gathered into a write operation + (e.g., the iovcnt parameter for IOV_ITER). Currently, this is always set to one. + +The STATX_ATTR_WRITE_ATOMIC flag in ``statx->attributes`` is set if atomic +writes are supported. + +.. _atomic_write_bdev_support: + +Hardware Support +---------------- + +The underlying storage device must support atomic write operations. +Modern NVMe and SCSI devices often provide this capability. +The Linux kernel exposes this information through sysfs: + +* ``/sys/block/<device>/queue/atomic_write_unit_min`` - Minimum atomic write size +* ``/sys/block/<device>/queue/atomic_write_unit_max`` - Maximum atomic write size + +Nonzero values for these attributes indicate that the device supports +atomic writes. + +See Also +-------- + +* :doc:`bigalloc` - Documentation on the bigalloc feature +* :doc:`allocators` - Documentation on block allocation in ext4 +* Support for atomic block writes in 6.13: + https://lwn.net/Articles/1009298/
Documentation/filesystems/ext4/overview.rst +1 -0
@@ -25,3 +25,4 @@ order. .. include:: inlinedata.rst .. include:: eainode.rst .. include:: verity.rst +.. include:: atomic_writes.rst
Signature · 1 line
2.49.0
Re: [PATCH v5 7/7] ext4: Add atomic block write documentation
On 15/05/2025 20:50, Ritesh Harjani (IBM) wrote:
thanks for adding this info
Quoted 1 line
Application Interface
Should we put this into a common file, as it is just not relevant to ext4?
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
Quoted 10 lines
+~~~~~~~~~~~~~~~~~~~~~
Documentation/filesystems/ext4/atomic_writes.rst new file +9
-0+ +Applications can use the ``pwritev2()`` system call with the ``RWF_ATOMIC`` flag +to perform atomic writes: + +.. code-block:: c + + pwritev2(fd, iov, iovcnt, offset, RWF_ATOMIC); + +The write must be aligned to the filesystem's block size and not exceed the
Documentation/filesystems/ext4/atomic_writes.rst line 198
Quoted 10 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +10
-0+filesystem's maximum atomic write unit size. +See ``generic_atomic_write_valid()`` for more details. + +``statx()`` system call with ``STATX_WRITE_ATOMIC`` flag can provides following +details: + + * ``stx_atomic_write_unit_min``: Minimum size of an atomic write request. + * ``stx_atomic_write_unit_max``: Maximum size of an atomic write request. + * ``stx_atomic_write_segments_max``: Upper limit for segments. The number of + separate memory buffers that can be gathered into a write operation
there will also be stx_atomic_write_unit_max_opt, as queued for 6.16
For HW-only support, I think that it is ok to just return same as stx_atomic_write_unit_max when we can atomic write > 1 filesystem block
Quoted 4 lines
+ (e.g., the iovcnt parameter for
IOV_ITER).Currently, this is always set to one.
JFYI, for xfs supporting filesystem-based atomic writes only, i.e. no HW support, we could set this to a higher value
Quoted 5 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +5
-0+ +The STATX_ATTR_WRITE_ATOMIC flag in ``statx->attributes`` is set if atomic +writes are supported. + +.. _atomic_write_bdev_support:
Documentation/filesystems/ext4/atomic_writes.rst line 214
Quoted 10 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +10
-0+ +Hardware Support +---------------- + +The underlying storage device must support atomic write operations. +Modern NVMe and SCSI devices often provide this capability. +The Linux kernel exposes this information through sysfs: + +* ``/sys/block/<device>/queue/atomic_write_unit_min`` - Minimum atomic write size +* ``/sys/block/<device>/queue/atomic_write_unit_max`` - Maximum atomic write size
there is also the max bytes and boundary files. I am not sure if it was intentional to omit them.
Documentation/filesystems/ext4/atomic_writes.rst line 219
Quoted 5 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +5
-0+ +Nonzero values for these attributes indicate that the device supports +atomic writes. + +See Also
thanks,
John
Theodore Ts'o
maintainerRe: [PATCH v5 7/7] ext4: Add atomic block write documentation
Quoted 3 lines · John Garry
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
What is the current outook for the xfs changes landing in the next merge window? I haven't been tracking the latest rounds of reviews for the xfs atomic writes patchset.
If the xfs atomic writes patchset aren't going to land this window, then we can land them as ext4 specific documentation, and when the xfs patches land, we can reorganize the documentation at that point. Does that make sense?
- Ted
Re: [PATCH v5 7/7] ext4: Add atomic block write documentation
On 16/05/2025 13:19, Theodore Ts'o wrote:
+ Carlos
Quoted 5 lines · John Garry
Quoted 2 lines
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
What is the current outook for the xfs changes landing in the next merge window?
The changes have been queued, please see:
https://lore.kernel.org/linux-xfs/174665351406.2683464.14829425904827876762.stg-ugh@frogsfrogsfrogs/
Quoted 7 lines
I haven't been tracking the latest rounds of reviews for the xfs atomic writes patchset.
If the xfs atomic writes patchset aren't going to land this window, then we can land them as ext4 specific documentation, and when the xfs patches land, we can reorganize the documentation at that point. Does that make sense?
So I figure that we can organise the documentation now to cover both ext4 and xfs.
Thanks,
John
Re: [PATCH v5 7/7] ext4: Add atomic block write documentation
Quoted 5 lines · John Garry
On 16/05/2025 13:19, Theodore Ts'o wrote:
+ Carlos
Quoted 1 line · John Garry
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
What is the current outook for the xfs changes landing in the next merge window?
The changes have been queued, please see:
https://lore.kernel.org/linux-xfs/174665351406.2683464.14829425904827876762.stg-ugh@frogsfrogsfrogs/
Hi Ted,
XFS changes are here:
https://web.git.kernel.org/pub/scm/fs/xfs/xfs-linux.git/log/?h=xfs-6.16-merge
Quoted 9 lines
Quoted 8 lines
I haven't been tracking the latest rounds of reviews for the xfs atomic writes patchset.
If the xfs atomic writes patchset aren't going to land this window, then we can land them as ext4 specific documentation, and when the xfs patches land, we can reorganize the documentation at that point. Does that make sense?
They have been also in xfs/for-next for a while now.
This is likely the final state for XFS merge-window and I hope to send it to Linus as soon as the merge window opens.
Hope this helps.
Quoted 5 lines
So I figure that we can organise the documentation now to cover both ext4 and xfs.
Thanks,
John
Ritesh Harjani (IBM)
reviewerRe: [PATCH v5 7/7] ext4: Add atomic block write documentation
In reply to John GarryQuoted 11 lines · John Garry
On 15/05/2025 20:50, Ritesh Harjani (IBM) wrote:
thanks for adding this info
Quoted 1 line
Application Interface
Should we put this into a common file, as it is just not relevant to ext4?
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
The purpose of adding this documentation was mainly to note down some of the implementation details around multi-fsblock atomic writes for ext4 using bigalloc which otherwise are easy to miss. But since there was no general documentation available on atomic writes, we added a bit more info around it mainly enough to cover ext4.
Quoted 23 lines
Quoted 10 lines
+~~~~~~~~~~~~~~~~~~~~~
Documentation/filesystems/ext4/atomic_writes.rst new file +9
-0+ +Applications can use the ``pwritev2()`` system call with the ``RWF_ATOMIC`` flag +to perform atomic writes: + +.. code-block:: c + + pwritev2(fd, iov, iovcnt, offset, RWF_ATOMIC); + +The write must be aligned to the filesystem's block size and not exceed theDocumentation/filesystems/ext4/atomic_writes.rst line 198
Quoted 10 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +10
-0+filesystem's maximum atomic write unit size. +See ``generic_atomic_write_valid()`` for more details. + +``statx()`` system call with ``STATX_WRITE_ATOMIC`` flag can provides following +details: + + * ``stx_atomic_write_unit_min``: Minimum size of an atomic write request. + * ``stx_atomic_write_unit_max``: Maximum size of an atomic write request. + * ``stx_atomic_write_segments_max``: Upper limit for segments. The number of + separate memory buffers that can be gathered into a write operationthere will also be
stx_atomic_write_unit_max_opt, as queued for 6.16
Quoted 3 lines
For HW-only support, I think that it is ok to just return same as
stx_atomic_write_unit_maxwhen we can atomic write > 1 filesystem block
Yes, so for HW-only support like ext4 it may not be strictly required. To avoid the dependency on XFS patch series, I think it will be better if we add those changes after XFS multi-fsblock atomic write has landed :)
Quoted 8 lines
Quoted 4 lines
+ (e.g., the iovcnt parameter for
IOV_ITER).Currently, this is always set to one.
JFYI, for xfs supporting filesystem-based atomic writes only, i.e. no HW support, we could set this to a higher value
Yes. But again, XFS specific detail, not strictly relevant for EXT4 atomic write documentation.
Quoted 10 lines
Quoted 10 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +10
-0+ +The STATX_ATTR_WRITE_ATOMIC flag in ``statx->attributes`` is set if atomic +writes are supported. + +.. _atomic_write_bdev_support: + +Hardware Support +---------------- + +The underlying storage device must support atomic write operations.
Quoted 9 lines
Documentation/filesystems/ext4/atomic_writes.rst line 214
Quoted 5 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +5
-0+Modern NVMe and SCSI devices often provide this capability. +The Linux kernel exposes this information through sysfs: + +* ``/sys/block/<device>/queue/atomic_write_unit_min`` - Minimum atomic write size +* ``/sys/block/<device>/queue/atomic_write_unit_max`` - Maximum atomic write sizethere is also the max bytes and boundary files. I am not sure if it was intentional to omit them.
The intention of this section was mainly for sysadmin to first check if the underlying block device supports atomic writes and what are it's awu units to decide an appropriate blocksize and/or clustersize for ext4 filesystem.
See section "Creating Filesystems with Atomic Write Support" which refers to this section first.
Quoted 8 lines
Documentation/filesystems/ext4/atomic_writes.rst line 219
Quoted 5 lines
Documentation/filesystems/ext4/atomic_writes.rst new file +5
-0+ +Nonzero values for these attributes indicate that the device supports +atomic writes. + +See Alsothanks,
John
Thanks for the review John.
I think the current documentation mainly caters to ext4 specific implementation notes on single and multi-fsblock atomic writes.
IMO, it is ok for us to keep this Documentation as is for v6.16 and let's work on a more general doc which can cover details like:
- block device driver support (scsi & nvme)
- block layer support (bio split & merge )
- Filesystem & iomap support (iomap, ext4, xfs)
- VFS layer support (statx, pwritev2...)
We can add these documentations in their respective subsystem directories and add a more common Documentation where VFS details are kept, which will refer to these subsystem specific details.
Thoughts?
-ritesh
Ritesh Harjani (IBM)
reviewerRe: [PATCH v5 7/7] ext4: Add atomic block write documentation
In reply to Theodore Ts'oQuoted 5 lines · Theodore Ts'o
Quoted 3 lines · John Garry
Or move this file to a common location, and have separate sections for ext4 and xfs? This would save having scattered files for instructions.
Quoted 9 lines
What is the current outook for the xfs changes landing in the next merge window? I haven't been tracking the latest rounds of reviews for the xfs atomic writes patchset.
If the xfs atomic writes patchset aren't going to land this window, then we can land them as ext4 specific documentation, and when the xfs patches land, we can reorganize the documentation at that point. Does that make sense?
IMO, the current documentation is primarily intended to capture notes from ext4's implementation perspective of single and multi-fsblock atomic writes.
I guess adding a more general atomic write documentation require a lot of other grounds to cover too e.g.
- block device driver support (scsi & nvme, dm-... )
- block layer support (bio split & merge )
- Filesystem & iomap support (iomap, ext4, xfs)
- VFS layer support (statx, pwritev2...)
So, IMO, even with XFS atomic writes patches queued for v6.16, the current documentation still stands correct. To cover more ground around atomic writes detail, we can think of adding a common documentation later which can refer to individual filesystem's documentation file for implementation notes.
Thoughts?
-ritesh
Theodore Ts'o
maintainerRe: [PATCH v5 7/7] ext4: Add atomic block write documentation
In reply to Carlos MaiolinoQuoted 3 lines · Carlos Maiolino
This is likely the final state for XFS merge-window and I hope to send it to Linus as soon as the merge window opens.
Very cool!
I've taken a quick peek, and it looks like the only XFS-specific atomic writes is an XFS mount option. Am I missing anything?
I want to keep merging the ext4 and xfs atomic write patchsets simple, so I'd prefer not to have any git-level dependencies on the branches. If we're confident that the xfs changes are going to land at the next merge window, given that the ext4 patch set is pretty much ready to land in the ext4 tree, how about updating the documentation in a follow-up patch.
I can either append the commit which generalizes the documentation to the ext4 tree, or if it turns out that there is a v6 needed of the ext4 atomic write patchset, we can fold the documentation update into the "ext4: add atomic block write documentation" commit and rename it to "Documentation: add atomic write block documentation."
Does that seem reasonable?
Cheers,
- Ted
Re: [PATCH v5 7/7] ext4: Add atomic block write documentation
Quoted 7 lines · Theodore Ts'o
Quoted 3 lines · Carlos Maiolino
This is likely the final state for XFS merge-window and I hope to send it to Linus as soon as the merge window opens.
Very cool!
Quoted 7 lines
I've taken a quick peek, and it looks like the only XFS-specific atomic writes is an XFS mount option. Am I missing anything?
I want to keep merging the ext4 and xfs atomic write patchsets simple, so I'd prefer not to have any git-level dependencies on the branches. If we're confident that the xfs changes are going to land at the next merge window,
/I/ for one hope that the xfs changes land this time around.
Quoted 11 lines
given that the ext4 patch set is pretty much ready to land in the ext4 tree, how about updating the documentation in a follow-up patch.
I can either append the commit which generalizes the documentation to the ext4 tree, or if it turns out that there is a v6 needed of the ext4 atomic write patchset, we can fold the documentation update into the "ext4: add atomic block write documentation" commit and rename it to "Documentation: add atomic write block documentation."
Does that seem reasonable?
I think it's ok to combine them after the merge. It would be useful to have a single programmer's guide that takes a person through the whole process of determining the block device's atomic write capabilities, formatting either an XFS or ext4 filesystem appropriately, and then presents a toy program to discover the atomic write limits on an open file and uses that to queue a single IO.
--D
Quoted 5 lines
Cheers,
- Ted
Re: [PATCH v5 7/7] ext4: Add atomic block write documentation
Quoted 11 lines · Darrick J. Wong
Quoted 10 lines · Theodore Ts'o
Quoted 3 lines · Carlos Maiolino
This is likely the final state for XFS merge-window and I hope to send it to Linus as soon as the merge window opens.
Very cool!
I've taken a quick peek, and it looks like the only XFS-specific atomic writes is an XFS mount option. Am I missing anything?
Quoted 6 lines
Quoted 4 lines
I want to keep merging the ext4 and xfs atomic write patchsets simple, so I'd prefer not to have any git-level dependencies on the branches. If we're confident that the xfs changes are going to land at the next merge window,
/I/ for one hope that the xfs changes land this time around.
Yes, so far everything looks good, and we've atomic writes on for-next for a while as I mentioned too (although a rebase yesterday required to have those patches re-introduced with different hashes, the content is still the same).
Ted, I'm not exactly sure what kind of git-level dependency you have in mind, but just to play safe here, bear in mind the atomic writes in merged on top of Axboe's block-6.15.
Quoted 11 lines
Quoted 11 lines
given that the ext4 patch set is pretty much ready to land in the ext4 tree, how about updating the documentation in a follow-up patch.
I can either append the commit which generalizes the documentation to the ext4 tree, or if it turns out that there is a v6 needed of the ext4 atomic write patchset, we can fold the documentation update into the "ext4: add atomic block write documentation" commit and rename it to "Documentation: add atomic write block documentation."
Quoted 8 lines
Quoted 1 line
Does that seem reasonable?
I think it's ok to combine them after the merge. It would be useful to have a single programmer's guide that takes a person through the whole process of determining the block device's atomic write capabilities, formatting either an XFS or ext4 filesystem appropriately, and then presents a toy program to discover the atomic write limits on an open file and uses that to queue a single IO.
This sounds indeed good to me too.
Have a nice weekend all.
Carlos
Quoted 9 lines
--D
Quoted 5 lines
Cheers,
- Ted
Ritesh Harjani (IBM)
reviewerQuoted 21 lines · Ritesh Harjani (IBM)
This adds multi-fsblock atomic write support to ext4 using bigalloc. The major chunk of the design changes are kept in Patch-4 & 5.
v4 -> v5:
=========
1. Addressed review comments and added Acked-by from Darrick.
2. Changed a minorWARN_ON(1)at one place toWARN_ON_ONCE(1)in patch-5 inext4_iomap_begin(). Ideally we may never hit it.
3. Added force commit related info in the Documentation section where mixed mapping details are mentioned.
[v4]: https://lore.kernel.org/linux-ext4/[email protected]/
<...>
Ritesh Harjani (IBM) (7):
ext4: Document an edge case for overwrites
ext4: Check if inode uses extents inext4_inode_can_atomic_write()
ext4: Makeext4_meta_trans_blocks()non-static for later use
ext4: Add support forEXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS
ext4: Add multi-fsblock atomic write support with bigalloc
ext4: Enable support for ext4 multi-fsblock atomic write using bigalloc
ext4: Add atomic block write documentation
Quoted 9 lines
.../filesystems/ext4/atomic_writes.rst | 225 +++++++++++++ Documentation/filesystems/ext4/overview.rst | 1 + fs/ext4/ext4.h | 26 +- fs/ext4/extents.c | 99 ++++++ fs/ext4/file.c | 7 +- fs/ext4/inode.c | 315 ++++++++++++++++-- fs/ext4/super.c | 7 +- 7 files changed, 655 insertions(+), 25 deletions(-) create mode 100644 Documentation/filesystems/ext4/atomic_writes.rst
Hi Ted,
I was working on the rebase over the weekend as I figured that there will be merge conflicts with Zhang's series. But later I saw that you have already rebased [1] and merged atomic write series in dev branch.
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/log/?h=dev
So, thanks for taking care of that. After looking at Zhang's series, I figured, we may need EXT4_EX_CACHE flag too in ext4_convert_unwritten_extents_atomic() i.e.
int flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT | EXT4_EX_NOCACHE;
This is since, in ext4_map_blocks(), we have a condition check which can emit a WARN_ON like this:
/* * Callers from the context of data submission are the only exceptions * for regular files that do not hold the i_rwsem or invalidate_lock. * However, caching unrelated ranges is not permitted. */ if (flags & EXT4_GET_BLOCKS_IO_SUBMIT) WARN_ON_ONCE(!(flags & EXT4_EX_NOCACHE)); else ext4_check_map_extents_env(inode);
Other than adding the no cache flag, couple of other minor simplifications can be done too, I guess for e.g. simplifying the query_flags logic in ext4_map_query_blocks() function.
So I am thinking maybe I will provide the above fix and few other minor simplfications which we could do on top of ext4's dev branch (after we rebased atomic write changes on top of Zhang's series). Please let me know if that is ok?
Or do we want to fix the original atomic write patch and do a force push to dev branch again?
Please let me know whichever way works best?
Thanks again!
-ritesh
Theodore Ts'o
maintainerQuoted 5 lines · Ritesh Harjani
So, thanks for taking care of that. After looking at Zhang's series, I figured, we may need
EXT4_EX_CACHEflag too inext4_convert_unwritten_extents_atomic()....
Quoted 8 lines
Other than adding the no cache flag, couple of other minor simplifications can be done too, I guess for e.g. simplifying the
query_flagslogic inext4_map_query_blocks()function.So I am thinking maybe I will provide the above fix and few other minor simplfications which we could do on top of ext4's dev branch (after we rebased atomic write changes on top of Zhang's series). Please let me know if that is ok?
Sure, that would be great. Many thanks!!
- Ted
Quoted 12 lines · Ritesh Harjani (IBM)
This adds multi-fsblock atomic write support to ext4 using bigalloc. The major chunk of the design changes are kept in Patch-4 & 5.
v4 -> v5:
=========
1. Addressed review comments and added Acked-by from Darrick.
2. Changed a minorWARN_ON(1)at one place toWARN_ON_ONCE(1)in patch-5 inext4_iomap_begin(). Ideally we may never hit it.
3. Added force commit related info in the Documentation section where mixed mapping details are mentioned.
[v4]: https://lore.kernel.org/linux-ext4/[email protected]/
Quoted 1 line
[...]
Applied, thanks!
[1/7] ext4: Document an edge case for overwrites
commit: 9fa6121684dad974c8c2b2aceb0df2b27f0627fe
[2/7] ext4: Check if inode uses extents in ext4_inode_can_atomic_write()
commit: 1c972b1d13dde34c9897d991283e2c54209b44e9
[3/7] ext4: Make ext4_meta_trans_blocks() non-static for later use
commit: 255e7bc2127cbd3a718a55d2da5b2d3f015adcd7
[4/7] ext4: Add support for EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS
commit: 5bb12b1837c0bf7ddc84e27812f1693a126fe27a
[5/7] ext4: Add multi-fsblock atomic write support with bigalloc
commit: b86629c2b2998338b4a715058b402e47d0b36206
[6/7] ext4: Enable support for ext4 multi-fsblock atomic write using bigalloc
commit: 642e0dc73c5def8270ff7c55d750ff36a6ea5d10
[7/7] ext4: Add atomic block write documentation
commit: 0bf1f51e34c4e260095fc7306c564c7fe01503e3Best regards,
Signature · 1 line
Theodore Ts'o <[email protected]>