diff options
author | Changman Lee <cm224.lee@samsung.com> | 2013-11-10 19:24:37 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-11-10 19:36:32 -0500 |
commit | 29e59c14ae5c21d25db1580d9651b5855d656a30 (patch) | |
tree | 28464aff2be40ae89b1b37c221529a8a23cbff09 /fs/f2fs/segment.c | |
parent | 1d15bd2034c9b0f9ac88fa0e4cd33e0d792b0bb0 (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.c | 36 |
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) | |||
139 | void clear_prefree_segments(struct f2fs_sb_info *sbi) | 139 | void 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 | } |