-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEq1nRK9aeMoq1VSgcnJ2qBz9kQNkFAmnLsoQACgkQnJ2qBz9k QNmnIAgAmJtXFZu/uJiRR6RrxmYzIdznkaZ8aTGeApQfG432goHqPhh1j+TKpe7Q YwrB90YP6umL16HOyKvci/jNpv7+vFb8sr93FPu8+01AnMJqfvA3IJ+hrzPy6IcX dqpO4oKr9gqbmf2/9Eny5mv50xcNI3+M7y+xh0MFsKoZxnEb2j4pCKQsPO0qMOZw Aui1fFb4nXpcWUlIJtNFRuXXR3pQf4n8ZpfywhUCe4FV5RRrwiq6Y8If0Tj8lqgx 2fEwbkkjZkFVlOijNhZSSWKnobwg3oUbpXStZE6Kyw60vZBcQgEKWOAke175v+qf XMuhiSrSawJDC45SZmb8QtGe8GEV6g== =gYPI -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
dbf00d8d23
30
fs/mpage.c
30
fs/mpage.c
|
|
@ -646,17 +646,24 @@ out:
|
|||
}
|
||||
|
||||
/**
|
||||
* mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them
|
||||
* __mpage_writepages - walk the list of dirty pages of the given address space
|
||||
* & writepage() all of them
|
||||
* @mapping: address space structure to write
|
||||
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
|
||||
* @get_block: the filesystem's block mapper function.
|
||||
* @write_folio: handler to call for each folio before calling
|
||||
* mpage_write_folio()
|
||||
*
|
||||
* This is a library function, which implements the writepages()
|
||||
* address_space_operation.
|
||||
* address_space_operation. It calls @write_folio handler for each folio. If
|
||||
* the handler returns value > 0, it calls mpage_write_folio() to do the
|
||||
* folio writeback.
|
||||
*/
|
||||
int
|
||||
mpage_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, get_block_t get_block)
|
||||
__mpage_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, get_block_t get_block,
|
||||
int (*write_folio)(struct folio *folio,
|
||||
struct writeback_control *wbc))
|
||||
{
|
||||
struct mpage_data mpd = {
|
||||
.get_block = get_block,
|
||||
|
|
@ -666,11 +673,22 @@ mpage_writepages(struct address_space *mapping,
|
|||
int error;
|
||||
|
||||
blk_start_plug(&plug);
|
||||
while ((folio = writeback_iter(mapping, wbc, folio, &error)))
|
||||
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
|
||||
if (write_folio) {
|
||||
error = write_folio(folio, wbc);
|
||||
/*
|
||||
* == 0 means folio is handled, < 0 means error. In
|
||||
* both cases hand back control to writeback_iter()
|
||||
*/
|
||||
if (error <= 0)
|
||||
continue;
|
||||
/* Let mpage_write_folio() handle the folio. */
|
||||
}
|
||||
error = mpage_write_folio(wbc, folio, &mpd);
|
||||
}
|
||||
if (mpd.bio)
|
||||
mpage_bio_submit_write(mpd.bio);
|
||||
blk_finish_plug(&plug);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(mpage_writepages);
|
||||
EXPORT_SYMBOL(__mpage_writepages);
|
||||
|
|
|
|||
|
|
@ -181,22 +181,23 @@ static void udf_write_failed(struct address_space *mapping, loff_t to)
|
|||
}
|
||||
}
|
||||
|
||||
static int udf_adinicb_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
static int udf_handle_page_wb(struct folio *folio,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct inode *inode = folio->mapping->host;
|
||||
struct udf_inode_info *iinfo = UDF_I(inode);
|
||||
struct folio *folio = NULL;
|
||||
int error = 0;
|
||||
|
||||
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
|
||||
BUG_ON(!folio_test_locked(folio));
|
||||
BUG_ON(folio->index != 0);
|
||||
memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio,
|
||||
/*
|
||||
* Inodes in the normal format are handled by the generic code. This
|
||||
* check is race-free as the folio lock protects us from inode type
|
||||
* conversion.
|
||||
*/
|
||||
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
|
||||
return 1;
|
||||
|
||||
memcpy_from_file_folio(iinfo->i_data + iinfo->i_lenEAttr, folio,
|
||||
0, i_size_read(inode));
|
||||
folio_unlock(folio);
|
||||
}
|
||||
|
||||
folio_unlock(folio);
|
||||
mark_inode_dirty(inode);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -204,12 +205,8 @@ static int udf_adinicb_writepages(struct address_space *mapping,
|
|||
static 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 udf_adinicb_writepages(mapping, wbc);
|
||||
return mpage_writepages(mapping, wbc, udf_get_block_wb);
|
||||
return __mpage_writepages(mapping, wbc, udf_get_block_wb,
|
||||
udf_handle_page_wb);
|
||||
}
|
||||
|
||||
static void udf_adinicb_read_folio(struct folio *folio)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,14 @@ struct readahead_control;
|
|||
|
||||
void mpage_readahead(struct readahead_control *, get_block_t get_block);
|
||||
int mpage_read_folio(struct folio *folio, get_block_t get_block);
|
||||
int mpage_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, get_block_t get_block);
|
||||
int __mpage_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, get_block_t get_block,
|
||||
int (*write_folio)(struct folio *folio,
|
||||
struct writeback_control *wbc));
|
||||
static inline int mpage_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, get_block_t get_block)
|
||||
{
|
||||
return __mpage_writepages(mapping, wbc, get_block, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue