Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'fs_for_v7.0-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull udf fix from Jan Kara:
"Fix for a race in UDF that can lead to memory corruption"

* tag 'fs_for_v7.0-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
udf: Fix race between file type conversion and writeback
mpage: Provide variant of mpage_writepages() with own optional folio handler

+48 -26
+24 -6
fs/mpage.c
··· 646 646 } 647 647 648 648 /** 649 - * mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them 649 + * __mpage_writepages - walk the list of dirty pages of the given address space 650 + * & writepage() all of them 650 651 * @mapping: address space structure to write 651 652 * @wbc: subtract the number of written pages from *@wbc->nr_to_write 652 653 * @get_block: the filesystem's block mapper function. 654 + * @write_folio: handler to call for each folio before calling 655 + * mpage_write_folio() 653 656 * 654 657 * This is a library function, which implements the writepages() 655 - * address_space_operation. 658 + * address_space_operation. It calls @write_folio handler for each folio. If 659 + * the handler returns value > 0, it calls mpage_write_folio() to do the 660 + * folio writeback. 656 661 */ 657 662 int 658 - mpage_writepages(struct address_space *mapping, 659 - struct writeback_control *wbc, get_block_t get_block) 663 + __mpage_writepages(struct address_space *mapping, 664 + struct writeback_control *wbc, get_block_t get_block, 665 + int (*write_folio)(struct folio *folio, 666 + struct writeback_control *wbc)) 660 667 { 661 668 struct mpage_data mpd = { 662 669 .get_block = get_block, ··· 673 666 int error; 674 667 675 668 blk_start_plug(&plug); 676 - while ((folio = writeback_iter(mapping, wbc, folio, &error))) 669 + while ((folio = writeback_iter(mapping, wbc, folio, &error))) { 670 + if (write_folio) { 671 + error = write_folio(folio, wbc); 672 + /* 673 + * == 0 means folio is handled, < 0 means error. In 674 + * both cases hand back control to writeback_iter() 675 + */ 676 + if (error <= 0) 677 + continue; 678 + /* Let mpage_write_folio() handle the folio. */ 679 + } 677 680 error = mpage_write_folio(wbc, folio, &mpd); 681 + } 678 682 if (mpd.bio) 679 683 mpage_bio_submit_write(mpd.bio); 680 684 blk_finish_plug(&plug); 681 685 return error; 682 686 } 683 - EXPORT_SYMBOL(mpage_writepages); 687 + EXPORT_SYMBOL(__mpage_writepages);
+15 -18
fs/udf/inode.c
··· 181 181 } 182 182 } 183 183 184 - static int udf_adinicb_writepages(struct address_space *mapping, 185 - struct writeback_control *wbc) 184 + static int udf_handle_page_wb(struct folio *folio, 185 + struct writeback_control *wbc) 186 186 { 187 - struct inode *inode = mapping->host; 187 + struct inode *inode = folio->mapping->host; 188 188 struct udf_inode_info *iinfo = UDF_I(inode); 189 - struct folio *folio = NULL; 190 - int error = 0; 191 189 192 - while ((folio = writeback_iter(mapping, wbc, folio, &error))) { 193 - BUG_ON(!folio_test_locked(folio)); 194 - BUG_ON(folio->index != 0); 195 - memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio, 190 + /* 191 + * Inodes in the normal format are handled by the generic code. This 192 + * check is race-free as the folio lock protects us from inode type 193 + * conversion. 194 + */ 195 + if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) 196 + return 1; 197 + 198 + memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio, 196 199 0, i_size_read(inode)); 197 - folio_unlock(folio); 198 - } 199 - 200 + folio_unlock(folio); 200 201 mark_inode_dirty(inode); 201 202 return 0; 202 203 } ··· 205 204 static int udf_writepages(struct address_space *mapping, 206 205 struct writeback_control *wbc) 207 206 { 208 - struct inode *inode = mapping->host; 209 - struct udf_inode_info *iinfo = UDF_I(inode); 210 - 211 - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 212 - return udf_adinicb_writepages(mapping, wbc); 213 - return mpage_writepages(mapping, wbc, udf_get_block_wb); 207 + return __mpage_writepages(mapping, wbc, udf_get_block_wb, 208 + udf_handle_page_wb); 214 209 } 215 210 216 211 static void udf_adinicb_read_folio(struct folio *folio)
+9 -2
include/linux/mpage.h
··· 17 17 18 18 void mpage_readahead(struct readahead_control *, get_block_t get_block); 19 19 int mpage_read_folio(struct folio *folio, get_block_t get_block); 20 - int mpage_writepages(struct address_space *mapping, 21 - struct writeback_control *wbc, get_block_t get_block); 20 + int __mpage_writepages(struct address_space *mapping, 21 + struct writeback_control *wbc, get_block_t get_block, 22 + int (*write_folio)(struct folio *folio, 23 + struct writeback_control *wbc)); 24 + static inline int mpage_writepages(struct address_space *mapping, 25 + struct writeback_control *wbc, get_block_t get_block) 26 + { 27 + return __mpage_writepages(mapping, wbc, get_block, NULL); 28 + } 22 29 23 30 #endif