From 79d3c6dbada4a20193467f72c531ab99c173bf4f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 24 Jan 2023 11:54:08 +0100 Subject: udf: Convert in-ICB files to use udf_writepages() Switching address_space_operations while a file is used is difficult to do in a race-free way. To be able to use single address_space_operations in UDF, make in-ICB files use udf_writepages(). Reported-by: syzbot+c27475eb921c46bbdc62@syzkaller.appspotmail.com Reported-by: Christoph Hellwig Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara --- fs/udf/inode.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'fs/udf/inode.c') diff --git a/fs/udf/inode.c b/fs/udf/inode.c index a1816f067c14..f0ab4dd0d8ce 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -185,10 +185,33 @@ static void udf_write_failed(struct address_space *mapping, loff_t to) } } -static int udf_writepages(struct address_space *mapping, - struct writeback_control *wbc) +static int udf_adinicb_writepage(struct page *page, + struct writeback_control *wbc, void *data) { - return mpage_writepages(mapping, wbc, udf_get_block_wb); + struct inode *inode = page->mapping->host; + char *kaddr; + struct udf_inode_info *iinfo = UDF_I(inode); + + BUG_ON(!PageLocked(page)); + + kaddr = kmap_atomic(page); + memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, i_size_read(inode)); + SetPageUptodate(page); + kunmap_atomic(kaddr); + unlock_page(page); + mark_inode_dirty(inode); + + return 0; +} + +int udf_writepages(struct address_space *mapping, struct writeback_control *wbc) +{ + struct inode *inode = mapping->host; + struct udf_inode_info *iinfo = UDF_I(inode); + + if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) + return mpage_writepages(mapping, wbc, udf_get_block_wb); + return write_cache_pages(mapping, wbc, udf_adinicb_writepage, NULL); } int udf_read_folio(struct file *file, struct folio *folio) -- cgit