f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read
Hello,
Observed below deadlock with quota enabled on f2fs during low memory situation. I think during f2fs_quota_enable -> which is doing read_cache_page with __GFP_FS flag set, due to low memory this is causing shrinker to get invoked and thus going into a deadlock due to mutex lock in dquota. Commit details in next patch contains the call stack.
Since I did not had the quota enabled on f2fs configuration, I could not test this on my setup yet.
Could the community kindly review and let me know if the patch is correct or not ?
Ritesh Harjani (1):
f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read
fs/f2fs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
PATCH 1/1 f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read
Quota code itself is serializing the operations by taking mutex_lock. It seems a below deadlock can happen if GF_NOFS is not used in f2fs_quota_read
__switch_to+0x88__schedule+0x5b0schedule+0x78schedule_preempt_disabled+0x20__mutex_lock_slowpath+0xdc //mutex owner is itselfmutex_lock+0x2cdquot_commit+0x30 //mutex_lock(&dqopt->dqio_mutex);dqput+0xe0__dquot_drop+0x80dquot_drop+0x48f2fs_evict_inode+0x218evict+0xa8dispose_list+0x3cprune_icache_sb+0x58super_cache_scan+0xf4do_shrink_slab+0x208
shrink_slab.part.40+0xacshrink_zone+0x1b0do_try_to_free_pages+0x25ctry_to_free_pages+0x164__alloc_pages_nodemask+0x534do_read_cache_page+0x6cread_cache_page+0x14f2fs_quota_read+0xa4read_blk+0x54find_tree_dqentry+0xe4find_tree_dqentry+0xb8find_tree_dqentry+0xb8find_tree_dqentry+0xb8qtree_read_dquot+0x68v2_read_dquot+0x24dquot_acquire+0x5c // mutex_lock(&dqopt->dqio_mutex);dqget+0x238__dquot_initialize+0xd4dquot_initialize+0x10dquot_file_open+0x34f2fs_file_open+0x6cdo_dentry_open+0x1e4vfs_open+0x6cpath_openat+0xa20do_filp_open+0x4cdo_sys_open+0x178
--- fs/f2fs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/f2fs/super.c +1 -1
@@ -1382,7 +1382,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data,while (toread >0 ) { tocopy = min_t(unsigned long, sb->s_blocksize - offset, toread); repeat: - page =read_mapping_page (mapping, blkidx,NULL ); + page =read_cache_page_gfp (mapping, blkidx,GFP_NOFS );if (IS_ERR (page)) {if (PTR_ERR (page) == -ENOMEM ) {congestion_wait (BLK_RW_ASYNC ,HZ /50 );
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Quoted 47 lines · Ritesh Harjani
Quota code itself is serializing the operations by taking
mutex_lock. It seems a below deadlock can happen ifGF_NOFSis not used inf2fs_quota_read
__switch_to+0x88__schedule+0x5b0schedule+0x78schedule_preempt_disabled+0x20__mutex_lock_slowpath+0xdc//mutex owner is itselfmutex_lock+0x2cdquot_commit+0x30//mutex_lock(&dqopt->dqio_mutex);dqput+0xe0__dquot_drop+0x80dquot_drop+0x48f2fs_evict_inode+0x218evict+0xa8dispose_list+0x3cprune_icache_sb+0x58super_cache_scan+0xf4do_shrink_slab+0x208
shrink_slab.part.40+0xacshrink_zone+0x1b0do_try_to_free_pages+0x25ctry_to_free_pages+0x164__alloc_pages_nodemask+0x534do_read_cache_page+0x6cread_cache_page+0x14f2fs_quota_read+0xa4read_blk+0x54find_tree_dqentry+0xe4find_tree_dqentry+0xb8find_tree_dqentry+0xb8find_tree_dqentry+0xb8qtree_read_dquot+0x68v2_read_dquot+0x24dquot_acquire+0x5c//mutex_lock(&dqopt->dqio_mutex);dqget+0x238__dquot_initialize+0xd4dquot_initialize+0x10dquot_file_open+0x34f2fs_file_open+0x6cdo_dentry_open+0x1e4vfs_open+0x6cpath_openat+0xa20do_filp_open+0x4cdo_sys_open+0x178
Quoted 1 line
Signed-off-by Ritesh Harjani <[email protected]>
Thanks,