* [PATCH 1/5] f2fs: add a slab cache entry for small discards
@ 2013-11-15 5:20 Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 2/5] f2fs: add key functions " Jaegeuk Kim
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Jaegeuk Kim @ 2013-11-15 5:20 UTC (permalink / raw)
Cc: Jaegeuk Kim, linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds a slab cache entry for small discards.
Each entry consists of:
struct discard_entry {
struct list_head list; /* list head */
block_t blkaddr; /* block address to be discarded */
int len; /* # of consecutive blocks of the discard */
};
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/f2fs.h | 14 ++++++++++++++
fs/f2fs/segment.c | 20 ++++++++++++++++++++
fs/f2fs/super.c | 7 ++++++-
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 89dc750..c73e3df 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -97,6 +97,13 @@ struct dir_inode_entry {
struct inode *inode; /* vfs inode pointer */
};
+/* for the list of blockaddresses to be discarded */
+struct discard_entry {
+ struct list_head list; /* list head */
+ block_t blkaddr; /* block address to be discarded */
+ int len; /* # of consecutive blocks of the discard */
+};
+
/* for the list of fsync inodes, used only during recovery */
struct fsync_inode_entry {
struct list_head list; /* list head */
@@ -308,6 +315,11 @@ struct f2fs_sm_info {
/* a threshold to reclaim prefree segments */
unsigned int rec_prefree_segments;
+
+ /* for small discard management */
+ struct list_head discard_list; /* 4KB discard list */
+ int nr_discards; /* # of discards in the list */
+ int max_discards; /* max. discards to be issued */
};
/*
@@ -1079,6 +1091,8 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *,
void flush_sit_entries(struct f2fs_sb_info *);
int build_segment_manager(struct f2fs_sb_info *);
void destroy_segment_manager(struct f2fs_sb_info *);
+int __init create_segment_manager_caches(void);
+void destroy_segment_manager_caches(void);
/*
* checkpoint.c
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 67f1e5b..823526e 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -22,6 +22,8 @@
#define __reverse_ffz(x) __reverse_ffs(~(x))
+static struct kmem_cache *discard_entry_slab;
+
/*
* __reverse_ffs is copied from include/asm-generic/bitops/__ffs.h since
* MSB and LSB are reversed in a byte by f2fs_set_bit.
@@ -1798,6 +1800,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
sm_info->rec_prefree_segments = DEF_RECLAIM_PREFREE_SEGMENTS;
+ INIT_LIST_HEAD(&sm_info->discard_list);
+ sm_info->nr_discards = 0;
+ sm_info->max_discards = 0;
+
err = build_sit_info(sbi);
if (err)
return err;
@@ -1913,3 +1919,17 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
sbi->sm_info = NULL;
kfree(sm_info);
}
+
+int __init create_segment_manager_caches(void)
+{
+ discard_entry_slab = f2fs_kmem_cache_create("discard_entry",
+ sizeof(struct discard_entry), NULL);
+ if (!discard_entry_slab)
+ return -ENOMEM;
+ return 0;
+}
+
+void destroy_segment_manager_caches(void)
+{
+ kmem_cache_destroy(discard_entry_slab);
+}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bafff72..e9aa3f7 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1078,9 +1078,12 @@ static int __init init_f2fs_fs(void)
err = create_node_manager_caches();
if (err)
goto free_inodecache;
- err = create_gc_caches();
+ err = create_segment_manager_caches();
if (err)
goto free_node_manager_caches;
+ err = create_gc_caches();
+ if (err)
+ goto free_segment_manager_caches;
err = create_checkpoint_caches();
if (err)
goto free_gc_caches;
@@ -1102,6 +1105,8 @@ free_checkpoint_caches:
destroy_checkpoint_caches();
free_gc_caches:
destroy_gc_caches();
+free_segment_manager_caches:
+ destroy_segment_manager_caches();
free_node_manager_caches:
destroy_node_manager_caches();
free_inodecache:
--
1.8.4.474.g128a96c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/5] f2fs: add key functions for small discards
2013-11-15 5:20 [PATCH 1/5] f2fs: add a slab cache entry for small discards Jaegeuk Kim
@ 2013-11-15 5:20 ` Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 3/5] f2fs: add a sysfs entry to control max_discards Jaegeuk Kim
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jaegeuk Kim @ 2013-11-15 5:20 UTC (permalink / raw)
Cc: Jaegeuk Kim, linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds key functions to activate the small discard feature.
Note that this procedure is conducted during the checkpoint only.
In flush_sit_entries(), when a new dirty sit entry is flushed, f2fs calls
add_discard_addrs() which searches candidates to be discarded.
The candidates should be marked *invalidated* and also previous checkpoint
recognizes it as *valid*.
At the end of a checkpoint procedure, f2fs throws discards based on the
discard entry list.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/segment.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 823526e..505a889 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -266,6 +266,47 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
mutex_unlock(&dirty_i->seglist_lock);
}
+static void add_discard_addrs(struct f2fs_sb_info *sbi,
+ unsigned int segno, struct seg_entry *se)
+{
+ struct list_head *head = &SM_I(sbi)->discard_list;
+ struct discard_entry *new;
+ int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+ int max_blocks = sbi->blocks_per_seg;
+ unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+ unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+ unsigned long dmap[entries];
+ unsigned int start = 0, end = -1;
+ int i;
+
+ if (!test_opt(sbi, DISCARD))
+ return;
+
+ /* zero block will be discarded through the prefree list */
+ if (!se->valid_blocks || se->valid_blocks == max_blocks)
+ return;
+
+ /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */
+ for (i = 0; i < entries; i++)
+ dmap[i] = (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i];
+
+ while (SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) {
+ start = __find_rev_next_bit(dmap, max_blocks, end + 1);
+ if (start >= max_blocks)
+ break;
+
+ end = __find_rev_next_zero_bit(dmap, max_blocks, start + 1);
+
+ new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS);
+ INIT_LIST_HEAD(&new->list);
+ new->blkaddr = START_BLOCK(sbi, segno) + start;
+ new->len = end - start;
+
+ list_add_tail(&new->list, head);
+ SM_I(sbi)->nr_discards += end - start;
+ }
+}
+
/*
* Should call clear_prefree_segments after checkpoint is done.
*/
@@ -288,6 +329,9 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
void clear_prefree_segments(struct f2fs_sb_info *sbi)
{
+ struct list_head *head = &(SM_I(sbi)->discard_list);
+ struct list_head *this, *next;
+ struct discard_entry *entry;
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
unsigned int total_segs = TOTAL_SEGS(sbi);
@@ -318,6 +362,18 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi)
GFP_NOFS, 0);
}
mutex_unlock(&dirty_i->seglist_lock);
+
+ /* send small discards */
+ list_for_each_safe(this, next, head) {
+ entry = list_entry(this, struct discard_entry, list);
+ blkdev_issue_discard(sbi->sb->s_bdev,
+ entry->blkaddr << sbi->log_sectors_per_block,
+ (1 << sbi->log_sectors_per_block) * entry->len,
+ GFP_NOFS, 0);
+ list_del(&entry->list);
+ SM_I(sbi)->nr_discards -= entry->len;
+ kmem_cache_free(discard_entry_slab, entry);
+ }
}
static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
@@ -1469,6 +1525,10 @@ void flush_sit_entries(struct f2fs_sb_info *sbi)
sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
+ /* add discard candidates */
+ if (SM_I(sbi)->nr_discards < SM_I(sbi)->max_discards)
+ add_discard_addrs(sbi, segno, se);
+
if (flushed)
goto to_sit_page;
--
1.8.4.474.g128a96c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/5] f2fs: add a sysfs entry to control max_discards
2013-11-15 5:20 [PATCH 1/5] f2fs: add a slab cache entry for small discards Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 2/5] f2fs: add key functions " Jaegeuk Kim
@ 2013-11-15 5:20 ` Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 4/5] f2fs: introduce f2fs_issue_discard() to clean up Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 5/5] f2fs: add a tracepoint for f2fs_issue_discard Jaegeuk Kim
3 siblings, 0 replies; 5+ messages in thread
From: Jaegeuk Kim @ 2013-11-15 5:20 UTC (permalink / raw)
Cc: Jaegeuk Kim, linux-fsdevel, linux-kernel, linux-f2fs-devel
If frequent small discards are issued to the device, the performance would
be degraded significantly.
So, this patch adds a sysfs entry to control the number of discards to be
issued during a checkpoint procedure.
By default, f2fs does not issue any small discards, which means max_discards
is zero.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/super.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index e9aa3f7..a022412 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -175,6 +175,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
+F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
static struct attribute *f2fs_attrs[] = {
@@ -183,6 +184,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(gc_no_gc_sleep_time),
ATTR_LIST(gc_idle),
ATTR_LIST(reclaim_segments),
+ ATTR_LIST(max_small_discards),
NULL,
};
--
1.8.4.474.g128a96c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/5] f2fs: introduce f2fs_issue_discard() to clean up
2013-11-15 5:20 [PATCH 1/5] f2fs: add a slab cache entry for small discards Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 2/5] f2fs: add key functions " Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 3/5] f2fs: add a sysfs entry to control max_discards Jaegeuk Kim
@ 2013-11-15 5:20 ` Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 5/5] f2fs: add a tracepoint for f2fs_issue_discard Jaegeuk Kim
3 siblings, 0 replies; 5+ messages in thread
From: Jaegeuk Kim @ 2013-11-15 5:20 UTC (permalink / raw)
Cc: Jaegeuk Kim, linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds f2fs_issue_discard() to clean up blkdev_issue_discard() flows.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/segment.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 505a889..d021cf3 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -266,6 +266,16 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
mutex_unlock(&dirty_i->seglist_lock);
}
+static void f2fs_issue_discard(struct f2fs_sb_info *sbi,
+ block_t blkstart, block_t blklen)
+{
+ sector_t sector_addr = blkstart << sbi->log_sectors_per_block;
+ sector_t sector_len = blklen << sbi->log_sectors_per_block;
+
+ blkdev_issue_discard(sbi->sb->s_bdev, sector_addr, sector_len,
+ GFP_NOFS, 0);
+}
+
static void add_discard_addrs(struct f2fs_sb_info *sbi,
unsigned int segno, struct seg_entry *se)
{
@@ -354,22 +364,15 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi)
if (!test_opt(sbi, DISCARD))
continue;
- blkdev_issue_discard(sbi->sb->s_bdev,
- START_BLOCK(sbi, start) <<
- sbi->log_sectors_per_block,
- (1 << (sbi->log_sectors_per_block +
- sbi->log_blocks_per_seg)) * (end - start),
- GFP_NOFS, 0);
+ f2fs_issue_discard(sbi, START_BLOCK(sbi, start),
+ (end - start) << sbi->log_blocks_per_seg);
}
mutex_unlock(&dirty_i->seglist_lock);
/* send small discards */
list_for_each_safe(this, next, head) {
entry = list_entry(this, struct discard_entry, list);
- blkdev_issue_discard(sbi->sb->s_bdev,
- entry->blkaddr << sbi->log_sectors_per_block,
- (1 << sbi->log_sectors_per_block) * entry->len,
- GFP_NOFS, 0);
+ f2fs_issue_discard(sbi, entry->blkaddr, entry->len);
list_del(&entry->list);
SM_I(sbi)->nr_discards -= entry->len;
kmem_cache_free(discard_entry_slab, entry);
--
1.8.4.474.g128a96c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5/5] f2fs: add a tracepoint for f2fs_issue_discard
2013-11-15 5:20 [PATCH 1/5] f2fs: add a slab cache entry for small discards Jaegeuk Kim
` (2 preceding siblings ...)
2013-11-15 5:20 ` [PATCH 4/5] f2fs: introduce f2fs_issue_discard() to clean up Jaegeuk Kim
@ 2013-11-15 5:20 ` Jaegeuk Kim
3 siblings, 0 replies; 5+ messages in thread
From: Jaegeuk Kim @ 2013-11-15 5:20 UTC (permalink / raw)
Cc: Jaegeuk Kim, linux-fsdevel, linux-kernel, linux-f2fs-devel
This patch adds a tracepoint for f2fs_issue_discard.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
fs/f2fs/segment.c | 1 +
include/trace/events/f2fs.h | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index d021cf3..1f83999 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -274,6 +274,7 @@ static void f2fs_issue_discard(struct f2fs_sb_info *sbi,
blkdev_issue_discard(sbi->sb->s_bdev, sector_addr, sector_len,
GFP_NOFS, 0);
+ trace_f2fs_issue_discard(sbi->sb, blkstart, blklen);
}
static void add_discard_addrs(struct f2fs_sb_info *sbi,
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index e0dc355..47ee70d 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -727,6 +727,29 @@ TRACE_EVENT(f2fs_write_checkpoint,
__entry->msg)
);
+TRACE_EVENT(f2fs_issue_discard,
+
+ TP_PROTO(struct super_block *sb, block_t blkstart, block_t blklen),
+
+ TP_ARGS(sb, blkstart, blklen),
+
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(block_t, blkstart)
+ __field(block_t, blklen)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = sb->s_dev;
+ __entry->blkstart = blkstart;
+ __entry->blklen = blklen;
+ ),
+
+ TP_printk("dev = (%d,%d), blkstart = 0x%llx, blklen = 0x%llx",
+ show_dev(__entry),
+ (unsigned long long)__entry->blkstart,
+ (unsigned long long)__entry->blklen)
+);
#endif /* _TRACE_F2FS_H */
/* This part must be outside protection */
--
1.8.4.474.g128a96c
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-11-15 5:22 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-15 5:20 [PATCH 1/5] f2fs: add a slab cache entry for small discards Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 2/5] f2fs: add key functions " Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 3/5] f2fs: add a sysfs entry to control max_discards Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 4/5] f2fs: introduce f2fs_issue_discard() to clean up Jaegeuk Kim
2013-11-15 5:20 ` [PATCH 5/5] f2fs: add a tracepoint for f2fs_issue_discard Jaegeuk Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).