Skip to content

Commit 1501f70

Browse files
committed
Merge tag 'f2fs-for-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim: "In this round, we've refactored the existing atomic write support implemented by in-memory operations to have storing data in disk temporarily, which can give us a benefit to accept more atomic writes. At the same time, we removed the existing volatile write support. We've also revisited the file pinning and GC flows and found some corner cases which contributeed abnormal system behaviours. As usual, there're several minor code refactoring for readability, sanity check, and clean ups. Enhancements: - allow compression for mmap files in compress_mode=user - kill volatile write support - change the current atomic write way - give priority to select unpinned section for foreground GC - introduce data read/write showing path info - remove unnecessary f2fs_lock_op in f2fs_new_inode Bug fixes: - fix the file pinning flow during checkpoint=disable and GCs - fix foreground and background GCs to select the right victims and get free sections on time - fix GC flags on defragmenting pages - avoid an infinite loop to flush node pages - fix fallocate to use file_modified to update permissions consistently" * tag 'f2fs-for-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (40 commits) f2fs: fix to tag gcing flag on page during file defragment f2fs: replace F2FS_I(inode) and sbi by the local variable f2fs: add f2fs_init_write_merge_io function f2fs: avoid unneeded error handling for revoke_entry_slab allocation f2fs: allow compression for mmap files in compress_mode=user f2fs: fix typo in comment f2fs: make f2fs_read_inline_data() more readable f2fs: fix to do sanity check for inline inode f2fs: fix fallocate to use file_modified to update permissions consistently f2fs: don't use casefolded comparison for "." and ".." f2fs: do not stop GC when requiring a free section f2fs: keep wait_ms if EAGAIN happens f2fs: introduce f2fs_gc_control to consolidate f2fs_gc parameters f2fs: reject test_dummy_encryption when !CONFIG_FS_ENCRYPTION f2fs: kill volatile write support f2fs: change the current atomic write way f2fs: don't need inode lock for system hidden quota f2fs: stop allocating pinned sections if EAGAIN happens f2fs: skip GC if possible when checkpoint disabling f2fs: give priority to select unpinned section for foreground GC ...
2 parents 2a5699b + 2d1fe8a commit 1501f70

File tree

18 files changed

+926
-823
lines changed

18 files changed

+926
-823
lines changed

fs/f2fs/checkpoint.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
9898
}
9999

100100
if (unlikely(!PageUptodate(page))) {
101-
if (page->index == sbi->metapage_eio_ofs) {
102-
if (sbi->metapage_eio_cnt++ == MAX_RETRY_META_PAGE_EIO)
103-
set_ckpt_flags(sbi, CP_ERROR_FLAG);
104-
} else {
105-
sbi->metapage_eio_ofs = page->index;
106-
sbi->metapage_eio_cnt = 0;
107-
}
101+
f2fs_handle_page_eio(sbi, page->index, META);
108102
f2fs_put_page(page, 1);
109103
return ERR_PTR(-EIO);
110104
}
@@ -158,7 +152,7 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
158152
f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
159153
blkaddr, exist);
160154
set_sbi_flag(sbi, SBI_NEED_FSCK);
161-
WARN_ON(1);
155+
dump_stack();
162156
}
163157
return exist;
164158
}
@@ -196,7 +190,7 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
196190
f2fs_warn(sbi, "access invalid blkaddr:%u",
197191
blkaddr);
198192
set_sbi_flag(sbi, SBI_NEED_FSCK);
199-
WARN_ON(1);
193+
dump_stack();
200194
return false;
201195
} else {
202196
return __is_bitmap_valid(sbi, blkaddr, type);
@@ -1010,9 +1004,7 @@ static void __add_dirty_inode(struct inode *inode, enum inode_type type)
10101004
return;
10111005

10121006
set_inode_flag(inode, flag);
1013-
if (!f2fs_is_volatile_file(inode))
1014-
list_add_tail(&F2FS_I(inode)->dirty_list,
1015-
&sbi->inode_list[type]);
1007+
list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]);
10161008
stat_inc_dirty_inode(sbi, type);
10171009
}
10181010

fs/f2fs/data.c

Lines changed: 143 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ static bool __is_cp_guaranteed(struct page *page)
6969

7070
if (f2fs_is_compressed_page(page))
7171
return false;
72-
if ((S_ISREG(inode->i_mode) &&
73-
(f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) ||
72+
if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) ||
7473
page_private_gcing(page))
7574
return true;
7675
return false;
@@ -585,6 +584,34 @@ static bool __has_merged_page(struct bio *bio, struct inode *inode,
585584
return false;
586585
}
587586

587+
int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi)
588+
{
589+
int i;
590+
591+
for (i = 0; i < NR_PAGE_TYPE; i++) {
592+
int n = (i == META) ? 1 : NR_TEMP_TYPE;
593+
int j;
594+
595+
sbi->write_io[i] = f2fs_kmalloc(sbi,
596+
array_size(n, sizeof(struct f2fs_bio_info)),
597+
GFP_KERNEL);
598+
if (!sbi->write_io[i])
599+
return -ENOMEM;
600+
601+
for (j = HOT; j < n; j++) {
602+
init_f2fs_rwsem(&sbi->write_io[i][j].io_rwsem);
603+
sbi->write_io[i][j].sbi = sbi;
604+
sbi->write_io[i][j].bio = NULL;
605+
spin_lock_init(&sbi->write_io[i][j].io_lock);
606+
INIT_LIST_HEAD(&sbi->write_io[i][j].io_list);
607+
INIT_LIST_HEAD(&sbi->write_io[i][j].bio_list);
608+
init_f2fs_rwsem(&sbi->write_io[i][j].bio_list_lock);
609+
}
610+
}
611+
612+
return 0;
613+
}
614+
588615
static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi,
589616
enum page_type type, enum temp_type temp)
590617
{
@@ -2564,7 +2591,12 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
25642591
bool ipu_force = false;
25652592
int err = 0;
25662593

2567-
set_new_dnode(&dn, inode, NULL, NULL, 0);
2594+
/* Use COW inode to make dnode_of_data for atomic write */
2595+
if (f2fs_is_atomic_file(inode))
2596+
set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0);
2597+
else
2598+
set_new_dnode(&dn, inode, NULL, NULL, 0);
2599+
25682600
if (need_inplace_update(fio) &&
25692601
f2fs_lookup_extent_cache(inode, page->index, &ei)) {
25702602
fio->old_blkaddr = ei.blk + page->index - ei.fofs;
@@ -2601,6 +2633,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
26012633
err = -EFSCORRUPTED;
26022634
goto out_writepage;
26032635
}
2636+
26042637
/*
26052638
* If current allocation needs SSR,
26062639
* it had better in-place writes for updated data.
@@ -2737,11 +2770,6 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
27372770
write:
27382771
if (f2fs_is_drop_cache(inode))
27392772
goto out;
2740-
/* we should not write 0'th page having journal header */
2741-
if (f2fs_is_volatile_file(inode) && (!page->index ||
2742-
(!wbc->for_reclaim &&
2743-
f2fs_available_free_memory(sbi, BASE_CHECK))))
2744-
goto redirty_out;
27452773

27462774
/* Dentry/quota blocks are controlled by checkpoint */
27472775
if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) {
@@ -3314,14 +3342,108 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
33143342
return err;
33153343
}
33163344

3345+
static int __find_data_block(struct inode *inode, pgoff_t index,
3346+
block_t *blk_addr)
3347+
{
3348+
struct dnode_of_data dn;
3349+
struct page *ipage;
3350+
struct extent_info ei = {0, };
3351+
int err = 0;
3352+
3353+
ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
3354+
if (IS_ERR(ipage))
3355+
return PTR_ERR(ipage);
3356+
3357+
set_new_dnode(&dn, inode, ipage, ipage, 0);
3358+
3359+
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
3360+
dn.data_blkaddr = ei.blk + index - ei.fofs;
3361+
} else {
3362+
/* hole case */
3363+
err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
3364+
if (err) {
3365+
dn.data_blkaddr = NULL_ADDR;
3366+
err = 0;
3367+
}
3368+
}
3369+
*blk_addr = dn.data_blkaddr;
3370+
f2fs_put_dnode(&dn);
3371+
return err;
3372+
}
3373+
3374+
static int __reserve_data_block(struct inode *inode, pgoff_t index,
3375+
block_t *blk_addr, bool *node_changed)
3376+
{
3377+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
3378+
struct dnode_of_data dn;
3379+
struct page *ipage;
3380+
int err = 0;
3381+
3382+
f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true);
3383+
3384+
ipage = f2fs_get_node_page(sbi, inode->i_ino);
3385+
if (IS_ERR(ipage)) {
3386+
err = PTR_ERR(ipage);
3387+
goto unlock_out;
3388+
}
3389+
set_new_dnode(&dn, inode, ipage, ipage, 0);
3390+
3391+
err = f2fs_get_block(&dn, index);
3392+
3393+
*blk_addr = dn.data_blkaddr;
3394+
*node_changed = dn.node_changed;
3395+
f2fs_put_dnode(&dn);
3396+
3397+
unlock_out:
3398+
f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false);
3399+
return err;
3400+
}
3401+
3402+
static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi,
3403+
struct page *page, loff_t pos, unsigned int len,
3404+
block_t *blk_addr, bool *node_changed)
3405+
{
3406+
struct inode *inode = page->mapping->host;
3407+
struct inode *cow_inode = F2FS_I(inode)->cow_inode;
3408+
pgoff_t index = page->index;
3409+
int err = 0;
3410+
block_t ori_blk_addr;
3411+
3412+
/* If pos is beyond the end of file, reserve a new block in COW inode */
3413+
if ((pos & PAGE_MASK) >= i_size_read(inode))
3414+
return __reserve_data_block(cow_inode, index, blk_addr,
3415+
node_changed);
3416+
3417+
/* Look for the block in COW inode first */
3418+
err = __find_data_block(cow_inode, index, blk_addr);
3419+
if (err)
3420+
return err;
3421+
else if (*blk_addr != NULL_ADDR)
3422+
return 0;
3423+
3424+
/* Look for the block in the original inode */
3425+
err = __find_data_block(inode, index, &ori_blk_addr);
3426+
if (err)
3427+
return err;
3428+
3429+
/* Finally, we should reserve a new block in COW inode for the update */
3430+
err = __reserve_data_block(cow_inode, index, blk_addr, node_changed);
3431+
if (err)
3432+
return err;
3433+
3434+
if (ori_blk_addr != NULL_ADDR)
3435+
*blk_addr = ori_blk_addr;
3436+
return 0;
3437+
}
3438+
33173439
static int f2fs_write_begin(struct file *file, struct address_space *mapping,
33183440
loff_t pos, unsigned len, struct page **pagep, void **fsdata)
33193441
{
33203442
struct inode *inode = mapping->host;
33213443
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
33223444
struct page *page = NULL;
33233445
pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT;
3324-
bool need_balance = false, drop_atomic = false;
3446+
bool need_balance = false;
33253447
block_t blkaddr = NULL_ADDR;
33263448
int err = 0;
33273449

@@ -3332,14 +3454,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
33323454
goto fail;
33333455
}
33343456

3335-
if ((f2fs_is_atomic_file(inode) &&
3336-
!f2fs_available_free_memory(sbi, INMEM_PAGES)) ||
3337-
is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) {
3338-
err = -ENOMEM;
3339-
drop_atomic = true;
3340-
goto fail;
3341-
}
3342-
33433457
/*
33443458
* We should check this at this moment to avoid deadlock on inode page
33453459
* and #0 page. The locking rule for inline_data conversion should be:
@@ -3387,7 +3501,11 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
33873501

33883502
*pagep = page;
33893503

3390-
err = prepare_write_begin(sbi, page, pos, len,
3504+
if (f2fs_is_atomic_file(inode))
3505+
err = prepare_atomic_write_begin(sbi, page, pos, len,
3506+
&blkaddr, &need_balance);
3507+
else
3508+
err = prepare_write_begin(sbi, page, pos, len,
33913509
&blkaddr, &need_balance);
33923510
if (err)
33933511
goto fail;
@@ -3443,8 +3561,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
34433561
fail:
34443562
f2fs_put_page(page, 1);
34453563
f2fs_write_failed(inode, pos + len);
3446-
if (drop_atomic)
3447-
f2fs_drop_inmem_pages_all(sbi, false);
34483564
return err;
34493565
}
34503566

@@ -3488,8 +3604,12 @@ static int f2fs_write_end(struct file *file,
34883604
set_page_dirty(page);
34893605

34903606
if (pos + copied > i_size_read(inode) &&
3491-
!f2fs_verity_in_progress(inode))
3607+
!f2fs_verity_in_progress(inode)) {
34923608
f2fs_i_size_write(inode, pos + copied);
3609+
if (f2fs_is_atomic_file(inode))
3610+
f2fs_i_size_write(F2FS_I(inode)->cow_inode,
3611+
pos + copied);
3612+
}
34933613
unlock_out:
34943614
f2fs_put_page(page, 1);
34953615
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
@@ -3522,9 +3642,6 @@ void f2fs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
35223642
inode->i_ino == F2FS_COMPRESS_INO(sbi))
35233643
clear_page_private_data(&folio->page);
35243644

3525-
if (page_private_atomic(&folio->page))
3526-
return f2fs_drop_inmem_page(inode, &folio->page);
3527-
35283645
folio_detach_private(folio);
35293646
}
35303647

@@ -3536,10 +3653,6 @@ bool f2fs_release_folio(struct folio *folio, gfp_t wait)
35363653
if (folio_test_dirty(folio))
35373654
return false;
35383655

3539-
/* This is atomic written page, keep Private */
3540-
if (page_private_atomic(&folio->page))
3541-
return false;
3542-
35433656
sbi = F2FS_M_SB(folio->mapping);
35443657
if (test_opt(sbi, COMPRESS_CACHE)) {
35453658
struct inode *inode = folio->mapping->host;
@@ -3565,18 +3678,6 @@ static bool f2fs_dirty_data_folio(struct address_space *mapping,
35653678
folio_mark_uptodate(folio);
35663679
BUG_ON(folio_test_swapcache(folio));
35673680

3568-
if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
3569-
if (!page_private_atomic(&folio->page)) {
3570-
f2fs_register_inmem_page(inode, &folio->page);
3571-
return true;
3572-
}
3573-
/*
3574-
* Previously, this page has been registered, we just
3575-
* return here.
3576-
*/
3577-
return false;
3578-
}
3579-
35803681
if (!folio_test_dirty(folio)) {
35813682
filemap_dirty_folio(mapping, folio);
35823683
f2fs_update_dirty_folio(inode, folio);
@@ -3656,42 +3757,14 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
36563757
int f2fs_migrate_page(struct address_space *mapping,
36573758
struct page *newpage, struct page *page, enum migrate_mode mode)
36583759
{
3659-
int rc, extra_count;
3660-
struct f2fs_inode_info *fi = F2FS_I(mapping->host);
3661-
bool atomic_written = page_private_atomic(page);
3760+
int rc, extra_count = 0;
36623761

36633762
BUG_ON(PageWriteback(page));
36643763

3665-
/* migrating an atomic written page is safe with the inmem_lock hold */
3666-
if (atomic_written) {
3667-
if (mode != MIGRATE_SYNC)
3668-
return -EBUSY;
3669-
if (!mutex_trylock(&fi->inmem_lock))
3670-
return -EAGAIN;
3671-
}
3672-
3673-
/* one extra reference was held for atomic_write page */
3674-
extra_count = atomic_written ? 1 : 0;
36753764
rc = migrate_page_move_mapping(mapping, newpage,
36763765
page, extra_count);
3677-
if (rc != MIGRATEPAGE_SUCCESS) {
3678-
if (atomic_written)
3679-
mutex_unlock(&fi->inmem_lock);
3766+
if (rc != MIGRATEPAGE_SUCCESS)
36803767
return rc;
3681-
}
3682-
3683-
if (atomic_written) {
3684-
struct inmem_pages *cur;
3685-
3686-
list_for_each_entry(cur, &fi->inmem_pages, list)
3687-
if (cur->page == page) {
3688-
cur->page = newpage;
3689-
break;
3690-
}
3691-
mutex_unlock(&fi->inmem_lock);
3692-
put_page(page);
3693-
get_page(newpage);
3694-
}
36953768

36963769
/* guarantee to start from no stale private field */
36973770
set_page_private(newpage, 0);

0 commit comments

Comments
 (0)