mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ext4: implement mmap path using iomap
Introduce ext4_iomap_page_mkwrite() to implement the mmap iomap path for ext4. The heavy lifting is delegated to iomap_page_mkwrite(), which only requires ext4_iomap_buffered_write_ops and ext4_iomap_buffered_da_write_ops to allocate and map blocks. Note that the lock ordering between folio lock and transaction start in this path is reversed compared to the buffer_head buffered write path. The lock ordering documentation in super.c has been updated accordingly. Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Reviewed-by: Jan Kara <jack@suse.cz> Tested-by: syzbot@syzkaller.appspotmail.com Link: https://patch.msgid.link/20261009103033.2920530-17-yi.zhang@huaweicloud.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
a2e096bf59
commit
e055578dc1
|
|
@ -4040,7 +4040,7 @@ static int ext4_iomap_buffered_do_write_begin(struct inode *inode,
|
|||
return -ERANGE;
|
||||
if (WARN_ON_ONCE(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
|
||||
return -EINVAL;
|
||||
if (WARN_ON_ONCE(!(flags & IOMAP_WRITE)))
|
||||
if (WARN_ON_ONCE(!(flags & (IOMAP_WRITE | IOMAP_FAULT))))
|
||||
return -EINVAL;
|
||||
|
||||
map_flags = delalloc ? EXT4_GET_BLOCKS_DELALLOC_RESERVE :
|
||||
|
|
@ -4098,6 +4098,14 @@ static int ext4_iomap_buffered_da_write_end(struct inode *inode, loff_t offset,
|
|||
if (iomap->type != IOMAP_DELALLOC || !(iomap->flags & IOMAP_F_NEW))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* iomap_page_mkwrite() will never fail in a way that requires delalloc
|
||||
* extents that it allocated to be revoked. Hence never try to release
|
||||
* them here.
|
||||
*/
|
||||
if (flags & IOMAP_FAULT)
|
||||
return 0;
|
||||
|
||||
/* Nothing to do if we've written the entire delalloc extent */
|
||||
start_byte = iomap_last_written_block(inode, offset, written);
|
||||
end_byte = round_up(offset + length, i_blocksize(inode));
|
||||
|
|
@ -7315,6 +7323,23 @@ static int ext4_block_page_mkwrite(struct inode *inode, struct folio *folio,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static vm_fault_t ext4_iomap_page_mkwrite(struct vm_fault *vmf)
|
||||
{
|
||||
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||
const struct iomap_ops *iomap_ops;
|
||||
|
||||
/*
|
||||
* ext4_nonda_switch() could writeback this folio, so have to
|
||||
* call it before lock folio.
|
||||
*/
|
||||
if (test_opt(inode->i_sb, DELALLOC) && !ext4_nonda_switch(inode->i_sb))
|
||||
iomap_ops = &ext4_iomap_buffered_da_write_ops;
|
||||
else
|
||||
iomap_ops = &ext4_iomap_buffered_write_ops;
|
||||
|
||||
return iomap_page_mkwrite(vmf, iomap_ops, NULL);
|
||||
}
|
||||
|
||||
vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
|
|
@ -7341,6 +7366,11 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
|
|||
if (err)
|
||||
goto out_ret;
|
||||
|
||||
if (ext4_inode_buffered_iomap(inode)) {
|
||||
ret = ext4_iomap_page_mkwrite(vmf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* On data journalling we skip straight to the transaction handle:
|
||||
* there's no delalloc; page truncated will be checked later; the
|
||||
|
|
|
|||
|
|
@ -100,8 +100,12 @@ static const struct fs_parameter_spec ext4_param_specs[];
|
|||
* Lock ordering
|
||||
*
|
||||
* page fault path:
|
||||
* mmap_lock -> sb_start_pagefault -> invalidate_lock (r) -> transaction start
|
||||
* -> page lock -> i_data_sem (rw)
|
||||
* - buffer_head path:
|
||||
* mmap_lock -> sb_start_pagefault -> invalidate_lock (r) ->
|
||||
* transaction start -> folio lock -> i_data_sem (rw)
|
||||
* - iomap path:
|
||||
* mmap_lock -> sb_start_pagefault -> invalidate_lock (r) ->
|
||||
* folio lock -> transaction start -> i_data_sem (rw)
|
||||
*
|
||||
* buffered write path:
|
||||
* sb_start_write -> i_rwsem (w) -> mmap_lock
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user