summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/segment.c
diff options
context:
space:
mode:
authorChangman Lee <cm224.lee@samsung.com>2013-11-10 19:24:37 -0500
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-11-10 19:36:32 -0500
commit29e59c14ae5c21d25db1580d9651b5855d656a30 (patch)
tree28464aff2be40ae89b1b37c221529a8a23cbff09 /fs/f2fs/segment.c
parent1d15bd2034c9b0f9ac88fa0e4cd33e0d792b0bb0 (diff)
f2fs: issue more large discard command
o Changes from v1 Use find_next(_zero)_bit suggested by jg.kim When f2fs issues discard command, if segment is contiguous, let's issue more large segment to gather adjacent segments. ** blktrace ** 179,1 0 5859 42.619023770 971 C D 131072 + 2097152 [0] 179,1 0 33665 108.840475468 971 C D 2228224 + 2494464 [0] 179,1 0 33671 109.131616427 971 C D 14909440 + 344064 [0] 179,1 0 33677 109.137100677 971 C D 15261696 + 4096 [0] Signed-off-by: Changman Lee <cm224.lee@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/segment.c')
-rw-r--r--fs/f2fs/segment.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 86dc28949192..fa284d397199 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -139,27 +139,33 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
139void clear_prefree_segments(struct f2fs_sb_info *sbi) 139void clear_prefree_segments(struct f2fs_sb_info *sbi)
140{ 140{
141 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); 141 struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
142 unsigned int segno = -1; 142 unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
143 unsigned int total_segs = TOTAL_SEGS(sbi); 143 unsigned int total_segs = TOTAL_SEGS(sbi);
144 unsigned int start = 0, end = -1;
144 145
145 mutex_lock(&dirty_i->seglist_lock); 146 mutex_lock(&dirty_i->seglist_lock);
147
146 while (1) { 148 while (1) {
147 segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, 149 int i;
148 segno + 1); 150 start = find_next_bit(prefree_map, total_segs, end + 1);
149 if (segno >= total_segs) 151 if (start >= total_segs)
150 break; 152 break;
153 end = find_next_zero_bit(prefree_map, total_segs, start + 1);
154
155 for (i = start; i < end; i++)
156 clear_bit(i, prefree_map);
157
158 dirty_i->nr_dirty[PRE] -= end - start;
159
160 if (!test_opt(sbi, DISCARD))
161 continue;
151 162
152 if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) 163 blkdev_issue_discard(sbi->sb->s_bdev,
153 dirty_i->nr_dirty[PRE]--; 164 START_BLOCK(sbi, start) <<
154 165 sbi->log_sectors_per_block,
155 /* Let's use trim */ 166 (1 << (sbi->log_sectors_per_block +
156 if (test_opt(sbi, DISCARD)) 167 sbi->log_blocks_per_seg)) * (end - start),
157 blkdev_issue_discard(sbi->sb->s_bdev, 168 GFP_NOFS, 0);
158 START_BLOCK(sbi, segno) <<
159 sbi->log_sectors_per_block,
160 1 << (sbi->log_sectors_per_block +
161 sbi->log_blocks_per_seg),
162 GFP_NOFS, 0);
163 } 169 }
164 mutex_unlock(&dirty_i->seglist_lock); 170 mutex_unlock(&dirty_i->seglist_lock);
165} 171}