mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-26 02:51:33 -05:00
f2fs: Convert f2fs_write_begin() to use a folio
Fetch a folio from the page cache instead of a page and use it throughout. We still have to convert back to a page for calling internal f2fs functions, but hopefully they will be converted soon. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
a0f858d450
commit
dfd2e81d37
@@ -3556,8 +3556,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
||||
struct page *page = NULL;
|
||||
pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT;
|
||||
struct folio *folio;
|
||||
pgoff_t index = pos >> PAGE_SHIFT;
|
||||
bool need_balance = false;
|
||||
bool use_cow = false;
|
||||
block_t blkaddr = NULL_ADDR;
|
||||
@@ -3573,7 +3573,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
|
||||
/*
|
||||
* We should check this at this moment to avoid deadlock on inode page
|
||||
* and #0 page. The locking rule for inline_data conversion should be:
|
||||
* lock_page(page #0) -> lock_page(inode_page)
|
||||
* folio_lock(folio #0) -> folio_lock(inode_page)
|
||||
*/
|
||||
if (index != 0) {
|
||||
err = f2fs_convert_inline_inode(inode);
|
||||
@@ -3603,81 +3603,85 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
|
||||
|
||||
repeat:
|
||||
/*
|
||||
* Do not use grab_cache_page_write_begin() to avoid deadlock due to
|
||||
* wait_for_stable_page. Will wait that below with our IO control.
|
||||
* Do not use FGP_STABLE to avoid deadlock.
|
||||
* Will wait that below with our IO control.
|
||||
*/
|
||||
page = f2fs_pagecache_get_page(mapping, index,
|
||||
folio = __filemap_get_folio(mapping, index,
|
||||
FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS);
|
||||
if (!page) {
|
||||
err = -ENOMEM;
|
||||
if (IS_ERR(folio)) {
|
||||
err = PTR_ERR(folio);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO: cluster can be compressed due to race with .writepage */
|
||||
|
||||
*pagep = page;
|
||||
*pagep = &folio->page;
|
||||
|
||||
if (f2fs_is_atomic_file(inode))
|
||||
err = prepare_atomic_write_begin(sbi, page, pos, len,
|
||||
err = prepare_atomic_write_begin(sbi, &folio->page, pos, len,
|
||||
&blkaddr, &need_balance, &use_cow);
|
||||
else
|
||||
err = prepare_write_begin(sbi, page, pos, len,
|
||||
err = prepare_write_begin(sbi, &folio->page, pos, len,
|
||||
&blkaddr, &need_balance);
|
||||
if (err)
|
||||
goto fail;
|
||||
goto put_folio;
|
||||
|
||||
if (need_balance && !IS_NOQUOTA(inode) &&
|
||||
has_not_enough_free_secs(sbi, 0, 0)) {
|
||||
unlock_page(page);
|
||||
folio_unlock(folio);
|
||||
f2fs_balance_fs(sbi, true);
|
||||
lock_page(page);
|
||||
if (page->mapping != mapping) {
|
||||
/* The page got truncated from under us */
|
||||
f2fs_put_page(page, 1);
|
||||
folio_lock(folio);
|
||||
if (folio->mapping != mapping) {
|
||||
/* The folio got truncated from under us */
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
|
||||
f2fs_wait_on_page_writeback(page, DATA, false, true);
|
||||
f2fs_wait_on_page_writeback(&folio->page, DATA, false, true);
|
||||
|
||||
if (len == PAGE_SIZE || PageUptodate(page))
|
||||
if (len == folio_size(folio) || folio_test_uptodate(folio))
|
||||
return 0;
|
||||
|
||||
if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) &&
|
||||
!f2fs_verity_in_progress(inode)) {
|
||||
zero_user_segment(page, len, PAGE_SIZE);
|
||||
folio_zero_segment(folio, len, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (blkaddr == NEW_ADDR) {
|
||||
zero_user_segment(page, 0, PAGE_SIZE);
|
||||
SetPageUptodate(page);
|
||||
folio_zero_segment(folio, 0, folio_size(folio));
|
||||
folio_mark_uptodate(folio);
|
||||
} else {
|
||||
if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
|
||||
DATA_GENERIC_ENHANCE_READ)) {
|
||||
err = -EFSCORRUPTED;
|
||||
goto fail;
|
||||
goto put_folio;
|
||||
}
|
||||
err = f2fs_submit_page_read(use_cow ?
|
||||
F2FS_I(inode)->cow_inode : inode, page,
|
||||
F2FS_I(inode)->cow_inode : inode, &folio->page,
|
||||
blkaddr, 0, true);
|
||||
if (err)
|
||||
goto fail;
|
||||
goto put_folio;
|
||||
|
||||
lock_page(page);
|
||||
if (unlikely(page->mapping != mapping)) {
|
||||
f2fs_put_page(page, 1);
|
||||
folio_lock(folio);
|
||||
if (unlikely(folio->mapping != mapping)) {
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
goto repeat;
|
||||
}
|
||||
if (unlikely(!PageUptodate(page))) {
|
||||
if (unlikely(!folio_test_uptodate(folio))) {
|
||||
err = -EIO;
|
||||
goto fail;
|
||||
goto put_folio;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
put_folio:
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
fail:
|
||||
f2fs_put_page(page, 1);
|
||||
f2fs_write_failed(inode, pos + len);
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user