Skip to content

Commit 9558cf1

Browse files
zhangyi089tytso
authored andcommitted
ext4: add nowait mode for ext4_getblk()
Current ext4_getblk() might sleep if some resources are not valid or could be race with a concurrent extents modifing procedure. So we cannot call ext4_getblk() and ext4_map_blocks() to get map blocks in the atomic context in some fast path (e.g. the upcoming procedure of getting symlink external block in the RCU context), even if the map extents have already been check and cached. Signed-off-by: Zhang Yi <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent e4e58e5 commit 9558cf1

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

fs/ext4/ext4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,8 @@ enum {
673673
/* Caller will submit data before dropping transaction handle. This
674674
* allows jbd2 to avoid submitting data before commit. */
675675
#define EXT4_GET_BLOCKS_IO_SUBMIT 0x0400
676+
/* Caller is in the atomic contex, find extent if it has been cached */
677+
#define EXT4_GET_BLOCKS_CACHED_NOWAIT 0x0800
676678

677679
/*
678680
* The bit position of these flags must not overlap with any of the

fs/ext4/inode.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,21 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
545545
} else {
546546
BUG();
547547
}
548+
549+
if (flags & EXT4_GET_BLOCKS_CACHED_NOWAIT)
550+
return retval;
548551
#ifdef ES_AGGRESSIVE_TEST
549552
ext4_map_blocks_es_recheck(handle, inode, map,
550553
&orig_map, flags);
551554
#endif
552555
goto found;
553556
}
557+
/*
558+
* In the query cache no-wait mode, nothing we can do more if we
559+
* cannot find extent in the cache.
560+
*/
561+
if (flags & EXT4_GET_BLOCKS_CACHED_NOWAIT)
562+
return 0;
554563

555564
/*
556565
* Try to see if we can get the block without requesting a new
@@ -837,10 +846,12 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
837846
struct ext4_map_blocks map;
838847
struct buffer_head *bh;
839848
int create = map_flags & EXT4_GET_BLOCKS_CREATE;
849+
bool nowait = map_flags & EXT4_GET_BLOCKS_CACHED_NOWAIT;
840850
int err;
841851

842852
ASSERT((EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
843853
|| handle != NULL || create == 0);
854+
ASSERT(create == 0 || !nowait);
844855

845856
map.m_lblk = block;
846857
map.m_len = 1;
@@ -851,6 +862,9 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
851862
if (err < 0)
852863
return ERR_PTR(err);
853864

865+
if (nowait)
866+
return sb_find_get_block(inode->i_sb, map.m_pblk);
867+
854868
bh = sb_getblk(inode->i_sb, map.m_pblk);
855869
if (unlikely(!bh))
856870
return ERR_PTR(-ENOMEM);

0 commit comments

Comments
 (0)