Skip to content

Commit 370a6de

Browse files
johnpgarrybrauner
authored andcommitted
iomap: rework IOMAP atomic flags
Flag IOMAP_ATOMIC_SW is not really required. The idea of having this flag is that the FS ->iomap_begin callback could check if this flag is set to decide whether to do a SW (FS-based) atomic write. But the FS can set which ->iomap_begin callback it wants when deciding to do a FS-based atomic write. Furthermore, it was thought that IOMAP_ATOMIC_HW is not a proper name, as the block driver can use SW-methods to emulate an atomic write. So change back to IOMAP_ATOMIC. The ->iomap_begin callback needs though to indicate to iomap core that REQ_ATOMIC needs to be set, so add IOMAP_F_ATOMIC_BIO for that. These changes were suggested by Christoph Hellwig and Dave Chinner. Signed-off-by: John Garry <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent aacd436 commit 370a6de

File tree

6 files changed

+37
-30
lines changed

6 files changed

+37
-30
lines changed

Documentation/filesystems/iomap/operations.rst

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -514,29 +514,32 @@ IOMAP_WRITE`` with any combination of the following enhancements:
514514
if the mapping is unwritten and the filesystem cannot handle zeroing
515515
the unaligned regions without exposing stale contents.
516516

517-
* ``IOMAP_ATOMIC_HW``: This write is being issued with torn-write
518-
protection based on HW-offload support.
519-
Only a single bio can be created for the write, and the write must
520-
not be split into multiple I/O requests, i.e. flag REQ_ATOMIC must be
521-
set.
517+
* ``IOMAP_ATOMIC``: This write is being issued with torn-write
518+
protection.
519+
Torn-write protection may be provided based on HW-offload or by a
520+
software mechanism provided by the filesystem.
521+
522+
For HW-offload based support, only a single bio can be created for the
523+
write, and the write must not be split into multiple I/O requests, i.e.
524+
flag REQ_ATOMIC must be set.
522525
The file range to write must be aligned to satisfy the requirements
523526
of both the filesystem and the underlying block device's atomic
524527
commit capabilities.
525528
If filesystem metadata updates are required (e.g. unwritten extent
526-
conversion or copy on write), all updates for the entire file range
529+
conversion or copy-on-write), all updates for the entire file range
527530
must be committed atomically as well.
528-
Only one space mapping is allowed per untorn write.
529-
Untorn writes may be longer than a single file block. In all cases,
531+
Untorn-writes may be longer than a single file block. In all cases,
530532
the mapping start disk block must have at least the same alignment as
531533
the write offset.
532-
533-
* ``IOMAP_ATOMIC_SW``: This write is being issued with torn-write
534-
protection via a software mechanism provided by the filesystem.
535-
All the disk block alignment and single bio restrictions which apply
536-
to IOMAP_ATOMIC_HW do not apply here.
537-
SW-based untorn writes would typically be used as a fallback when
538-
HW-based untorn writes may not be issued, e.g. the range of the write
539-
covers multiple extents, meaning that it is not possible to issue
534+
The filesystems must set IOMAP_F_ATOMIC_BIO to inform iomap core of an
535+
untorn-write based on HW-offload.
536+
537+
For untorn-writes based on a software mechanism provided by the
538+
filesystem, all the disk block alignment and single bio restrictions
539+
which apply for HW-offload based untorn-writes do not apply.
540+
The mechanism would typically be used as a fallback for when
541+
HW-offload based untorn-writes may not be issued, e.g. the range of the
542+
write covers multiple extents, meaning that it is not possible to issue
540543
a single bio.
541544
All filesystem metadata updates for the entire file range must be
542545
committed atomically as well.

fs/ext4/inode.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3290,6 +3290,10 @@ static void ext4_set_iomap(struct inode *inode, struct iomap *iomap,
32903290
if (map->m_flags & EXT4_MAP_NEW)
32913291
iomap->flags |= IOMAP_F_NEW;
32923292

3293+
/* HW-offload atomics are always used */
3294+
if (flags & IOMAP_ATOMIC)
3295+
iomap->flags |= IOMAP_F_ATOMIC_BIO;
3296+
32933297
if (flags & IOMAP_DAX)
32943298
iomap->dax_dev = EXT4_SB(inode->i_sb)->s_daxdev;
32953299
else
@@ -3467,7 +3471,7 @@ static inline bool ext4_want_directio_fallback(unsigned flags, ssize_t written)
34673471
return false;
34683472

34693473
/* atomic writes are all-or-nothing */
3470-
if (flags & IOMAP_ATOMIC_HW)
3474+
if (flags & IOMAP_ATOMIC)
34713475
return false;
34723476

34733477
/* can only try again if we wrote nothing */

fs/iomap/direct-io.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
349349
if (dio->flags & IOMAP_DIO_WRITE) {
350350
bio_opf |= REQ_OP_WRITE;
351351

352-
if (iter->flags & IOMAP_ATOMIC_HW) {
352+
if (iomap->flags & IOMAP_F_ATOMIC_BIO) {
353353
/*
354354
* Ensure that the mapping covers the full write
355355
* length, otherwise it won't be submitted as a single
@@ -677,10 +677,8 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
677677
iomi.flags |= IOMAP_OVERWRITE_ONLY;
678678
}
679679

680-
if (dio_flags & IOMAP_DIO_ATOMIC_SW)
681-
iomi.flags |= IOMAP_ATOMIC_SW;
682-
else if (iocb->ki_flags & IOCB_ATOMIC)
683-
iomi.flags |= IOMAP_ATOMIC_HW;
680+
if (iocb->ki_flags & IOCB_ATOMIC)
681+
iomi.flags |= IOMAP_ATOMIC;
684682

685683
/* for data sync or sync, we need sync completion processing */
686684
if (iocb_is_dsync(iocb)) {

fs/iomap/trace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ DEFINE_RANGE_EVENT(iomap_dio_rw_queued);
9999
{ IOMAP_FAULT, "FAULT" }, \
100100
{ IOMAP_DIRECT, "DIRECT" }, \
101101
{ IOMAP_NOWAIT, "NOWAIT" }, \
102-
{ IOMAP_ATOMIC_HW, "ATOMIC_HW" }
102+
{ IOMAP_ATOMIC, "ATOMIC" }
103103

104104
#define IOMAP_F_FLAGS_STRINGS \
105105
{ IOMAP_F_NEW, "NEW" }, \

fs/xfs/xfs_iomap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,10 @@ xfs_direct_write_iomap_begin(
828828
if (offset + length > i_size_read(inode))
829829
iomap_flags |= IOMAP_F_DIRTY;
830830

831+
/* HW-offload atomics are always used in this path */
832+
if (flags & IOMAP_ATOMIC)
833+
iomap_flags |= IOMAP_F_ATOMIC_BIO;
834+
831835
/*
832836
* COW writes may allocate delalloc space or convert unwritten COW
833837
* extents, so we need to make sure to take the lock exclusively here.

include/linux/iomap.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ struct vm_fault;
6060
* IOMAP_F_ANON_WRITE indicates that (write) I/O does not have a target block
6161
* assigned to it yet and the file system will do that in the bio submission
6262
* handler, splitting the I/O as needed.
63+
*
64+
* IOMAP_F_ATOMIC_BIO indicates that (write) I/O will be issued as an atomic
65+
* bio, i.e. set REQ_ATOMIC.
6366
*/
6467
#define IOMAP_F_NEW (1U << 0)
6568
#define IOMAP_F_DIRTY (1U << 1)
@@ -73,6 +76,7 @@ struct vm_fault;
7376
#define IOMAP_F_XATTR (1U << 5)
7477
#define IOMAP_F_BOUNDARY (1U << 6)
7578
#define IOMAP_F_ANON_WRITE (1U << 7)
79+
#define IOMAP_F_ATOMIC_BIO (1U << 8)
7680

7781
/*
7882
* Flags set by the core iomap code during operations:
@@ -189,9 +193,8 @@ struct iomap_folio_ops {
189193
#else
190194
#define IOMAP_DAX 0
191195
#endif /* CONFIG_FS_DAX */
192-
#define IOMAP_ATOMIC_HW (1 << 9) /* HW-based torn-write protection */
196+
#define IOMAP_ATOMIC (1 << 9) /* torn-write protection */
193197
#define IOMAP_DONTCACHE (1 << 10)
194-
#define IOMAP_ATOMIC_SW (1 << 11)/* SW-based torn-write protection */
195198

196199
struct iomap_ops {
197200
/*
@@ -503,11 +506,6 @@ struct iomap_dio_ops {
503506
*/
504507
#define IOMAP_DIO_PARTIAL (1 << 2)
505508

506-
/*
507-
* Use software-based torn-write protection.
508-
*/
509-
#define IOMAP_DIO_ATOMIC_SW (1 << 3)
510-
511509
ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
512510
const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
513511
unsigned int dio_flags, void *private, size_t done_before);

0 commit comments

Comments
 (0)