요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. 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 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 a 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 provide 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/
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
atomic write 유형과 요구 조건
1-46atomic(untorn) block write는 write 전체가 disk에 commit되거나 아무것도 commit되지 않도록 보장합니다. power loss나 system crash 때 old data와 new data가 섞이는 torn write를 막습니다.
ext4는 regular file이 extents를 사용하고 underlying storage device가 hardware atomic write를 지원할 때 Direct I/O에 한해서 atomic write를 지원합니다.
첫 번째 방식은 single-fsblock atomic write입니다. ext4는 Linux v6.13부터 filesystem block 하나에 대한 atomic write를 지원하며 atomic write unit의 minimum과 maximum이 모두 filesystem block size입니다. 예를 들어 page size가 64KB인 시스템의 16KB block size 파일시스템에서 16KB atomic write가 가능합니다.
두 번째 방식은 bigalloc을 이용한 multi-fsblock atomic write입니다. 여러 filesystem block에 걸친 요청을 지원하며, underlying device의 atomic write unit 한계를 바탕으로 filesystem block size와 cluster size가 minimum과 maximum을 결정합니다.
기본 요구 조건은 ext4에서 기본인 extents feature와 block device의 atomic write 지원입니다. single-fsblock 방식은 page size 이하의 적절한 filesystem block size가 필요합니다. multi-fsblock 방식은 bigalloc feature가 켜져 있고 cluster size가 적절히 설정돼야 합니다.
ext4는 software 또는 COW 기반 atomic write를 지원하지 않습니다. underlying storage device가 직접 지원할 때만 사용할 수 있습니다.
filesystem 단위와 필요한 기능을 비교합니다.
.. 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 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.
bigalloc 제약과 allocation 전략
47-79bigalloc은 ext4가 여러 filesystem block을 cluster라는 단위로 할당하게 합니다. block bitmap의 bit 하나는 개별 filesystem block이 아니라 2의 거듭제곱 개 block으로 구성된 cluster 하나를 나타냅니다.
multi-fsblock atomic write의 minimum size는 filesystem block size와 minimum hardware atomic write unit 중 큰 값입니다. maximum size는 bigalloc cluster size와 maximum hardware atomic write unit 중 작은 값입니다.
bigalloc은 모든 allocation을 cluster size에 맞춰 align합니다. partition 또는 logical volume 시작점도 올바르게 align돼 있다면 hardware device의 LBA alignment 요구 조건을 만족합니다.
완전히 mapped된 extent 영역은 추가 작업이 필요 없습니다. append write에는 새 mapped extent를 할당하고, 전체가 hole인 영역에는 unwritten extent를 만듭니다. 큰 unwritten extent는 요청 크기에 맞는 두 unwritten extent로 나눕니다.
hole, unwritten extent, mapped extent가 섞인 mixed mapping 영역에서는 `ext4_map_blocks()`를 `EXT4_GET_BLOCKS_ZERO` flag와 함께 반복 호출합니다. zero를 write하고 범위 안의 unwritten extent를 written으로 바꿔 요청 영역 전체를 하나의 연속 mapped extent로 만듭니다.
mapped이거나 unwritten인 단일 연속 underlying extent에 쓰는 것 자체는 문제가 아닙니다. atomic write에서는 mapped와 unwritten extent가 섞인 mixed mapping 영역에 직접 쓰는 일을 피해야 합니다.
기존 mapping 상태에 따라 write 전 준비 작업이 달라집니다.
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 a 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.
torn write 방지를 위한 단일 extent 준비
80-106`pwritev2()`에 `RWF_ATOMIC` flag를 주어 실행한 atomic write는 data 전체를 쓰거나 전혀 쓰지 않아야 합니다. write 중 crash 또는 power loss가 발생해도 나중에 읽은 영역은 complete old data 또는 complete new data 중 하나여야 하며 둘의 혼합이어서는 안 됩니다.
이를 위해 ext4는 어떤 data도 쓰기 전에 write target이 하나의 contiguous extent로 backing되도록 보장합니다. ext4는 unwritten extent를 written extent로 바꾸는 작업을 I/O completion path, 보통 `->end_io()`까지 미룹니다.
mapped와 unwritten extent가 섞인 영역에 write하다 중간에 실패하면 reboot 뒤 mapped 부분에는 new data가, written으로 표시되지 못한 unwritten 부분에는 stale old data가 보일 수 있습니다. 이는 atomicity와 torn write prevention 보장을 위반합니다.
ext4는 `ext4_iomap_alloc`에서 `ext4_map_blocks_atomic()`을 호출해 요청 영역 전체에 하나의 contiguous extent를 선제적으로 할당합니다. mixed mapping 위에 allocation했다면 현재 journalling transaction도 강제로 commit합니다.
강제 commit은 실제 write I/O 전에 unwritten-to-written conversion 같은 pending metadata update가 file data block과 일관된 상태가 되도록 합니다. commit이 실패하면 torn write 가능성을 막기 위해 I/O 전체를 abort합니다. 이 단계가 성공한 뒤에만 iomap이 실제 data write를 수행합니다.
mixed mapping을 제거하고 metadata와 data의 경계를 맞추는 순서입니다.
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.
split leaf extent와 journal credit
107-149논리적으로도 물리적으로도 연속인 extent가 on-disk extent tree의 서로 다른 leaf node에 저장되는 특수 사례가 있습니다. 일반적인 on-disk extent tree merge는 같은 leaf block 안에서만 일어나며, 예외적으로 2-level tree 전체가 inode 안으로 merge·collapse될 때만 경계를 넘습니다.
이 layout에서 memory pressure로 extent status cache entry가 회수되면 `ext4_map_blocks()`가 split leaf extent 전체를 단일 contiguous extent로 반환하지 못할 수 있습니다.
이 문제를 처리하기 위해 `EXT4_GET_BLOCKS_QUERY_LEAF_BLOCKS` get-block flag가 추가되어 `ext4_map_query_blocks()` lookup을 확장합니다. 먼저 전체 범위의 extent status cache entry가 있는지 확인하고, 없으면 `ext4_map_query_blocks()`로 on-disk extent tree를 조회합니다.
찾은 extent가 leaf node 끝에 있으면 다음 logical block(`lblk`)을 probe해 인접 leaf의 contiguous extent를 찾습니다. atomic write 크기는 보통 `[blocksize, clustersize]`로 작게 제한되므로 효율을 위해 추가 leaf block 하나만 조회합니다.
multi-fsblock atomic write를 위해 두 시점에 충분한 journal credit을 확보합니다. `ext4_iomap_alloc()`의 block allocation 때 underlying 요청 범위에 mixed mapping 가능성이 있는지 먼저 조회합니다. 가능하다면 매 alternate block이 unwritten extent이고 그 다음이 hole일 수 있다고 가정해 최대 `m_len`만큼 credit을 예약합니다.
`->end_io()`에서는 unwritten-to-written conversion 전체를 수행할 단일 transaction을 시작합니다. conversion loop는 주로 leaf block 경계를 가로질러 split된 extent를 처리할 때 필요합니다.
cache miss 뒤 인접 leaf를 확인하고 두 단계에서 credit을 확보합니다.
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.
filesystem 생성과 application interface
150-203먼저 block device가 지원하는 atomic write unit을 확인합니다. single-fsblock atomic write에서 system block size가 page size보다 작고 더 큰 filesystem block을 쓰려면 page size가 block size 이상이어야 합니다.
16KB block size ext4 filesystem은 `mkfs.ext4 -b 16384 /dev/device`로 만듭니다. 이 예시는 page size가 16KB 이상이어야 합니다.
bigalloc과 64KB cluster size를 사용하는 multi-fsblock filesystem은 `mkfs.ext4 -F -O bigalloc -b 4096 -C 65536 /dev/device`로 만듭니다. `-b`는 block size, `-C`는 byte 단위 cluster size, `-O bigalloc`은 bigalloc feature를 뜻합니다.
application은 `pwritev2(fd, iov, iovcnt, offset, RWF_ATOMIC);`을 호출해 atomic write를 수행합니다. write는 filesystem block size에 align돼야 하고 filesystem의 maximum atomic write unit size를 넘을 수 없습니다. 자세한 검증은 `generic_atomic_write_valid()`를 참조합니다.
`statx()`에 `STATX_WRITE_ATOMIC` flag를 주면 `stx_atomic_write_unit_min` 최소 요청 크기, `stx_atomic_write_unit_max` 최대 요청 크기, `stx_atomic_write_segments_max` segment 상한을 얻습니다.
segment 상한은 IOV_ITER의 `iovcnt`처럼 한 write operation으로 gather할 수 있는 별도 memory buffer 수입니다. 현재는 항상 1입니다. atomic write를 지원하면 `statx->attributes`에 `STATX_ATTR_WRITE_ATOMIC` flag가 설정됩니다.
생성 명령과 syscall에서 확인할 값입니다.
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 provide 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.
hardware 지원과 관련 문서
204-225underlying storage device가 atomic write operation을 지원해야 합니다. 최신 NVMe와 SCSI device는 이 기능을 제공하는 경우가 많습니다.
Linux kernel은 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를 노출합니다. 두 attribute가 nonzero이면 device가 atomic write를 지원한다는 뜻입니다.
관련 자료로 ext4 bigalloc 문서 `bigalloc`, block allocation 문서 `allocators`, Linux 6.13 atomic block write 지원을 설명하는 `https://lwn.net/Articles/1009298/`을 참조합니다.
application과 filesystem이 확인할 hardware 단위입니다.
.. _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/
요약·해설
atomic_writes.rst:1-225ext4 atomic write는 Direct I/O, extents, hardware atomic write 지원을 전제로 old data 전체 또는 new data 전체만 보이게 합니다. single-fsblock은 block 하나, bigalloc 방식은 여러 block을 cluster 단위로 처리합니다.
핵심 구현은 write 전에 mixed mapping을 contiguous extent 하나로 정리하고 journal transaction을 commit하는 것입니다. userspace는 `RWF_ATOMIC`과 `statx()`를 사용하며, 실제 단위는 filesystem 설정과 sysfs의 hardware minimum·maximum을 함께 확인해야 합니다.
device capability 확인부터 완료 처리까지의 순서입니다.