Skip to content

Commit 0f18b46

Browse files
author
Jaegeuk Kim
committed
f2fs: flush inode metadata when checkpoint is doing
This patch registers all the inodes which have dirty metadata to sync when checkpoint is doing. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 205b982 commit 0f18b46

File tree

7 files changed

+107
-7
lines changed

7 files changed

+107
-7
lines changed

fs/f2fs/checkpoint.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,34 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
859859
goto retry;
860860
}
861861

862+
int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
863+
{
864+
struct list_head *head = &sbi->inode_list[DIRTY_META];
865+
struct inode *inode;
866+
struct f2fs_inode_info *fi;
867+
s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);
868+
869+
while (total--) {
870+
if (unlikely(f2fs_cp_error(sbi)))
871+
return -EIO;
872+
873+
spin_lock(&sbi->inode_lock[DIRTY_META]);
874+
if (list_empty(head)) {
875+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
876+
return 0;
877+
}
878+
fi = list_entry(head->next, struct f2fs_inode_info,
879+
gdirty_list);
880+
inode = igrab(&fi->vfs_inode);
881+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
882+
if (inode) {
883+
update_inode_page(inode);
884+
iput(inode);
885+
}
886+
};
887+
return 0;
888+
}
889+
862890
/*
863891
* Freeze all the FS-operations for checkpoint.
864892
*/
@@ -885,6 +913,14 @@ static int block_operations(struct f2fs_sb_info *sbi)
885913
goto retry_flush_dents;
886914
}
887915

916+
if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
917+
f2fs_unlock_all(sbi);
918+
err = f2fs_sync_inode_meta(sbi);
919+
if (err)
920+
goto out;
921+
goto retry_flush_dents;
922+
}
923+
888924
/*
889925
* POR: we should ensure that there are no dirty node pages
890926
* until finishing nat/sit flush.

fs/f2fs/debug.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
4747
si->ndirty_data = get_pages(sbi, F2FS_DIRTY_DATA);
4848
si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
4949
si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
50+
si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
5051
si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
5152
si->wb_bios = atomic_read(&sbi->nr_wb_bios);
5253
si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
@@ -304,8 +305,8 @@ static int stat_show(struct seq_file *s, void *v)
304305
si->inmem_pages, si->wb_bios);
305306
seq_printf(s, " - nodes: %4lld in %4d\n",
306307
si->ndirty_node, si->node_pages);
307-
seq_printf(s, " - dents: %4lld in dirs:%4d\n",
308-
si->ndirty_dent, si->ndirty_dirs);
308+
seq_printf(s, " - dents: %4lld in dirs:%4d (%4d)\n",
309+
si->ndirty_dent, si->ndirty_dirs, si->ndirty_all);
309310
seq_printf(s, " - datas: %4lld in files:%4d\n",
310311
si->ndirty_data, si->ndirty_files);
311312
seq_printf(s, " - meta: %4lld in %4d\n",

fs/f2fs/f2fs.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ struct f2fs_inode_info {
442442
nid_t i_xattr_nid; /* node id that contains xattrs */
443443
unsigned long long xattr_ver; /* cp version of xattr modification */
444444

445-
struct list_head dirty_list; /* linked in global dirty list */
445+
struct list_head dirty_list; /* dirty list for dirs and files */
446+
struct list_head gdirty_list; /* linked in global dirty list */
446447
struct list_head inmem_pages; /* inmemory pages managed by f2fs */
447448
struct mutex inmem_lock; /* lock for inmemory pages */
448449
struct extent_tree *extent_tree; /* cached extent_tree entry */
@@ -657,6 +658,7 @@ enum count_type {
657658
F2FS_DIRTY_NODES,
658659
F2FS_DIRTY_META,
659660
F2FS_INMEM_PAGES,
661+
F2FS_DIRTY_IMETA,
660662
NR_COUNT_TYPE,
661663
};
662664

@@ -707,6 +709,7 @@ struct f2fs_bio_info {
707709
enum inode_type {
708710
DIR_INODE, /* for dirty dir inode */
709711
FILE_INODE, /* for dirty regular/symlink inode */
712+
DIRTY_META, /* for all dirtied inode metadata */
710713
NR_INODE_TYPE,
711714
};
712715

@@ -1899,6 +1902,7 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
18991902
/*
19001903
* super.c
19011904
*/
1905+
void f2fs_inode_synced(struct inode *);
19021906
int f2fs_commit_super(struct f2fs_sb_info *, bool);
19031907
int f2fs_sync_fs(struct super_block *, int);
19041908
extern __printf(3, 4)
@@ -2010,6 +2014,7 @@ void add_ino_entry(struct f2fs_sb_info *, nid_t, int type);
20102014
void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
20112015
void release_ino_entry(struct f2fs_sb_info *, bool);
20122016
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
2017+
int f2fs_sync_inode_meta(struct f2fs_sb_info *);
20132018
int acquire_orphan_inode(struct f2fs_sb_info *);
20142019
void release_orphan_inode(struct f2fs_sb_info *);
20152020
void add_orphan_inode(struct f2fs_sb_info *, nid_t);
@@ -2078,7 +2083,7 @@ struct f2fs_stat_info {
20782083
unsigned long long hit_total, total_ext;
20792084
int ext_tree, zombie_tree, ext_node;
20802085
s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
2081-
unsigned int ndirty_dirs, ndirty_files;
2086+
unsigned int ndirty_dirs, ndirty_files, ndirty_all;
20822087
int nats, dirty_nats, sits, dirty_sits, fnids;
20832088
int total_count, utilization;
20842089
int bg_gc, wb_bios;

fs/f2fs/inode.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ int update_inode(struct inode *inode, struct page *node_page)
262262

263263
__set_inode_rdev(inode, ri);
264264
set_cold_node(inode, node_page);
265-
clear_inode_flag(inode, FI_DIRTY_INODE);
265+
f2fs_inode_synced(inode);
266266

267267
/* deleted inode */
268268
if (inode->i_nlink == 0)
@@ -286,6 +286,7 @@ int update_inode_page(struct inode *inode)
286286
} else if (err != -ENOENT) {
287287
f2fs_stop_checkpoint(sbi, false);
288288
}
289+
f2fs_inode_synced(inode);
289290
return 0;
290291
}
291292
ret = update_inode(inode, node_page);
@@ -360,6 +361,8 @@ void f2fs_evict_inode(struct inode *inode)
360361
goto retry;
361362
}
362363

364+
if (err)
365+
update_inode_page(inode);
363366
sb_end_intwrite(inode->i_sb);
364367
no_delete:
365368
stat_dec_inline_xattr(inode);
@@ -381,6 +384,8 @@ void f2fs_evict_inode(struct inode *inode)
381384
!exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
382385
out_clear:
383386
fscrypt_put_encryption_info(inode, NULL);
387+
388+
f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE));
384389
clear_inode(inode);
385390
}
386391

fs/f2fs/node.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ static void truncate_node(struct dnode_of_data *dn)
670670
if (dn->nid == dn->inode->i_ino) {
671671
remove_orphan_inode(sbi, dn->nid);
672672
dec_valid_inode_count(sbi);
673+
f2fs_inode_synced(dn->inode);
673674
} else {
674675
sync_inode_page(dn);
675676
}

fs/f2fs/segment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed)
479479
int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
480480
int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
481481

482+
node_secs += get_blocktype_secs(sbi, F2FS_DIRTY_IMETA);
483+
482484
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
483485
return false;
484486

fs/f2fs/super.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
537537
fi->i_advise = 0;
538538
init_rwsem(&fi->i_sem);
539539
INIT_LIST_HEAD(&fi->dirty_list);
540+
INIT_LIST_HEAD(&fi->gdirty_list);
540541
INIT_LIST_HEAD(&fi->inmem_pages);
541542
mutex_init(&fi->inmem_lock);
542543

@@ -547,14 +548,16 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
547548

548549
static int f2fs_drop_inode(struct inode *inode)
549550
{
551+
int ret;
552+
550553
/*
551554
* This is to avoid a deadlock condition like below.
552555
* writeback_single_inode(inode)
553556
* - f2fs_write_data_page
554557
* - f2fs_gc -> iput -> evict
555558
* - inode_wait_for_writeback(inode)
556559
*/
557-
if (!inode_unhashed(inode) && inode->i_state & I_SYNC) {
560+
if ((!inode_unhashed(inode) && inode->i_state & I_SYNC)) {
558561
if (!inode->i_nlink && !is_bad_inode(inode)) {
559562
/* to avoid evict_inode call simultaneously */
560563
atomic_inc(&inode->i_count);
@@ -581,7 +584,20 @@ static int f2fs_drop_inode(struct inode *inode)
581584
}
582585
return 0;
583586
}
584-
return generic_drop_inode(inode);
587+
588+
ret = generic_drop_inode(inode);
589+
if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
590+
if (ret)
591+
inode->i_state |= I_WILL_FREE;
592+
spin_unlock(&inode->i_lock);
593+
594+
update_inode_page(inode);
595+
596+
spin_lock(&inode->i_lock);
597+
if (ret)
598+
inode->i_state &= ~I_WILL_FREE;
599+
}
600+
return ret;
585601
}
586602

587603
/*
@@ -591,7 +607,40 @@ static int f2fs_drop_inode(struct inode *inode)
591607
*/
592608
static void f2fs_dirty_inode(struct inode *inode, int flags)
593609
{
610+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
611+
612+
if (inode->i_ino == F2FS_NODE_INO(sbi) ||
613+
inode->i_ino == F2FS_META_INO(sbi))
614+
return;
615+
616+
spin_lock(&sbi->inode_lock[DIRTY_META]);
617+
if (is_inode_flag_set(inode, FI_DIRTY_INODE)) {
618+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
619+
return;
620+
}
621+
594622
set_inode_flag(inode, FI_DIRTY_INODE);
623+
list_add_tail(&F2FS_I(inode)->gdirty_list,
624+
&sbi->inode_list[DIRTY_META]);
625+
inc_page_count(sbi, F2FS_DIRTY_IMETA);
626+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
627+
stat_inc_dirty_inode(sbi, DIRTY_META);
628+
}
629+
630+
void f2fs_inode_synced(struct inode *inode)
631+
{
632+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
633+
634+
spin_lock(&sbi->inode_lock[DIRTY_META]);
635+
if (!is_inode_flag_set(inode, FI_DIRTY_INODE)) {
636+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
637+
return;
638+
}
639+
list_del_init(&F2FS_I(inode)->gdirty_list);
640+
clear_inode_flag(inode, FI_DIRTY_INODE);
641+
dec_page_count(sbi, F2FS_DIRTY_IMETA);
642+
spin_unlock(&sbi->inode_lock[DIRTY_META]);
643+
stat_dec_dirty_inode(F2FS_I_SB(inode), DIRTY_META);
595644
}
596645

597646
static void f2fs_i_callback(struct rcu_head *head)
@@ -1757,6 +1806,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
17571806
return 0;
17581807

17591808
free_kobj:
1809+
f2fs_sync_inode_meta(sbi);
17601810
kobject_del(&sbi->s_kobj);
17611811
kobject_put(&sbi->s_kobj);
17621812
wait_for_completion(&sbi->s_kobj_unregister);

0 commit comments

Comments
 (0)