mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 05:17:10 +09:00
UPSTREAM: f2fs: update_sit_entry_for_release() supports consecutive blocks.
This function can process some consecutive blocks at a time. When using update_sit_entry() to release consecutive blocks, ensure that the consecutive blocks belong to the same segment. Because after update_sit_entry_for_realese(), @segno is still in use in update_sit_entry(). Bug: 394006856 Change-Id: Ia6be213c3838351292d1000a52bd54a1090f1137 Signed-off-by: Yi Sun <yi.sun@unisoc.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> (cherry picked from commit 81ffbd224e5f926bf8df01d6107db9c8779f7d57)
This commit is contained in:
@@ -2304,6 +2304,10 @@ static void update_segment_mtime(struct f2fs_sb_info *sbi, block_t blkaddr,
|
|||||||
SIT_I(sbi)->max_mtime = ctime;
|
SIT_I(sbi)->max_mtime = ctime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: when updating multiple blocks at the same time, please ensure
|
||||||
|
* that the consecutive input blocks belong to the same segment.
|
||||||
|
*/
|
||||||
static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_entry *se,
|
static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_entry *se,
|
||||||
block_t blkaddr, unsigned int offset, int del)
|
block_t blkaddr, unsigned int offset, int del)
|
||||||
{
|
{
|
||||||
@@ -2311,43 +2315,49 @@ static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_ent
|
|||||||
#ifdef CONFIG_F2FS_CHECK_FS
|
#ifdef CONFIG_F2FS_CHECK_FS
|
||||||
bool mir_exist;
|
bool mir_exist;
|
||||||
#endif
|
#endif
|
||||||
|
int i;
|
||||||
|
int del_count = -del;
|
||||||
|
|
||||||
exist = f2fs_test_and_clear_bit(offset, se->cur_valid_map);
|
f2fs_bug_on(sbi, GET_SEGNO(sbi, blkaddr) != GET_SEGNO(sbi, blkaddr + del_count - 1));
|
||||||
|
|
||||||
|
for (i = 0; i < del_count; i++) {
|
||||||
|
exist = f2fs_test_and_clear_bit(offset + i, se->cur_valid_map);
|
||||||
#ifdef CONFIG_F2FS_CHECK_FS
|
#ifdef CONFIG_F2FS_CHECK_FS
|
||||||
mir_exist = f2fs_test_and_clear_bit(offset,
|
mir_exist = f2fs_test_and_clear_bit(offset + i,
|
||||||
se->cur_valid_map_mir);
|
se->cur_valid_map_mir);
|
||||||
if (unlikely(exist != mir_exist)) {
|
if (unlikely(exist != mir_exist)) {
|
||||||
f2fs_err(sbi, "Inconsistent error when clearing bitmap, blk:%u, old bit:%d",
|
f2fs_err(sbi, "Inconsistent error when clearing bitmap, blk:%u, old bit:%d",
|
||||||
blkaddr, exist);
|
blkaddr + i, exist);
|
||||||
f2fs_bug_on(sbi, 1);
|
f2fs_bug_on(sbi, 1);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (unlikely(!exist)) {
|
|
||||||
f2fs_err(sbi, "Bitmap was wrongly cleared, blk:%u", blkaddr);
|
|
||||||
f2fs_bug_on(sbi, 1);
|
|
||||||
se->valid_blocks++;
|
|
||||||
del = 0;
|
|
||||||
} else if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
|
|
||||||
/*
|
|
||||||
* If checkpoints are off, we must not reuse data that
|
|
||||||
* was used in the previous checkpoint. If it was used
|
|
||||||
* before, we must track that to know how much space we
|
|
||||||
* really have.
|
|
||||||
*/
|
|
||||||
if (f2fs_test_bit(offset, se->ckpt_valid_map)) {
|
|
||||||
spin_lock(&sbi->stat_lock);
|
|
||||||
sbi->unusable_block_count++;
|
|
||||||
spin_unlock(&sbi->stat_lock);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
if (unlikely(!exist)) {
|
||||||
|
f2fs_err(sbi, "Bitmap was wrongly cleared, blk:%u", blkaddr + i);
|
||||||
|
f2fs_bug_on(sbi, 1);
|
||||||
|
se->valid_blocks++;
|
||||||
|
del += 1;
|
||||||
|
} else if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
|
||||||
|
/*
|
||||||
|
* If checkpoints are off, we must not reuse data that
|
||||||
|
* was used in the previous checkpoint. If it was used
|
||||||
|
* before, we must track that to know how much space we
|
||||||
|
* really have.
|
||||||
|
*/
|
||||||
|
if (f2fs_test_bit(offset + i, se->ckpt_valid_map)) {
|
||||||
|
spin_lock(&sbi->stat_lock);
|
||||||
|
sbi->unusable_block_count++;
|
||||||
|
spin_unlock(&sbi->stat_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f2fs_block_unit_discard(sbi) &&
|
||||||
|
f2fs_test_and_clear_bit(offset + i, se->discard_map))
|
||||||
|
sbi->discard_blks++;
|
||||||
|
|
||||||
|
if (!f2fs_test_bit(offset + i, se->ckpt_valid_map))
|
||||||
|
se->ckpt_valid_blocks -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f2fs_block_unit_discard(sbi) &&
|
|
||||||
f2fs_test_and_clear_bit(offset, se->discard_map))
|
|
||||||
sbi->discard_blks++;
|
|
||||||
|
|
||||||
if (!f2fs_test_bit(offset, se->ckpt_valid_map))
|
|
||||||
se->ckpt_valid_blocks += del;
|
|
||||||
|
|
||||||
return del;
|
return del;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2395,6 +2405,11 @@ static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry
|
|||||||
return del;
|
return del;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If releasing blocks, this function supports updating multiple consecutive blocks
|
||||||
|
* at one time, but please note that these consecutive blocks need to belong to the
|
||||||
|
* same segment.
|
||||||
|
*/
|
||||||
static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
|
static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
|
||||||
{
|
{
|
||||||
struct seg_entry *se;
|
struct seg_entry *se;
|
||||||
|
|||||||
Reference in New Issue
Block a user