[PATCH 3/3] f2fs: flush dirty directory pages when scattered pages are gathered

From: Jaegeuk Kim
Date: Tue Apr 15 2014 - 06:59:43 EST


If a lot of directory inodes have the small number of dentry pages in each
page cache, there is no chance to flush them periodically.
This patch proposes the average number of dirty dentry pages for the threshold.

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@xxxxxxxxxxx>
---
fs/f2fs/checkpoint.c | 2 ++
fs/f2fs/f2fs.h | 1 +
fs/f2fs/segment.h | 16 +++++++++-------
fs/f2fs/super.c | 1 +
4 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 5133aec..d57d93f 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -562,6 +562,7 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
set_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
F2FS_I(inode)->dirty_dir = new;
list_add_tail(&new->list, &sbi->dir_inode_list);
+ atomic_inc(&sbi->dirty_dir_inodes);
stat_inc_dirty_dir(sbi);
return 0;
}
@@ -626,6 +627,7 @@ void remove_dirty_dir_inode(struct inode *inode)
list_del(&entry->list);
F2FS_I(inode)->dirty_dir = NULL;
clear_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
+ atomic_dec(&sbi->dirty_dir_inodes);
stat_dec_dirty_dir(sbi);
spin_unlock(&sbi->dir_inode_lock);
kmem_cache_free(inode_entry_slab, entry);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d3180f8..e708d02 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -450,6 +450,7 @@ struct f2fs_sb_info {

/* for directory inode management */
struct list_head dir_inode_list; /* dir inode list */
+ atomic_t dirty_dir_inodes; /* # of dirty inodes */
spinlock_t dir_inode_lock; /* for dir inode list lock */

/* basic file system units */
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 7091204..8eb23a0 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -668,20 +668,22 @@ static inline unsigned int max_hw_blocks(struct f2fs_sb_info *sbi)
/*
* It is very important to gather dirty pages and write at once, so that we can
* submit a big bio without interfering other data writes.
- * By default, 512 pages for directory data,
+ * By default, avg. dirty pages for directory data,
* 512 pages (2MB) * 3 for three types of nodes, and
* max_bio_blocks for meta are set.
*/
static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
{
- if (type == DATA)
- return sbi->blocks_per_seg;
- else if (type == NODE)
+ if (type == DATA) {
+ unsigned int dirty = atomic_read(&sbi->dirty_dir_inodes);
+ if (dirty > sbi->blocks_per_seg * sbi->blocks_per_seg)
+ return div_u64(get_pages(sbi, F2FS_DIRTY_DENTS), dirty);
+ } else if (type == NODE) {
return 3 * sbi->blocks_per_seg;
- else if (type == META)
+ } else if (type == META) {
return MAX_BIO_BLOCKS(max_hw_blocks(sbi));
- else
- return 0;
+ }
+ return sbi->blocks_per_seg;
}

/*
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 5e20d2a..eabf8df 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -973,6 +973,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
sbi->last_valid_block_count = sbi->total_valid_block_count;
sbi->alloc_valid_block_count = 0;
INIT_LIST_HEAD(&sbi->dir_inode_list);
+ atomic_set(&sbi->dirty_dir_inodes, 0);
spin_lock_init(&sbi->dir_inode_lock);

init_orphan_info(sbi);
--
1.8.4.474.g128a96c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/