[PATCH 5.15 059/245] fs/ntfs3: use non-movable memory for ntfs3 MFT buffer cache

Greg Kroah-Hartman
2024-02-27T14:03:58Z

From: Ism Hong <ism.hong@gmail.com>

[ Upstream commit d6d33f03baa43d763fe094ca926eeae7d3421d07 ]

Since the buffer cache for ntfs3 metadata is not released until the file
system is unmounted, allocating from the movable zone may result in cma
allocation failures. This is due to the page still being used by ntfs3,
leading to migration failures.

To address this, this commit use sb_bread_umovable() instead of
sb_bread(). This change prevents allocation from the movable zone,
ensuring compatibility with scenarios where the buffer head is not
released until unmount. This patch is inspired by commit
a8ac900b8163("ext4: use non-movable memory for the ext4 superblock").

The issue is found when playing video files stored in NTFS on the
Android TV platform. During this process, the media parser reads the
video file, causing ntfs3 to allocate buffer cache from the CMA area.
Subsequently, the hardware decoder attempts to allocate memory from the
same CMA area. However, the page is still in use by ntfs3, resulting in
a migrate failure in alloc_contig_range().

The pinned page and allocating stacktrace reported by page owner shows
below:

page:ffffffff00b68880 refcount:3 mapcount:0 mapping:ffffff80046aa828
index:0xc0040 pfn:0x20fa4
aops:def_blk_aops ino:0
flags: 0x2020(active|private)
page dumped because: migration failure
page last allocated via order 0, migratetype Movable,
gfp_mask 0x108c48
(GFP_NOFS|__GFP_NOFAIL|__GFP_HARDWALL|__GFP_MOVABLE),
page_owner tracks the page as allocated
prep_new_page
get_page_from_freelist
__alloc_pages_nodemask
pagecache_get_page
__getblk_gfp
__bread_gfp
ntfs_read_run_nb
ntfs_read_bh
mi_read
ntfs_iget5
dir_search_u
ntfs_lookup
__lookup_slow
lookup_slow
walk_component
path_lookupat

Signed-off-by: Ism Hong <ism.hong@gmail.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ntfs3/ntfs_fs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 9812765000439..ffc8dfbb310ff 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -1014,7 +1014,7 @@ static inline u64 bytes_to_block(const struct super_block *sb, u64 size)
static inline struct buffer_head *ntfs_bread(struct super_block *sb,
sector_t block)
{
- struct buffer_head *bh = sb_bread(sb, block);
+ struct buffer_head *bh = sb_bread_unmovable(sb, block);

if (bh)
return bh;
--
2.43.0