2024-04-10 15:13:40

by Zhang Yi

[permalink] [raw]
Subject: [RESEND RFC PATCH v4 00/34] ext4: use iomap for regular file's buffered IO path and enable large folio

Hello!

This is the fourth version of RFC patch series that convert ext4 regular
file's buffered IO path to iomap and enable large folio. I've rebased it
on 6.9-rc3, it also **depends on my xfs/iomap fix series** which has
been reviewed but not merged yet[1]. Compared to the third vesion, this
iteration fixes an issue discovered in current ext4 code, and contains
another two main changes, 1) add bigalloc support and 2) simplify the
updating logic of reserved delalloc data block, both changes could be
sent out as preliminary patch series, besides these, others are some
small code cleanups, performance optimize and commit log improvements.
Please take a look at this series and any comments are welcome.

This series supports ext4 with the default features and mount
options(bigalloc is also supported), doesn't support non-extent(ext3),
inline_data, dax, fs_verity, fs_crypt and data=journal mode, ext4 would
fall back to buffer_head path automatically if you enabled those
features or options. Although it has many limitations now, it can satisfy
the requirements of most common cases and bring a significant performance
benefit for large IOs.

The iomap path would be simpler than the buffer_head path to some extent,
please note that there are 4 major differences:
1. Always allocate unwritten extent for new blocks, it means that it's
not controlled by dioread_nolock mount option.
2. Since 1, there is no risk of exposing stale data during the append
write, so we don't need to write back data before metadata, it's time
to drop 'data = ordered' mode automatically.
3. Since 2, we don't need to reserve journal credits and use reserved
handle for the extent status conversion during writeback.
4. We could postpone updating the i_disksize to the endio, it could
avoid exposing zero data during append write and instantaneous power
failure.

Series details:
Patch 1-9: this is the part 2 preparation series, it fix a problem
first, and makes ext4_insert_delayed_block() call path support inserting
multiple delalloc blocks (also support bigalloc), finally make
ext4_da_map_blocks() buffer_head unaware, I've send it out separately[2]
and hope this could be merged first.

Patch 10-19: this is the part 3 prepartory changes(picked out from my
metadata reservation series[3], these are not a strong dependency
patches, but I'd suggested these could be merged before the iomap
conversion). These patches moves ext4_da_update_reserve_space() to
ext4_es_insert_extent(), and always set EXT4_GET_BLOCKS_DELALLOC_RESERVE
when allocating delalloc blocks, no matter it's from delayed allocate or
non-delayed allocate (fallocate) path, it makes delalloc extents always
delonly. These can make delalloc reservation simpler and cleaner than
before.

Patch 20-34: These patches are the main implements of the buffered IO
iomap conversion, It first introduce a sequence counter for extent
status tree, then add a new iomap aops for read, write, mmap, replace
current buffered_head path. Finally, enable iomap path besides inline
data, non-extent, dax, fs_verity, fs_crypt, defrag and data=journal
mode, if user specify "buffered_iomap" mount option, also enable large
folio. Please look at the following patch for details.

About Tests:
- Pass kvm-xfstests in auto mode, and the keep running stress tests and
fault injection tests.
- A performance tests below (tested on my version 3 series,
theoretically there won't be much difference in this version).

Fio tests with psync on my machine with Intel Xeon Gold 6240 CPU
with 400GB system ram, 200GB ramdisk and 1TB nvme ssd disk.

== buffer read ==

buffer head iomap + large folio
type bs IOPS BW(MiB/s) IOPS BW(MiB/s)
----------------------------------------------------
hole 4K 565k 2206 811k 3167
hole 64K 45.1k 2820 78.1k 4879
hole 1M 2744 2744 4890 4891
ramdisk 4K 436k 1703 554k 2163
ramdisk 64K 29.6k 1848 44.0k 2747
ramdisk 1M 1994 1995 2809 2809
nvme 4K 306k 1196 324k 1267
nvme 64K 19.3k 1208 24.3k 1517
nvme 1M 1694 1694 2256 2256

== buffer write ==

buffer head iomap + large folio
type Overwrite Sync Writeback bs IOPS BW IOPS BW
------------------------------------------------------------
cache N N N 4K 395k 1544 415k 1621
cache N N N 64K 30.8k 1928 80.1k 5005
cache N N N 1M 1963 1963 5641 5642
cache Y N N 4K 423k 1652 443k 1730
cache Y N N 64K 33.0k 2063 80.8k 5051
cache Y N N 1M 2103 2103 5588 5589
ramdisk N N Y 4K 362k 1416 307k 1198
ramdisk N N Y 64K 22.4k 1399 64.8k 4050
ramdisk N N Y 1M 1670 1670 4559 4560
ramdisk N Y N 4K 9830 38.4 13.5k 52.8
ramdisk N Y N 64K 5834 365 10.1k 629
ramdisk N Y N 1M 1011 1011 2064 2064
ramdisk Y N Y 4K 397k 1550 409k 1598
ramdisk Y N Y 64K 29.2k 1827 73.6k 4597
ramdisk Y N Y 1M 1837 1837 4985 4985
ramdisk Y Y N 4K 173k 675 182k 710
ramdisk Y Y N 64K 17.7k 1109 33.7k 2105
ramdisk Y Y N 1M 1128 1129 1790 1791
nvme N N Y 4K 298k 1164 290k 1134
nvme N N Y 64K 21.5k 1343 57.4k 3590
nvme N N Y 1M 1308 1308 3664 3664
nvme N Y N 4K 10.7k 41.8 12.0k 46.9
nvme N Y N 64K 5962 373 8598 537
nvme N Y N 1M 676 677 1417 1418
nvme Y N Y 4K 366k 1430 373k 1456
nvme Y N Y 64K 26.7k 1670 56.8k 3547
nvme Y N Y 1M 1745 1746 3586 3586
nvme Y Y N 4K 59.0k 230 61.2k 239
nvme Y Y N 64K 13.0k 813 21.0k 1311
nvme Y Y N 1M 683 683 1368 1369

TODO
- Keep on doing stress tests and fixing.
- Reserve enough space for delalloc metadata blocks and try to drop
ext4_nonda_switch().
- First support defrag and then support other more unsupported features
and mount options.

Changes since v3:
- Drop the part 1 prepartory patches which have been merged [4].
- Drop the two iomap patches since I've submitted separately [1].
- Fix an incorrect reserved delalloc blocks count and incorrect extent
status cache issue found on current ext4 code.
- Pick out part 2 prepartory patch series [2], it make
ext4_insert_delayed_block() call path support inserting multiple
delalloc blocks (also support bigalloc )and make ext4_da_map_blocks()
buffer_head unaware.
- Adjust and simplify the reserved delalloc blocks updating logic,
preparing for reserving meta data blocks for delalloc.
- Drop datasync dirty check in ext4_set_iomap() for buffered
read/write, improves the concurrent performance on small I/Os.
- Prevent always hold invalid_lock in page_cache_ra_order(), add
lockless check.
- Disable iomap path by default since it's experimental new, add a
mount option "buffered_iomap" to enable it.
- Some other minor fixes and change log improvements.
Changes since v2:
- Update patch 1-6 to v3.
- iomap_zero and iomap_unshare don't need to update i_size and call
iomap_write_failed(), introduce a new helper iomap_write_end_simple()
to avoid doing that.
- Factor out ext4_[ext|ind]_map_blocks() parts from ext4_map_blocks(),
introduce a new helper ext4_iomap_map_one_extent() to allocate
delalloc blocks in writeback, which is always under i_data_sem in
write mode. This is done to prevent the writing back delalloc
extents become stale if it raced by truncate.
- Add a lock detection in mapping_clear_large_folios().
Changes since v1:
- Introduce seq count for iomap buffered write and writeback to protect
races from extents changes, e.g. truncate, mwrite.
- Always allocate unwritten extents for new blocks, drop dioread_lock
mode, and make no distinctions between dioread_lock and
dioread_nolock.
- Don't add ditry data range to jinode, drop data=ordered mode, and
make no distinctions between data=ordered and data=writeback mode.
- Postpone updating i_disksize to endio.
- Allow splitting extents and use reserved space in endio.
- Instead of reimplement a new delayed mapping helper
ext4_iomap_da_map_blocks() for buffer write, try to reuse
ext4_da_map_blocks().
- Add support for disabling large folio on active inodes.
- Support online defragmentation, make file fall back to buffer_head
and disable large folio in ext4_move_extents().
- Move ext4_nonda_switch() in advance to prevent deadlock in mwrite.
- Add dirty_len and pos trace info to trace_iomap_writepage_map().
- Update patch 1-6 to v2.

[1] https://lore.kernel.org/linux-xfs/[email protected]/
[2] https://lore.kernel.org/linux-ext4/[email protected]/
[3] https://lore.kernel.org/linux-ext4/[email protected]/
[4] https://lore.kernel.org/linux-ext4/[email protected]/

Thanks,
Yi.

---
v3: https://lore.kernel.org/linux-ext4/[email protected]/
v2: https://lore.kernel.org/linux-ext4/[email protected]/
v1: https://lore.kernel.org/linux-ext4/[email protected]/

Zhang Yi (34):
ext4: factor out a common helper to query extent map
ext4: check the extent status again before inserting delalloc block
ext4: trim delalloc extent
ext4: drop iblock parameter
ext4: make ext4_es_insert_delayed_block() insert multi-blocks
ext4: make ext4_da_reserve_space() reserve multi-clusters
ext4: factor out check for whether a cluster is allocated
ext4: make ext4_insert_delayed_block() insert multi-blocks
ext4: make ext4_da_map_blocks() buffer_head unaware
ext4: factor out ext4_map_create_blocks() to allocate new blocks
ext4: optimize the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag set
ext4: don't set EXTENT_STATUS_DELAYED on allocated blocks
ext4: let __revise_pending() return newly inserted pendings
ext4: count removed reserved blocks for delalloc only extent entry
ext4: update delalloc data reserve spcae in ext4_es_insert_extent()
ext4: drop ext4_es_delayed_clu()
ext4: use ext4_map_query_blocks() in ext4_map_blocks()
ext4: drop ext4_es_is_delonly()
ext4: drop all delonly descriptions
ext4: use reserved metadata blocks when splitting extent on endio
ext4: introduce seq counter for the extent status entry
ext4: add a new iomap aops for regular file's buffered IO path
ext4: implement buffered read iomap path
ext4: implement buffered write iomap path
ext4: implement writeback iomap path
ext4: implement mmap iomap path
ext4: implement zero_range iomap path
ext4: writeback partial blocks before zeroing out range
ext4: fall back to buffer_head path for defrag
ext4: partial enable iomap for regular file's buffered IO path
filemap: support disable large folios on active inode
ext4: enable large folio for regular file with iomap buffered IO path
ext4: don't mark IOMAP_F_DIRTY for buffer write
ext4: add mount option for buffered IO iomap path

--
2.39.2



2024-04-10 15:18:35

by Zhang Yi

[permalink] [raw]
Subject: [PATCH v4 05/34] ext4: make ext4_es_insert_delayed_block() insert multi-blocks

From: Zhang Yi <[email protected]>

Rename ext4_es_insert_delayed_block() to ext4_es_insert_delayed_extent()
and pass length parameter to make it insert multi delalloc blocks once a
time. For the case of bigalloc, expand the allocated parameter to
lclu_allocated and end_allocated. lclu_allocated indicates the allocate
state of the cluster which containing the lblk, end_allocated represents
the end, and the middle clusters must be unallocated.

Signed-off-by: Zhang Yi <[email protected]>
---
fs/ext4/extents_status.c | 63 ++++++++++++++++++++++++-------------
fs/ext4/extents_status.h | 5 +--
fs/ext4/inode.c | 2 +-
include/trace/events/ext4.h | 16 +++++-----
4 files changed, 55 insertions(+), 31 deletions(-)

diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 4a00e2f019d9..2320b0d71001 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -2052,34 +2052,42 @@ bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk)
}

/*
- * ext4_es_insert_delayed_block - adds a delayed block to the extents status
- * tree, adding a pending reservation where
- * needed
+ * ext4_es_insert_delayed_extent - adds some delayed blocks to the extents
+ * status tree, adding a pending reservation
+ * where needed
*
* @inode - file containing the newly added block
- * @lblk - logical block to be added
- * @allocated - indicates whether a physical cluster has been allocated for
- * the logical cluster that contains the block
+ * @lblk - start logical block to be added
+ * @len - length of blocks to be added
+ * @lclu_allocated/end_allocated - indicates whether a physical cluster has
+ * been allocated for the logical cluster
+ * that contains the block
*/
-void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
- bool allocated)
+void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+ ext4_lblk_t len, bool lclu_allocated,
+ bool end_allocated)
{
struct extent_status newes;
+ ext4_lblk_t end = lblk + len - 1;
int err1 = 0, err2 = 0, err3 = 0;
struct extent_status *es1 = NULL;
struct extent_status *es2 = NULL;
- struct pending_reservation *pr = NULL;
+ struct pending_reservation *pr1 = NULL;
+ struct pending_reservation *pr2 = NULL;

if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
return;

- es_debug("add [%u/1) delayed to extent status tree of inode %lu\n",
- lblk, inode->i_ino);
+ es_debug("add [%u/%u) delayed to extent status tree of inode %lu\n",
+ lblk, len, inode->i_ino);
+ if (!len)
+ return;

newes.es_lblk = lblk;
- newes.es_len = 1;
+ newes.es_len = len;
ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED);
- trace_ext4_es_insert_delayed_block(inode, &newes, allocated);
+ trace_ext4_es_insert_delayed_extent(inode, &newes, lclu_allocated,
+ end_allocated);

ext4_es_insert_extent_check(inode, &newes);

@@ -2088,11 +2096,15 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
es1 = __es_alloc_extent(true);
if ((err1 || err2) && !es2)
es2 = __es_alloc_extent(true);
- if ((err1 || err2 || err3) && allocated && !pr)
- pr = __alloc_pending(true);
+ if (err1 || err2 || err3) {
+ if (lclu_allocated && !pr1)
+ pr1 = __alloc_pending(true);
+ if (end_allocated && !pr2)
+ pr2 = __alloc_pending(true);
+ }
write_lock(&EXT4_I(inode)->i_es_lock);

- err1 = __es_remove_extent(inode, lblk, lblk, NULL, es1);
+ err1 = __es_remove_extent(inode, lblk, end, NULL, es1);
if (err1 != 0)
goto error;
/* Free preallocated extent if it didn't get used. */
@@ -2112,13 +2124,22 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
es2 = NULL;
}

- if (allocated) {
- err3 = __insert_pending(inode, lblk, &pr);
+ if (lclu_allocated) {
+ err3 = __insert_pending(inode, lblk, &pr1);
if (err3 != 0)
goto error;
- if (pr) {
- __free_pending(pr);
- pr = NULL;
+ if (pr1) {
+ __free_pending(pr1);
+ pr1 = NULL;
+ }
+ }
+ if (end_allocated) {
+ err3 = __insert_pending(inode, end, &pr2);
+ if (err3 != 0)
+ goto error;
+ if (pr2) {
+ __free_pending(pr2);
+ pr2 = NULL;
}
}
error:
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index d9847a4a25db..3c8e2edee5d5 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -249,8 +249,9 @@ extern void ext4_exit_pending(void);
extern void ext4_init_pending_tree(struct ext4_pending_tree *tree);
extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk);
extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk);
-extern void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
- bool allocated);
+extern void ext4_es_insert_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
+ ext4_lblk_t len, bool lclu_allocated,
+ bool end_allocated);
extern unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk,
ext4_lblk_t len);
extern void ext4_clear_inode_es(struct inode *inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cccc16506f5f..d37233e2ed0b 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1702,7 +1702,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
}
}

- ext4_es_insert_delayed_block(inode, lblk, allocated);
+ ext4_es_insert_delayed_extent(inode, lblk, 1, allocated, false);
return 0;
}

diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index a697f4b77162..6b41ac61310f 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -2478,11 +2478,11 @@ TRACE_EVENT(ext4_es_shrink,
__entry->scan_time, __entry->nr_skipped, __entry->retried)
);

-TRACE_EVENT(ext4_es_insert_delayed_block,
+TRACE_EVENT(ext4_es_insert_delayed_extent,
TP_PROTO(struct inode *inode, struct extent_status *es,
- bool allocated),
+ bool lclu_allocated, bool end_allocated),

- TP_ARGS(inode, es, allocated),
+ TP_ARGS(inode, es, lclu_allocated, end_allocated),

TP_STRUCT__entry(
__field( dev_t, dev )
@@ -2491,7 +2491,8 @@ TRACE_EVENT(ext4_es_insert_delayed_block,
__field( ext4_lblk_t, len )
__field( ext4_fsblk_t, pblk )
__field( char, status )
- __field( bool, allocated )
+ __field( bool, lclu_allocated )
+ __field( bool, end_allocated )
),

TP_fast_assign(
@@ -2501,16 +2502,17 @@ TRACE_EVENT(ext4_es_insert_delayed_block,
__entry->len = es->es_len;
__entry->pblk = ext4_es_show_pblock(es);
__entry->status = ext4_es_status(es);
- __entry->allocated = allocated;
+ __entry->lclu_allocated = lclu_allocated;
+ __entry->end_allocated = end_allocated;
),

TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s "
- "allocated %d",
+ "allocated %d %d",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino,
__entry->lblk, __entry->len,
__entry->pblk, show_extent_status(__entry->status),
- __entry->allocated)
+ __entry->lclu_allocated, __entry->end_allocated)
);

/* fsmap traces */
--
2.39.2


2024-04-24 08:12:57

by Zhang Yi

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH v4 00/34] ext4: use iomap for regular file's buffered IO path and enable large folio

Hi Ted and Jan,

I'm almost done with the first phase of this iomap conversion for
regular file's buffered IO path, could you please take time to take
a look at this series, I'd appreciated if I could get some feedback
and comments before the next phase of development, or is there any
plan to merge this series?

Thanks,
Yi.

On 2024/4/10 22:29, Zhang Yi wrote:
> Hello!
>
> This is the fourth version of RFC patch series that convert ext4 regular
> file's buffered IO path to iomap and enable large folio. I've rebased it
> on 6.9-rc3, it also **depends on my xfs/iomap fix series** which has
> been reviewed but not merged yet[1]. Compared to the third vesion, this
> iteration fixes an issue discovered in current ext4 code, and contains
> another two main changes, 1) add bigalloc support and 2) simplify the
> updating logic of reserved delalloc data block, both changes could be
> sent out as preliminary patch series, besides these, others are some
> small code cleanups, performance optimize and commit log improvements.
> Please take a look at this series and any comments are welcome.
>
> This series supports ext4 with the default features and mount
> options(bigalloc is also supported), doesn't support non-extent(ext3),
> inline_data, dax, fs_verity, fs_crypt and data=journal mode, ext4 would
> fall back to buffer_head path automatically if you enabled those
> features or options. Although it has many limitations now, it can satisfy
> the requirements of most common cases and bring a significant performance
> benefit for large IOs.
>
> The iomap path would be simpler than the buffer_head path to some extent,
> please note that there are 4 major differences:
> 1. Always allocate unwritten extent for new blocks, it means that it's
> not controlled by dioread_nolock mount option.
> 2. Since 1, there is no risk of exposing stale data during the append
> write, so we don't need to write back data before metadata, it's time
> to drop 'data = ordered' mode automatically.
> 3. Since 2, we don't need to reserve journal credits and use reserved
> handle for the extent status conversion during writeback.
> 4. We could postpone updating the i_disksize to the endio, it could
> avoid exposing zero data during append write and instantaneous power
> failure.
>
> Series details:
> Patch 1-9: this is the part 2 preparation series, it fix a problem
> first, and makes ext4_insert_delayed_block() call path support inserting
> multiple delalloc blocks (also support bigalloc), finally make
> ext4_da_map_blocks() buffer_head unaware, I've send it out separately[2]
> and hope this could be merged first.
>
> Patch 10-19: this is the part 3 prepartory changes(picked out from my
> metadata reservation series[3], these are not a strong dependency
> patches, but I'd suggested these could be merged before the iomap
> conversion). These patches moves ext4_da_update_reserve_space() to
> ext4_es_insert_extent(), and always set EXT4_GET_BLOCKS_DELALLOC_RESERVE
> when allocating delalloc blocks, no matter it's from delayed allocate or
> non-delayed allocate (fallocate) path, it makes delalloc extents always
> delonly. These can make delalloc reservation simpler and cleaner than
> before.
>
> Patch 20-34: These patches are the main implements of the buffered IO
> iomap conversion, It first introduce a sequence counter for extent
> status tree, then add a new iomap aops for read, write, mmap, replace
> current buffered_head path. Finally, enable iomap path besides inline
> data, non-extent, dax, fs_verity, fs_crypt, defrag and data=journal
> mode, if user specify "buffered_iomap" mount option, also enable large
> folio. Please look at the following patch for details.
>
> About Tests:
> - Pass kvm-xfstests in auto mode, and the keep running stress tests and
> fault injection tests.
> - A performance tests below (tested on my version 3 series,
> theoretically there won't be much difference in this version).
>
> Fio tests with psync on my machine with Intel Xeon Gold 6240 CPU
> with 400GB system ram, 200GB ramdisk and 1TB nvme ssd disk.
>
> == buffer read ==
>
> buffer head iomap + large folio
> type bs IOPS BW(MiB/s) IOPS BW(MiB/s)
> ----------------------------------------------------
> hole 4K 565k 2206 811k 3167
> hole 64K 45.1k 2820 78.1k 4879
> hole 1M 2744 2744 4890 4891
> ramdisk 4K 436k 1703 554k 2163
> ramdisk 64K 29.6k 1848 44.0k 2747
> ramdisk 1M 1994 1995 2809 2809
> nvme 4K 306k 1196 324k 1267
> nvme 64K 19.3k 1208 24.3k 1517
> nvme 1M 1694 1694 2256 2256
>
> == buffer write ==
>
> buffer head iomap + large folio
> type Overwrite Sync Writeback bs IOPS BW IOPS BW
> ------------------------------------------------------------
> cache N N N 4K 395k 1544 415k 1621
> cache N N N 64K 30.8k 1928 80.1k 5005
> cache N N N 1M 1963 1963 5641 5642
> cache Y N N 4K 423k 1652 443k 1730
> cache Y N N 64K 33.0k 2063 80.8k 5051
> cache Y N N 1M 2103 2103 5588 5589
> ramdisk N N Y 4K 362k 1416 307k 1198
> ramdisk N N Y 64K 22.4k 1399 64.8k 4050
> ramdisk N N Y 1M 1670 1670 4559 4560
> ramdisk N Y N 4K 9830 38.4 13.5k 52.8
> ramdisk N Y N 64K 5834 365 10.1k 629
> ramdisk N Y N 1M 1011 1011 2064 2064
> ramdisk Y N Y 4K 397k 1550 409k 1598
> ramdisk Y N Y 64K 29.2k 1827 73.6k 4597
> ramdisk Y N Y 1M 1837 1837 4985 4985
> ramdisk Y Y N 4K 173k 675 182k 710
> ramdisk Y Y N 64K 17.7k 1109 33.7k 2105
> ramdisk Y Y N 1M 1128 1129 1790 1791
> nvme N N Y 4K 298k 1164 290k 1134
> nvme N N Y 64K 21.5k 1343 57.4k 3590
> nvme N N Y 1M 1308 1308 3664 3664
> nvme N Y N 4K 10.7k 41.8 12.0k 46.9
> nvme N Y N 64K 5962 373 8598 537
> nvme N Y N 1M 676 677 1417 1418
> nvme Y N Y 4K 366k 1430 373k 1456
> nvme Y N Y 64K 26.7k 1670 56.8k 3547
> nvme Y N Y 1M 1745 1746 3586 3586
> nvme Y Y N 4K 59.0k 230 61.2k 239
> nvme Y Y N 64K 13.0k 813 21.0k 1311
> nvme Y Y N 1M 683 683 1368 1369
>
> TODO
> - Keep on doing stress tests and fixing.
> - Reserve enough space for delalloc metadata blocks and try to drop
> ext4_nonda_switch().
> - First support defrag and then support other more unsupported features
> and mount options.
>
> Changes since v3:
> - Drop the part 1 prepartory patches which have been merged [4].
> - Drop the two iomap patches since I've submitted separately [1].
> - Fix an incorrect reserved delalloc blocks count and incorrect extent
> status cache issue found on current ext4 code.
> - Pick out part 2 prepartory patch series [2], it make
> ext4_insert_delayed_block() call path support inserting multiple
> delalloc blocks (also support bigalloc )and make ext4_da_map_blocks()
> buffer_head unaware.
> - Adjust and simplify the reserved delalloc blocks updating logic,
> preparing for reserving meta data blocks for delalloc.
> - Drop datasync dirty check in ext4_set_iomap() for buffered
> read/write, improves the concurrent performance on small I/Os.
> - Prevent always hold invalid_lock in page_cache_ra_order(), add
> lockless check.
> - Disable iomap path by default since it's experimental new, add a
> mount option "buffered_iomap" to enable it.
> - Some other minor fixes and change log improvements.
> Changes since v2:
> - Update patch 1-6 to v3.
> - iomap_zero and iomap_unshare don't need to update i_size and call
> iomap_write_failed(), introduce a new helper iomap_write_end_simple()
> to avoid doing that.
> - Factor out ext4_[ext|ind]_map_blocks() parts from ext4_map_blocks(),
> introduce a new helper ext4_iomap_map_one_extent() to allocate
> delalloc blocks in writeback, which is always under i_data_sem in
> write mode. This is done to prevent the writing back delalloc
> extents become stale if it raced by truncate.
> - Add a lock detection in mapping_clear_large_folios().
> Changes since v1:
> - Introduce seq count for iomap buffered write and writeback to protect
> races from extents changes, e.g. truncate, mwrite.
> - Always allocate unwritten extents for new blocks, drop dioread_lock
> mode, and make no distinctions between dioread_lock and
> dioread_nolock.
> - Don't add ditry data range to jinode, drop data=ordered mode, and
> make no distinctions between data=ordered and data=writeback mode.
> - Postpone updating i_disksize to endio.
> - Allow splitting extents and use reserved space in endio.
> - Instead of reimplement a new delayed mapping helper
> ext4_iomap_da_map_blocks() for buffer write, try to reuse
> ext4_da_map_blocks().
> - Add support for disabling large folio on active inodes.
> - Support online defragmentation, make file fall back to buffer_head
> and disable large folio in ext4_move_extents().
> - Move ext4_nonda_switch() in advance to prevent deadlock in mwrite.
> - Add dirty_len and pos trace info to trace_iomap_writepage_map().
> - Update patch 1-6 to v2.
>
> [1] https://lore.kernel.org/linux-xfs/[email protected]/
> [2] https://lore.kernel.org/linux-ext4/[email protected]/
> [3] https://lore.kernel.org/linux-ext4/[email protected]/
> [4] https://lore.kernel.org/linux-ext4/[email protected]/
>
> Thanks,
> Yi.
>
> ---
> v3: https://lore.kernel.org/linux-ext4/[email protected]/
> v2: https://lore.kernel.org/linux-ext4/[email protected]/
> v1: https://lore.kernel.org/linux-ext4/[email protected]/
>
> Zhang Yi (34):
> ext4: factor out a common helper to query extent map
> ext4: check the extent status again before inserting delalloc block
> ext4: trim delalloc extent
> ext4: drop iblock parameter
> ext4: make ext4_es_insert_delayed_block() insert multi-blocks
> ext4: make ext4_da_reserve_space() reserve multi-clusters
> ext4: factor out check for whether a cluster is allocated
> ext4: make ext4_insert_delayed_block() insert multi-blocks
> ext4: make ext4_da_map_blocks() buffer_head unaware
> ext4: factor out ext4_map_create_blocks() to allocate new blocks
> ext4: optimize the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag set
> ext4: don't set EXTENT_STATUS_DELAYED on allocated blocks
> ext4: let __revise_pending() return newly inserted pendings
> ext4: count removed reserved blocks for delalloc only extent entry
> ext4: update delalloc data reserve spcae in ext4_es_insert_extent()
> ext4: drop ext4_es_delayed_clu()
> ext4: use ext4_map_query_blocks() in ext4_map_blocks()
> ext4: drop ext4_es_is_delonly()
> ext4: drop all delonly descriptions
> ext4: use reserved metadata blocks when splitting extent on endio
> ext4: introduce seq counter for the extent status entry
> ext4: add a new iomap aops for regular file's buffered IO path
> ext4: implement buffered read iomap path
> ext4: implement buffered write iomap path
> ext4: implement writeback iomap path
> ext4: implement mmap iomap path
> ext4: implement zero_range iomap path
> ext4: writeback partial blocks before zeroing out range
> ext4: fall back to buffer_head path for defrag
> ext4: partial enable iomap for regular file's buffered IO path
> filemap: support disable large folios on active inode
> ext4: enable large folio for regular file with iomap buffered IO path
> ext4: don't mark IOMAP_F_DIRTY for buffer write
> ext4: add mount option for buffered IO iomap path
>