f2fs: clear nlink if fail to add_link
Chao Yu
maintainerPATCH 1/8 f2fs: clear nlink if fail to add_link
From: Chao Yu <[email protected]>
We don't need to keep incomplete created inode in cache, so if we fail to add link into directory during new inode creation, it's better to set nlink of inode to zero, then we can evict inode immediately. Otherwise release of nid belong to inode will be delayed until inode cache is being shrunk, it may cause a seemingly endless loop while allocating free nids in time of testing generic/269 case of fstest suit.
--- fs/f2fs/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/f2fs/inode.c +8 -0
@@ -384,6 +384,8 @@ retry:f2fs_lock_op (sbi); err =remove_inode_page (inode);f2fs_unlock_op (sbi); +if (err == -ENOENT ) + err =0 ; }/* give more chances, if ENOMEM case */
@@ -424,6 +426,12 @@ void handle_failed_inode(struct inode *inode)struct f2fs_sb_info *sbi =F2FS_I_SB (inode);struct node_info ni; +/* +* clear nlink of inode in order to release resource of inode +* immediately. +*/ +clear_nlink (inode); +/* don't make bad inode, since it becomes a regular file. */ unlock_new_inode (inode);
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 2/8 f2fs: fix to release discard entries during checkpoint
From: Chao Yu <[email protected]>
In f2fs_fill_super, if there is any IO error occurs during recovery, cached discard entries will be leaked, in order to avoid this, make write_checkpoint() handle memory release by itself, besides, move clear_prefree_segments to write_checkpoint for readability.
--- fs/f2fs/checkpoint.c | 9 ++++++--- fs/f2fs/super.c | 1 - 2 files changed, 6 insertions(+), 4 deletions(-)
fs/f2fs/checkpoint.c +6 -3
@@ -1184,7 +1184,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)if (unlikely (f2fs_cp_error (sbi)))return -EIO ; -clear_prefree_segments (sbi, cpc);clear_sbi_flag (sbi,SBI_IS_DIRTY );clear_sbi_flag (sbi,SBI_NEED_CP );
@@ -1261,8 +1260,12 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)/* unlock all the fs_lock[] in do_checkpoint() */ err =do_checkpoint (sbi, cpc); - -f2fs_wait_all_discard_bio (sbi); +if (err) { +release_discard_addrs (sbi); + }else { +clear_prefree_segments (sbi, cpc); +f2fs_wait_all_discard_bio (sbi); + }unblock_operations (sbi);stat_inc_cp_count (sbi->stat_info);
fs/f2fs/super.c +0 -1
@@ -738,7 +738,6 @@ static void f2fs_put_super(struct super_block *sb)* In addition, EIO will skip do checkpoint, we need this as well. */ release_ino_entry (sbi, true); -release_discard_addrs (sbi);f2fs_leave_shrinker (sbi);mutex_unlock (&sbi->umount_mutex);
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 3/8 f2fs: give a chance to detach from dirty list
In reply to Chao YuFrom: Chao Yu <[email protected]>
If there is no dirty pages in inode, we should give a chance to detach the inode from global dirty list, otherwise it needs to call another unnecessary .writepages for detaching.
--- fs/f2fs/data.c | 8 +++++--- fs/f2fs/dir.c | 1 + fs/f2fs/gc.c | 4 +++- fs/f2fs/inline.c | 4 +++- fs/f2fs/node.c | 1 + fs/f2fs/segment.c | 4 +++- 6 files changed, 16 insertions(+), 6 deletions(-)
fs/f2fs/data.c +5 -3
@@ -1785,12 +1785,14 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset,return ;if (PageDirty (page)) { -if (inode->i_ino ==F2FS_META_INO (sbi)) +if (inode->i_ino ==F2FS_META_INO (sbi)) {dec_page_count (sbi,F2FS_DIRTY_META ); -else if (inode->i_ino ==F2FS_NODE_INO (sbi)) + }else if (inode->i_ino ==F2FS_NODE_INO (sbi)) {dec_page_count (sbi,F2FS_DIRTY_NODES ); -else + }else {inode_dec_dirty_pages (inode); +remove_dirty_inode (inode); + } }/* This is atomic written page, keep Private */
fs/f2fs/dir.c +1 -0
@@ -742,6 +742,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,ClearPagePrivate (page);ClearPageUptodate (page);inode_dec_dirty_pages (dir); +remove_dirty_inode (dir); }f2fs_put_page (page,1 ); }
fs/f2fs/gc.c +3 -1
@@ -673,8 +673,10 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type) retry:set_page_dirty (page);f2fs_wait_on_page_writeback (page,DATA , true); -if (clear_page_dirty_for_io (page)) +if (clear_page_dirty_for_io (page)) {inode_dec_dirty_pages (inode); +remove_dirty_inode (inode); + }set_cold_data (page);
fs/f2fs/inline.c +3 -1
@@ -137,8 +137,10 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) fio.old_blkaddr = dn->data_blkaddr;write_data_page (dn, &fio);f2fs_wait_on_page_writeback (page,DATA , true); -if (dirty) +if (dirty) {inode_dec_dirty_pages (dn->inode); +remove_dirty_inode (dn->inode); + }/* this converted inline_data should be recovered. */ set_inode_flag (dn->inode,FI_APPEND_WRITE );
fs/f2fs/node.c +1 -0
@@ -1204,6 +1204,7 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) ret =f2fs_write_inline_data (inode, page);inode_dec_dirty_pages (inode); +remove_dirty_inode (inode);if (ret)set_page_dirty (page); page_out:
fs/f2fs/segment.c +3 -1
@@ -274,8 +274,10 @@ static int __commit_inmem_pages(struct inode *inode,set_page_dirty (page);f2fs_wait_on_page_writeback (page,DATA , true); -if (clear_page_dirty_for_io (page)) +if (clear_page_dirty_for_io (page)) {inode_dec_dirty_pages (inode); +remove_dirty_inode (inode); + } fio.page = page; err =do_write_data_page (&fio);
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 4/8 f2fs: add missing f2fs_balance_fs in f2fs_zero_range
In reply to Chao YuFrom: Chao Yu <[email protected]>
f2fs_balance_fs should be called in between node page updating, otherwise node page count will exceeded far beyond watermark of triggering foreground garbage collection, result in facing high risk of hitting LFS allocation failure.
--- fs/f2fs/file.c | 3 +++ 1 file changed, 3 insertions(+)
fs/f2fs/file.c +3 -0
@@ -1260,6 +1260,9 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len, ret =f2fs_do_zero_range (&dn, index, end);f2fs_put_dnode (&dn);f2fs_unlock_op (sbi); + +f2fs_balance_fs (sbi, dn.node_changed); +if (ret) goto out;
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 5/8 f2fs: don't miss any f2fs_balance_fs cases
In reply to Chao YuFrom: Chao Yu <[email protected]>
In f2fs_map_blocks, let f2fs_balance_fs detects node page modification with dn.node_changed to avoid miss some corner cases.
--- fs/f2fs/data.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
fs/f2fs/data.c +3 -8
@@ -676,7 +676,6 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,unsigned int ofs_in_node, last_ofs_in_node;blkcnt_t prealloc;struct extent_info ei; -bool allocated = false;block_t blkaddr;if (!maxblocks)
@@ -735,10 +734,8 @@ next_block: } }else { err =__allocate_data_block (&dn); -if (!err) { +if (!err)set_inode_flag (inode,FI_APPEND_WRITE ); - allocated = true; - } }if (err) goto sync_out;
@@ -793,7 +790,6 @@ skip: err =reserve_new_blocks (&dn, prealloc);if (err) goto sync_out; - allocated = dn.node_changed; map->m_len += dn.ofs_in_node - ofs_in_node;if (prealloc && dn.ofs_in_node != last_ofs_in_node +1 ) {
@@ -812,9 +808,8 @@ skip:if (create) {f2fs_unlock_op (sbi); -f2fs_balance_fs (sbi, allocated); +f2fs_balance_fs (sbi, dn.node_changed); } - allocated = false; goto next_dnode; sync_out:
@@ -822,7 +817,7 @@ sync_out: unlock_out:if (create) {f2fs_unlock_op (sbi); -f2fs_balance_fs (sbi, allocated); +f2fs_balance_fs (sbi, dn.node_changed); } out:trace_f2fs_map_blocks (inode, map, err);
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 6/8 f2fs: be aware of extent beyond EOF in fiemap
In reply to Chao YuFrom: Chao Yu <[email protected]>
f2fs can support fallocating blocks beyond file size without changing the size, but ->fiemap of f2fs was restricted and can't detect these extents fallocated past EOF, now relieve the restriction.
--- fs/f2fs/data.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-)
fs/f2fs/data.c +4 -14
@@ -886,7 +886,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,struct buffer_head map_bh;sector_t start_blk, last_blk;pgoff_t next_pgofs; -loff_t isize;u64 logical =0 , phys =0 , size =0 ;u32 flags =0 ;int ret =0 ;
@@ -903,13 +902,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,inode_lock (inode); - isize =i_size_read (inode); -if (start >= isize) - goto out; - -if (start + len > isize) - len = isize - start; -if (logical_to_blk (inode, len) ==0 ) len =blk_to_logical (inode,1 );
@@ -928,13 +920,11 @@ next:/* HOLE */ if (!buffer_mapped (&map_bh)) { start_blk = next_pgofs; -/* Go through holes util pass the EOF */ -if (blk_to_logical (inode, start_blk) < isize) + +if (blk_to_logical (inode, start_blk) <blk_to_logical (inode, +F2FS_I_SB (inode)->max_file_blocks)) goto prep_next; -/* Found a hole beyond isize means no more extents. -* Note that the premise is that filesystems don't -* punch holes beyond isize and keep size unchanged. -*/ + flags |=FIEMAP_EXTENT_LAST ; }
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 7/8 f2fs: fix to update largest extent under lock
In reply to Chao YuFrom: Chao Yu <[email protected]>
In order to avoid racing problem, make largest extent cache being updated under lock.
--- fs/f2fs/inode.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
fs/f2fs/inode.c +7 -4
@@ -252,6 +252,7 @@ retry:int update_inode (struct inode *inode,struct page *node_page) {struct f2fs_inode *ri; +struct extent_tree *et =F2FS_I (inode)->extent_tree;f2fs_inode_synced (inode);
@@ -267,11 +268,13 @@ int update_inode(struct inode *inode, struct page *node_page) ri->i_size =cpu_to_le64 (i_size_read (inode)); ri->i_blocks =cpu_to_le64 (inode->i_blocks); -if (F2FS_I (inode)->extent_tree) -set_raw_extent (&F2FS_I (inode)->extent_tree->largest, - &ri->i_ext); -else +if (et) { +read_lock (&et->lock); +set_raw_extent (&et->largest, &ri->i_ext); +read_unlock (&et->lock); + }else {memset (&ri->i_ext,0 ,sizeof (ri->i_ext)); + }set_raw_inline (inode, ri); ri->i_atime =cpu_to_le64 (inode->i_atime.tv_sec);
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerPATCH 8/8 f2fs: fix error handling in fsync_node_pages
In reply to Chao YuFrom: Chao Yu <[email protected]>
In fsync_node_pages, if f2fs was taged with CP_ERROR_FLAG, make sure bio cache was flushed before return.
--- fs/f2fs/node.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/f2fs/node.c +3 -2
@@ -1339,7 +1339,8 @@ retry:if (unlikely (f2fs_cp_error (sbi))) {f2fs_put_page (last_page,0 );pagevec_release (&pvec); -return -EIO ; + ret = -EIO ; + goto out; }if (!IS_DNODE (page) || !is_cold_node (page))
@@ -1412,7 +1413,7 @@ continue_unlock:unlock_page (last_page); goto retry; } - +out:if (nwritten)f2fs_submit_merged_bio_cond (sbi,NULL ,NULL , ino,NODE ,WRITE );return ret ? -EIO :0 ;
Signature · 6 lines
2.10.1 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Jaegeuk Kim
maintainerHi Chao,
Quoted 28 lines · Chao Yu
From: Chao Yu <[email protected]>
We don't need to keep incomplete created inode in cache, so if we fail to add link into directory during new inode creation, it's better to set nlink of inode to zero, then we can evict inode immediately. Otherwise release of nid belong to inode will be delayed until inode cache is being shrunk, it may cause a seemingly endless loop while allocating free nids in time of testing generic/269 case of fstest suit.
Signed-off-by Chao Yu <[email protected]>--- fs/f2fs/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)fs/f2fs/inode.c +2
-0@@ -384,6 +384,8 @@ retry:f2fs_lock_op (sbi); err =remove_inode_page (inode);f2fs_unlock_op (sbi); +if (err == -ENOENT ) + err =0 ; }/* give more chances, if ENOMEM case */
fs/f2fs/inode.c void handle_failed_inode(struct inode *inode) · line 433
Quoted 8 lines
fs/f2fs/inode.c +5
-0@@ -424,6 +426,12 @@ void handle_failed_inode(struct inode *inode)struct f2fs_sb_info *sbi =F2FS_I_SB (inode);struct node_info ni; +/* +* clear nlink of inode in order to release resource of inode +* immediately. +*/ +clear_nlink (inode);
We must call update_inode_page() here to avoid kernel panic. Otherwise, this inode is kept in the gdirty list, resulting in kernel panic when flushg dirty inodes, since it was already evicted.
I fixed this and started a round of tests.
Thanks,
Quoted 6 lines
fs/f2fs/inode.c +1
-0+/* don't make bad inode, since it becomes a regular file. */ unlock_new_inode (inode);Signature · 1 line
2.10.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Chao Yu
maintainerHi Jaegeuk,
Quoted 34 lines · Jaegeuk Kim
Hi Chao,
Quoted 31 lines · Chao Yu
From: Chao Yu <[email protected]>
We don't need to keep incomplete created inode in cache, so if we fail to add link into directory during new inode creation, it's better to set nlink of inode to zero, then we can evict inode immediately. Otherwise release of nid belong to inode will be delayed until inode cache is being shrunk, it may cause a seemingly endless loop while allocating free nids in time of testing generic/269 case of fstest suit.
Signed-off-by Chao Yu <[email protected]>--- fs/f2fs/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)fs/f2fs/inode.c +2
-0@@ -384,6 +384,8 @@ retry:f2fs_lock_op (sbi); err =remove_inode_page (inode);f2fs_unlock_op (sbi); +if (err == -ENOENT ) + err =0 ; }/* give more chances, if ENOMEM case */ @@ -424,6 +426,12 @@ void handle_failed_inode(struct inode *inode)struct f2fs_sb_info *sbi =F2FS_I_SB (inode);struct node_info ni;
Quoted 9 lines
fs/f2fs/inode.c void handle_failed_inode(struct inode *inode) · line 433
Quoted 5 lines
fs/f2fs/inode.c +5
-0+/* +* clear nlink of inode in order to release resource of inode +* immediately. +*/ +clear_nlink (inode);We must call
update_inode_page()here to avoid kernel panic. Otherwise, this inode is kept in the gdirty list, resulting in kernel panic when flushg dirty inodes, since it was already evicted.
Thanks for fixing this, is this panic produced with fault injection?
Thanks,
Quoted 11 lines
I fixed this and started a round of tests.
Thanks,
Quoted 6 lines
fs/f2fs/inode.c +1
-0+/* don't make bad inode, since it becomes a regular file. */ unlock_new_inode (inode);Signature · 1 line
2.10.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Jaegeuk Kim
maintainerQuoted 47 lines · Chao Yu
Hi Jaegeuk,
Quoted 34 lines · Jaegeuk Kim
Hi Chao,
Quoted 31 lines · Chao Yu
From: Chao Yu <[email protected]>
We don't need to keep incomplete created inode in cache, so if we fail to add link into directory during new inode creation, it's better to set nlink of inode to zero, then we can evict inode immediately. Otherwise release of nid belong to inode will be delayed until inode cache is being shrunk, it may cause a seemingly endless loop while allocating free nids in time of testing generic/269 case of fstest suit.
Signed-off-by Chao Yu <[email protected]>--- fs/f2fs/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)fs/f2fs/inode.c +2
-0@@ -384,6 +384,8 @@ retry:f2fs_lock_op (sbi); err =remove_inode_page (inode);f2fs_unlock_op (sbi); +if (err == -ENOENT ) + err =0 ; }/* give more chances, if ENOMEM case */ @@ -424,6 +426,12 @@ void handle_failed_inode(struct inode *inode)struct f2fs_sb_info *sbi =F2FS_I_SB (inode);struct node_info ni;Quoted 9 lines
fs/f2fs/inode.c void handle_failed_inode(struct inode *inode) · line 433
Quoted 5 lines
fs/f2fs/inode.c +5
-0+/* +* clear nlink of inode in order to release resource of inode +* immediately. +*/ +clear_nlink (inode);We must call
update_inode_page()here to avoid kernel panic. Otherwise, this inode is kept in the gdirty list, resulting in kernel panic when flushg dirty inodes, since it was already evicted.
Quoted 1 line
Thanks for fixing this, is this panic produced with fault injection?
No, it happened xfstests/027 under encrypted mode only.
Thanks,
Quoted 14 lines
Thanks,
Quoted 11 lines
I fixed this and started a round of tests.
Thanks,
Quoted 6 lines
fs/f2fs/inode.c +1
-0+/* don't make bad inode, since it becomes a regular file. */ unlock_new_inode (inode);Signature · 1 line
2.10.1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot
Quoted 1 line · Jaegeuk Kim
No, it happened xfstests/027 under encrypted mode only.
Got it. :)
Thanks,
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot