Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f18b462 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

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: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 205b9822
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -859,6 +859,34 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
	goto retry;
}

int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
{
	struct list_head *head = &sbi->inode_list[DIRTY_META];
	struct inode *inode;
	struct f2fs_inode_info *fi;
	s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);

	while (total--) {
		if (unlikely(f2fs_cp_error(sbi)))
			return -EIO;

		spin_lock(&sbi->inode_lock[DIRTY_META]);
		if (list_empty(head)) {
			spin_unlock(&sbi->inode_lock[DIRTY_META]);
			return 0;
		}
		fi = list_entry(head->next, struct f2fs_inode_info,
							gdirty_list);
		inode = igrab(&fi->vfs_inode);
		spin_unlock(&sbi->inode_lock[DIRTY_META]);
		if (inode) {
			update_inode_page(inode);
			iput(inode);
		}
	};
	return 0;
}

/*
 * Freeze all the FS-operations for checkpoint.
 */
@@ -885,6 +913,14 @@ static int block_operations(struct f2fs_sb_info *sbi)
		goto retry_flush_dents;
	}

	if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
		f2fs_unlock_all(sbi);
		err = f2fs_sync_inode_meta(sbi);
		if (err)
			goto out;
		goto retry_flush_dents;
	}

	/*
	 * POR: we should ensure that there are no dirty node pages
	 * until finishing nat/sit flush.
+3 −2
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
	si->ndirty_data = get_pages(sbi, F2FS_DIRTY_DATA);
	si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
	si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
	si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
	si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
	si->wb_bios = atomic_read(&sbi->nr_wb_bios);
	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)
			   si->inmem_pages, si->wb_bios);
		seq_printf(s, "  - nodes: %4lld in %4d\n",
			   si->ndirty_node, si->node_pages);
		seq_printf(s, "  - dents: %4lld in dirs:%4d\n",
			   si->ndirty_dent, si->ndirty_dirs);
		seq_printf(s, "  - dents: %4lld in dirs:%4d (%4d)\n",
			   si->ndirty_dent, si->ndirty_dirs, si->ndirty_all);
		seq_printf(s, "  - datas: %4lld in files:%4d\n",
			   si->ndirty_data, si->ndirty_files);
		seq_printf(s, "  - meta: %4lld in %4d\n",
+7 −2
Original line number Diff line number Diff line
@@ -442,7 +442,8 @@ struct f2fs_inode_info {
	nid_t i_xattr_nid;		/* node id that contains xattrs */
	unsigned long long xattr_ver;	/* cp version of xattr modification */

	struct list_head dirty_list;	/* linked in global dirty list */
	struct list_head dirty_list;	/* dirty list for dirs and files */
	struct list_head gdirty_list;	/* linked in global dirty list */
	struct list_head inmem_pages;	/* inmemory pages managed by f2fs */
	struct mutex inmem_lock;	/* lock for inmemory pages */
	struct extent_tree *extent_tree;	/* cached extent_tree entry */
@@ -657,6 +658,7 @@ enum count_type {
	F2FS_DIRTY_NODES,
	F2FS_DIRTY_META,
	F2FS_INMEM_PAGES,
	F2FS_DIRTY_IMETA,
	NR_COUNT_TYPE,
};

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

@@ -1899,6 +1902,7 @@ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
/*
 * super.c
 */
void f2fs_inode_synced(struct inode *);
int f2fs_commit_super(struct f2fs_sb_info *, bool);
int f2fs_sync_fs(struct super_block *, int);
extern __printf(3, 4)
@@ -2010,6 +2014,7 @@ void add_ino_entry(struct f2fs_sb_info *, nid_t, int type);
void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
void release_ino_entry(struct f2fs_sb_info *, bool);
bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
int f2fs_sync_inode_meta(struct f2fs_sb_info *);
int acquire_orphan_inode(struct f2fs_sb_info *);
void release_orphan_inode(struct f2fs_sb_info *);
void add_orphan_inode(struct f2fs_sb_info *, nid_t);
@@ -2078,7 +2083,7 @@ struct f2fs_stat_info {
	unsigned long long hit_total, total_ext;
	int ext_tree, zombie_tree, ext_node;
	s64 ndirty_node, ndirty_dent, ndirty_meta, ndirty_data, inmem_pages;
	unsigned int ndirty_dirs, ndirty_files;
	unsigned int ndirty_dirs, ndirty_files, ndirty_all;
	int nats, dirty_nats, sits, dirty_sits, fnids;
	int total_count, utilization;
	int bg_gc, wb_bios;
+6 −1
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ int update_inode(struct inode *inode, struct page *node_page)

	__set_inode_rdev(inode, ri);
	set_cold_node(inode, node_page);
	clear_inode_flag(inode, FI_DIRTY_INODE);
	f2fs_inode_synced(inode);

	/* deleted inode */
	if (inode->i_nlink == 0)
@@ -286,6 +286,7 @@ int update_inode_page(struct inode *inode)
		} else if (err != -ENOENT) {
			f2fs_stop_checkpoint(sbi, false);
		}
		f2fs_inode_synced(inode);
		return 0;
	}
	ret = update_inode(inode, node_page);
@@ -360,6 +361,8 @@ void f2fs_evict_inode(struct inode *inode)
		goto retry;
	}

	if (err)
		update_inode_page(inode);
	sb_end_intwrite(inode->i_sb);
no_delete:
	stat_dec_inline_xattr(inode);
@@ -381,6 +384,8 @@ void f2fs_evict_inode(struct inode *inode)
		!exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
out_clear:
	fscrypt_put_encryption_info(inode, NULL);

	f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE));
	clear_inode(inode);
}

+1 −0
Original line number Diff line number Diff line
@@ -670,6 +670,7 @@ static void truncate_node(struct dnode_of_data *dn)
	if (dn->nid == dn->inode->i_ino) {
		remove_orphan_inode(sbi, dn->nid);
		dec_valid_inode_count(sbi);
		f2fs_inode_synced(dn->inode);
	} else {
		sync_inode_page(dn);
	}
Loading