Skip to content

Commit 6aa58d8

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: readahead encrypted block during GC
During GC, for each encrypted block, we will read block synchronously into meta page, and then submit it into current cold data log area. So this block read model with 4k granularity can make poor performance, like migrating non-encrypted block, let's readahead encrypted block as well to improve migration performance. To implement this, we choose meta page that its index is old block address of the encrypted block, and readahead ciphertext into this page, later, if readaheaded page is still updated, we will load its data into target meta page, and submit the write IO. Note that for OPU, truncation, deletion, we need to invalid meta page after we invalid old block address, to make sure we won't load invalid data from target meta page during encrypted block migration. for ((i = 0; i < 1000; i++)) do { xfs_io -f /mnt/f2fs/dir/$i -c "pwrite 0 128k" -c "fsync"; } done for ((i = 0; i < 1000; i+=2)) do { rm /mnt/f2fs/dir/$i; } done ret = ioctl(fd, F2FS_IOC_GARBAGE_COLLECT, 0); Before: gc-6549 [001] d..1 214682.212797: block_rq_insert: 8,32 RA 32768 () 786400 + 64 [gc] gc-6549 [001] d..1 214682.212802: block_unplug: [gc] 1 gc-6549 [001] .... 214682.213892: block_bio_queue: 8,32 R 67494144 + 8 [gc] gc-6549 [001] .... 214682.213899: block_getrq: 8,32 R 67494144 + 8 [gc] gc-6549 [001] .... 214682.213902: block_plug: [gc] gc-6549 [001] d..1 214682.213905: block_rq_insert: 8,32 R 4096 () 67494144 + 8 [gc] gc-6549 [001] d..1 214682.213908: block_unplug: [gc] 1 gc-6549 [001] .... 214682.226405: block_bio_queue: 8,32 R 67494152 + 8 [gc] gc-6549 [001] .... 214682.226412: block_getrq: 8,32 R 67494152 + 8 [gc] gc-6549 [001] .... 214682.226414: block_plug: [gc] gc-6549 [001] d..1 214682.226417: block_rq_insert: 8,32 R 4096 () 67494152 + 8 [gc] gc-6549 [001] d..1 214682.226420: block_unplug: [gc] 1 gc-6549 [001] .... 214682.226904: block_bio_queue: 8,32 R 67494160 + 8 [gc] gc-6549 [001] .... 214682.226910: block_getrq: 8,32 R 67494160 + 8 [gc] gc-6549 [001] .... 214682.226911: block_plug: [gc] gc-6549 [001] d..1 214682.226914: block_rq_insert: 8,32 R 4096 () 67494160 + 8 [gc] gc-6549 [001] d..1 214682.226916: block_unplug: [gc] 1 After: gc-5678 [003] .... 214327.025906: block_bio_queue: 8,32 R 67493824 + 8 [gc] gc-5678 [003] .... 214327.025908: block_bio_backmerge: 8,32 R 67493824 + 8 [gc] gc-5678 [003] .... 214327.025915: block_bio_queue: 8,32 R 67493832 + 8 [gc] gc-5678 [003] .... 214327.025917: block_bio_backmerge: 8,32 R 67493832 + 8 [gc] gc-5678 [003] .... 214327.025923: block_bio_queue: 8,32 R 67493840 + 8 [gc] gc-5678 [003] .... 214327.025925: block_bio_backmerge: 8,32 R 67493840 + 8 [gc] gc-5678 [003] .... 214327.025932: block_bio_queue: 8,32 R 67493848 + 8 [gc] gc-5678 [003] .... 214327.025934: block_bio_backmerge: 8,32 R 67493848 + 8 [gc] gc-5678 [003] .... 214327.025941: block_bio_queue: 8,32 R 67493856 + 8 [gc] gc-5678 [003] .... 214327.025943: block_bio_backmerge: 8,32 R 67493856 + 8 [gc] gc-5678 [003] .... 214327.025953: block_bio_queue: 8,32 R 67493864 + 8 [gc] gc-5678 [003] .... 214327.025955: block_bio_backmerge: 8,32 R 67493864 + 8 [gc] gc-5678 [003] .... 214327.025962: block_bio_queue: 8,32 R 67493872 + 8 [gc] gc-5678 [003] .... 214327.025964: block_bio_backmerge: 8,32 R 67493872 + 8 [gc] gc-5678 [003] .... 214327.025970: block_bio_queue: 8,32 R 67493880 + 8 [gc] gc-5678 [003] .... 214327.025972: block_bio_backmerge: 8,32 R 67493880 + 8 [gc] gc-5678 [003] .... 214327.026000: block_bio_queue: 8,32 WS 34123776 + 2048 [gc] gc-5678 [003] .... 214327.026019: block_getrq: 8,32 WS 34123776 + 2048 [gc] gc-5678 [003] d..1 214327.026021: block_rq_insert: 8,32 R 131072 () 67493632 + 256 [gc] gc-5678 [003] d..1 214327.026023: block_unplug: [gc] 1 gc-5678 [003] d..1 214327.026026: block_rq_issue: 8,32 R 131072 () 67493632 + 256 [gc] gc-5678 [003] .... 214327.026046: block_plug: [gc] Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 6f8d445 commit 6aa58d8

File tree

3 files changed

+134
-22
lines changed

3 files changed

+134
-22
lines changed

fs/f2fs/data.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
875875
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
876876
struct f2fs_summary sum;
877877
struct node_info ni;
878+
block_t old_blkaddr;
878879
pgoff_t fofs;
879880
blkcnt_t count = 1;
880881
int err;
@@ -896,9 +897,12 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
896897

897898
alloc:
898899
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
899-
900-
f2fs_allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
900+
old_blkaddr = dn->data_blkaddr;
901+
f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
901902
&sum, seg_type, NULL, false);
903+
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
904+
invalidate_mapping_pages(META_MAPPING(sbi),
905+
old_blkaddr, old_blkaddr);
902906
f2fs_set_data_blkaddr(dn);
903907

904908
/* update i_size */
@@ -1614,6 +1618,7 @@ static int f2fs_read_data_pages(struct file *file,
16141618
static int encrypt_one_page(struct f2fs_io_info *fio)
16151619
{
16161620
struct inode *inode = fio->page->mapping->host;
1621+
struct page *mpage;
16171622
gfp_t gfp_flags = GFP_NOFS;
16181623

16191624
if (!f2fs_encrypted_file(inode))
@@ -1625,17 +1630,25 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
16251630
retry_encrypt:
16261631
fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
16271632
PAGE_SIZE, 0, fio->page->index, gfp_flags);
1628-
if (!IS_ERR(fio->encrypted_page))
1629-
return 0;
1633+
if (IS_ERR(fio->encrypted_page)) {
1634+
/* flush pending IOs and wait for a while in the ENOMEM case */
1635+
if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
1636+
f2fs_flush_merged_writes(fio->sbi);
1637+
congestion_wait(BLK_RW_ASYNC, HZ/50);
1638+
gfp_flags |= __GFP_NOFAIL;
1639+
goto retry_encrypt;
1640+
}
1641+
return PTR_ERR(fio->encrypted_page);
1642+
}
16301643

1631-
/* flush pending IOs and wait for a while in the ENOMEM case */
1632-
if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
1633-
f2fs_flush_merged_writes(fio->sbi);
1634-
congestion_wait(BLK_RW_ASYNC, HZ/50);
1635-
gfp_flags |= __GFP_NOFAIL;
1636-
goto retry_encrypt;
1644+
mpage = find_lock_page(META_MAPPING(fio->sbi), fio->old_blkaddr);
1645+
if (mpage) {
1646+
if (PageUptodate(mpage))
1647+
memcpy(page_address(mpage),
1648+
page_address(fio->encrypted_page), PAGE_SIZE);
1649+
f2fs_put_page(mpage, 1);
16371650
}
1638-
return PTR_ERR(fio->encrypted_page);
1651+
return 0;
16391652
}
16401653

16411654
static inline bool check_inplace_update_policy(struct inode *inode,

fs/f2fs/gc.c

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,72 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
599599
return true;
600600
}
601601

602+
static int ra_data_block(struct inode *inode, pgoff_t index)
603+
{
604+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
605+
struct address_space *mapping = inode->i_mapping;
606+
struct dnode_of_data dn;
607+
struct page *page;
608+
struct extent_info ei = {0, 0, 0};
609+
struct f2fs_io_info fio = {
610+
.sbi = sbi,
611+
.ino = inode->i_ino,
612+
.type = DATA,
613+
.temp = COLD,
614+
.op = REQ_OP_READ,
615+
.op_flags = 0,
616+
.encrypted_page = NULL,
617+
.in_list = false,
618+
.retry = false,
619+
};
620+
int err;
621+
622+
page = f2fs_grab_cache_page(mapping, index, true);
623+
if (!page)
624+
return -ENOMEM;
625+
626+
if (f2fs_lookup_extent_cache(inode, index, &ei)) {
627+
dn.data_blkaddr = ei.blk + index - ei.fofs;
628+
goto got_it;
629+
}
630+
631+
set_new_dnode(&dn, inode, NULL, NULL, 0);
632+
err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
633+
if (err)
634+
goto put_page;
635+
f2fs_put_dnode(&dn);
636+
637+
if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
638+
DATA_GENERIC))) {
639+
err = -EFAULT;
640+
goto put_page;
641+
}
642+
got_it:
643+
/* read page */
644+
fio.page = page;
645+
fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
646+
647+
fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(sbi),
648+
dn.data_blkaddr,
649+
FGP_LOCK | FGP_CREAT, GFP_NOFS);
650+
if (!fio.encrypted_page) {
651+
err = -ENOMEM;
652+
goto put_page;
653+
}
654+
655+
err = f2fs_submit_page_bio(&fio);
656+
if (err)
657+
goto put_encrypted_page;
658+
f2fs_put_page(fio.encrypted_page, 0);
659+
f2fs_put_page(page, 1);
660+
return 0;
661+
put_encrypted_page:
662+
f2fs_put_page(fio.encrypted_page, 1);
663+
put_page:
664+
f2fs_put_page(page, 1);
665+
return err;
666+
}
667+
602668
/*
603669
* Move data block via META_MAPPING while keeping locked data page.
604670
* This can be used to move blocks, aka LBAs, directly on disk.
@@ -620,7 +686,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
620686
struct dnode_of_data dn;
621687
struct f2fs_summary sum;
622688
struct node_info ni;
623-
struct page *page;
689+
struct page *page, *mpage;
624690
block_t newaddr;
625691
int err;
626692
bool lfs_mode = test_opt(fio.sbi, LFS);
@@ -683,6 +749,23 @@ static void move_data_block(struct inode *inode, block_t bidx,
683749
goto recover_block;
684750
}
685751

752+
mpage = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
753+
fio.old_blkaddr, FGP_LOCK, GFP_NOFS);
754+
if (mpage) {
755+
bool updated = false;
756+
757+
if (PageUptodate(mpage)) {
758+
memcpy(page_address(fio.encrypted_page),
759+
page_address(mpage), PAGE_SIZE);
760+
updated = true;
761+
}
762+
f2fs_put_page(mpage, 1);
763+
invalidate_mapping_pages(META_MAPPING(fio.sbi),
764+
fio.old_blkaddr, fio.old_blkaddr);
765+
if (updated)
766+
goto write_page;
767+
}
768+
686769
err = f2fs_submit_page_bio(&fio);
687770
if (err)
688771
goto put_page_out;
@@ -699,6 +782,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
699782
goto put_page_out;
700783
}
701784

785+
write_page:
702786
set_page_dirty(fio.encrypted_page);
703787
f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true);
704788
if (clear_page_dirty_for_io(fio.encrypted_page))
@@ -873,23 +957,30 @@ static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
873957
if (IS_ERR(inode) || is_bad_inode(inode))
874958
continue;
875959

876-
/* if inode uses special I/O path, let's go phase 3 */
877-
if (f2fs_post_read_required(inode)) {
878-
add_gc_inode(gc_list, inode);
879-
continue;
880-
}
881-
882960
if (!down_write_trylock(
883961
&F2FS_I(inode)->i_gc_rwsem[WRITE])) {
884962
iput(inode);
885963
sbi->skipped_gc_rwsem++;
886964
continue;
887965
}
888966

889-
start_bidx = f2fs_start_bidx_of_node(nofs, inode);
967+
start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
968+
ofs_in_node;
969+
970+
if (f2fs_post_read_required(inode)) {
971+
int err = ra_data_block(inode, start_bidx);
972+
973+
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
974+
if (err) {
975+
iput(inode);
976+
continue;
977+
}
978+
add_gc_inode(gc_list, inode);
979+
continue;
980+
}
981+
890982
data_page = f2fs_get_read_data_page(inode,
891-
start_bidx + ofs_in_node, REQ_RAHEAD,
892-
true);
983+
start_bidx, REQ_RAHEAD, true);
893984
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
894985
if (IS_ERR(data_page)) {
895986
iput(inode);

fs/f2fs/segment.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,8 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
20792079
if (addr == NEW_ADDR)
20802080
return;
20812081

2082+
invalidate_mapping_pages(META_MAPPING(sbi), addr, addr);
2083+
20822084
/* add it into sit main buffer */
20832085
down_write(&sit_i->sentry_lock);
20842086

@@ -2978,6 +2980,9 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
29782980
reallocate:
29792981
f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
29802982
&fio->new_blkaddr, sum, type, fio, true);
2983+
if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
2984+
invalidate_mapping_pages(META_MAPPING(fio->sbi),
2985+
fio->old_blkaddr, fio->old_blkaddr);
29812986

29822987
/* writeout dirty page into bdev */
29832988
f2fs_submit_page_write(fio);
@@ -3132,8 +3137,11 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
31323137

31333138
if (!recover_curseg || recover_newaddr)
31343139
update_sit_entry(sbi, new_blkaddr, 1);
3135-
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
3140+
if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) {
3141+
invalidate_mapping_pages(META_MAPPING(sbi),
3142+
old_blkaddr, old_blkaddr);
31363143
update_sit_entry(sbi, old_blkaddr, -1);
3144+
}
31373145

31383146
locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
31393147
locate_dirty_segment(sbi, GET_SEGNO(sbi, new_blkaddr));

0 commit comments

Comments
 (0)