|
|
@@ -497,6 +497,33 @@ static inline int reserved_sections(struct f2fs_sb_info *sbi)
|
|
|
return GET_SEC_FROM_SEG(sbi, (unsigned int)reserved_segments(sbi));
|
|
|
}
|
|
|
|
|
|
+static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi)
|
|
|
+{
|
|
|
+ unsigned int node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) +
|
|
|
+ get_pages(sbi, F2FS_DIRTY_DENTS);
|
|
|
+ unsigned int dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS);
|
|
|
+ unsigned int segno, left_blocks;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* check current node segment */
|
|
|
+ for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
|
|
|
+ segno = CURSEG_I(sbi, i)->segno;
|
|
|
+ left_blocks = sbi->blocks_per_seg -
|
|
|
+ get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
|
+
|
|
|
+ if (node_blocks > left_blocks)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* check current data segment */
|
|
|
+ segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
|
|
|
+ left_blocks = sbi->blocks_per_seg -
|
|
|
+ get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
|
+ if (dent_blocks > left_blocks)
|
|
|
+ return false;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
|
|
|
int freed, int needed)
|
|
|
{
|
|
|
@@ -507,6 +534,9 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
|
|
|
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
|
|
|
return false;
|
|
|
|
|
|
+ if (free_sections(sbi) + freed == reserved_sections(sbi) + needed &&
|
|
|
+ has_curseg_enough_space(sbi))
|
|
|
+ return false;
|
|
|
return (free_sections(sbi) + freed) <=
|
|
|
(node_secs + 2 * dent_secs + imeta_secs +
|
|
|
reserved_sections(sbi) + needed);
|