.. | .. |
---|
16 | 16 | #define DEF_MAX_RECLAIM_PREFREE_SEGMENTS 4096 /* 8GB in maximum */ |
---|
17 | 17 | |
---|
18 | 18 | #define F2FS_MIN_SEGMENTS 9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */ |
---|
| 19 | +#define F2FS_MIN_META_SEGMENTS 8 /* SB + 2 (CP + SIT + NAT) + SSA */ |
---|
19 | 20 | |
---|
20 | 21 | /* L: Logical segment # in volume, R: Relative segment # in main area */ |
---|
21 | 22 | #define GET_L2R_SEGNO(free_i, segno) ((segno) - (free_i)->start_segno) |
---|
22 | 23 | #define GET_R2L_SEGNO(free_i, segno) ((segno) + (free_i)->start_segno) |
---|
23 | 24 | |
---|
24 | 25 | #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA) |
---|
25 | | -#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE) |
---|
| 26 | +#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE && (t) <= CURSEG_COLD_NODE) |
---|
| 27 | +#define SE_PAGETYPE(se) ((IS_NODESEG((se)->type) ? NODE : DATA)) |
---|
| 28 | + |
---|
| 29 | +static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, |
---|
| 30 | + unsigned short seg_type) |
---|
| 31 | +{ |
---|
| 32 | + f2fs_bug_on(sbi, seg_type >= NR_PERSISTENT_LOG); |
---|
| 33 | +} |
---|
26 | 34 | |
---|
27 | 35 | #define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA) |
---|
28 | 36 | #define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA) |
---|
.. | .. |
---|
34 | 42 | ((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \ |
---|
35 | 43 | ((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \ |
---|
36 | 44 | ((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \ |
---|
37 | | - ((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno)) |
---|
| 45 | + ((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno) || \ |
---|
| 46 | + ((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno) || \ |
---|
| 47 | + ((seg) == CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC)->segno)) |
---|
38 | 48 | |
---|
39 | 49 | #define IS_CURSEC(sbi, secno) \ |
---|
40 | 50 | (((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \ |
---|
.. | .. |
---|
48 | 58 | ((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \ |
---|
49 | 59 | (sbi)->segs_per_sec) || \ |
---|
50 | 60 | ((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \ |
---|
51 | | - (sbi)->segs_per_sec)) \ |
---|
| 61 | + (sbi)->segs_per_sec) || \ |
---|
| 62 | + ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA_PINNED)->segno / \ |
---|
| 63 | + (sbi)->segs_per_sec) || \ |
---|
| 64 | + ((secno) == CURSEG_I(sbi, CURSEG_ALL_DATA_ATGC)->segno / \ |
---|
| 65 | + (sbi)->segs_per_sec)) |
---|
52 | 66 | |
---|
53 | 67 | #define MAIN_BLKADDR(sbi) \ |
---|
54 | 68 | (SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \ |
---|
.. | .. |
---|
132 | 146 | * In the victim_sel_policy->alloc_mode, there are two block allocation modes. |
---|
133 | 147 | * LFS writes data sequentially with cleaning operations. |
---|
134 | 148 | * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations. |
---|
| 149 | + * AT_SSR (Age Threshold based Slack Space Recycle) merges fragments into |
---|
| 150 | + * fragmented segment which has similar aging degree. |
---|
135 | 151 | */ |
---|
136 | 152 | enum { |
---|
137 | 153 | LFS = 0, |
---|
138 | | - SSR |
---|
| 154 | + SSR, |
---|
| 155 | + AT_SSR, |
---|
139 | 156 | }; |
---|
140 | 157 | |
---|
141 | 158 | /* |
---|
142 | 159 | * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes. |
---|
143 | 160 | * GC_CB is based on cost-benefit algorithm. |
---|
144 | 161 | * GC_GREEDY is based on greedy algorithm. |
---|
| 162 | + * GC_AT is based on age-threshold algorithm. |
---|
145 | 163 | */ |
---|
146 | 164 | enum { |
---|
147 | 165 | GC_CB = 0, |
---|
148 | 166 | GC_GREEDY, |
---|
| 167 | + GC_AT, |
---|
149 | 168 | ALLOC_NEXT, |
---|
150 | 169 | FLUSH_DEVICE, |
---|
151 | 170 | MAX_GC_POLICY, |
---|
.. | .. |
---|
154 | 173 | /* |
---|
155 | 174 | * BG_GC means the background cleaning job. |
---|
156 | 175 | * FG_GC means the on-demand cleaning job. |
---|
157 | | - * FORCE_FG_GC means on-demand cleaning job in background. |
---|
158 | 176 | */ |
---|
159 | 177 | enum { |
---|
160 | 178 | BG_GC = 0, |
---|
161 | 179 | FG_GC, |
---|
162 | | - FORCE_FG_GC, |
---|
163 | 180 | }; |
---|
164 | 181 | |
---|
165 | 182 | /* for a function parameter to select a victim segment */ |
---|
166 | 183 | struct victim_sel_policy { |
---|
167 | 184 | int alloc_mode; /* LFS or SSR */ |
---|
168 | 185 | int gc_mode; /* GC_CB or GC_GREEDY */ |
---|
169 | | - unsigned long *dirty_segmap; /* dirty segment bitmap */ |
---|
170 | | - unsigned int max_search; /* maximum # of segments to search */ |
---|
| 186 | + unsigned long *dirty_bitmap; /* dirty segment/section bitmap */ |
---|
| 187 | + unsigned int max_search; /* |
---|
| 188 | + * maximum # of segments/sections |
---|
| 189 | + * to search |
---|
| 190 | + */ |
---|
171 | 191 | unsigned int offset; /* last scanned bitmap offset */ |
---|
172 | 192 | unsigned int ofs_unit; /* bitmap search unit */ |
---|
173 | 193 | unsigned int min_cost; /* minimum cost */ |
---|
| 194 | + unsigned long long oldest_age; /* oldest age of segments having the same min cost */ |
---|
174 | 195 | unsigned int min_segno; /* segment # having min. cost */ |
---|
| 196 | + unsigned long long age; /* mtime of GCed section*/ |
---|
| 197 | + unsigned long long age_threshold;/* age threshold */ |
---|
175 | 198 | }; |
---|
176 | 199 | |
---|
177 | 200 | struct seg_entry { |
---|
.. | .. |
---|
184 | 207 | unsigned char *cur_valid_map_mir; /* mirror of current valid bitmap */ |
---|
185 | 208 | #endif |
---|
186 | 209 | /* |
---|
187 | | - * # of valid blocks and the validity bitmap stored in the the last |
---|
| 210 | + * # of valid blocks and the validity bitmap stored in the last |
---|
188 | 211 | * checkpoint pack. This information is used by the SSR mode. |
---|
189 | 212 | */ |
---|
190 | 213 | unsigned char *ckpt_valid_map; /* validity bitmap of blocks last cp */ |
---|
.. | .. |
---|
237 | 260 | unsigned long long mounted_time; /* mount time */ |
---|
238 | 261 | unsigned long long min_mtime; /* min. modification time */ |
---|
239 | 262 | unsigned long long max_mtime; /* max. modification time */ |
---|
| 263 | + unsigned long long dirty_min_mtime; /* rerange candidates in GC_AT */ |
---|
| 264 | + unsigned long long dirty_max_mtime; /* rerange candidates in GC_AT */ |
---|
240 | 265 | |
---|
241 | 266 | unsigned int last_victim[MAX_GC_POLICY]; /* last victim segment # */ |
---|
242 | 267 | }; |
---|
.. | .. |
---|
266 | 291 | struct dirty_seglist_info { |
---|
267 | 292 | const struct victim_selection *v_ops; /* victim selction operation */ |
---|
268 | 293 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; |
---|
| 294 | + unsigned long *dirty_secmap; |
---|
269 | 295 | struct mutex seglist_lock; /* lock for segment bitmaps */ |
---|
270 | 296 | int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ |
---|
271 | 297 | unsigned long *victim_secmap; /* background GC victims */ |
---|
.. | .. |
---|
274 | 300 | /* victim selection function for cleaning and SSR */ |
---|
275 | 301 | struct victim_selection { |
---|
276 | 302 | int (*get_victim)(struct f2fs_sb_info *, unsigned int *, |
---|
277 | | - int, int, char); |
---|
| 303 | + int, int, char, unsigned long long); |
---|
278 | 304 | }; |
---|
279 | 305 | |
---|
280 | 306 | /* for active log information */ |
---|
.. | .. |
---|
284 | 310 | struct rw_semaphore journal_rwsem; /* protect journal area */ |
---|
285 | 311 | struct f2fs_journal *journal; /* cached journal info */ |
---|
286 | 312 | unsigned char alloc_type; /* current allocation type */ |
---|
| 313 | + unsigned short seg_type; /* segment type like CURSEG_XXX_TYPE */ |
---|
287 | 314 | unsigned int segno; /* current segment number */ |
---|
288 | 315 | unsigned short next_blkoff; /* next block offset to write */ |
---|
289 | 316 | unsigned int zone; /* current zone number */ |
---|
290 | 317 | unsigned int next_segno; /* preallocated segment */ |
---|
| 318 | + bool inited; /* indicate inmem log is inited */ |
---|
291 | 319 | }; |
---|
292 | 320 | |
---|
293 | 321 | struct sit_entry_set { |
---|
.. | .. |
---|
301 | 329 | */ |
---|
302 | 330 | static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) |
---|
303 | 331 | { |
---|
304 | | - if (type == CURSEG_COLD_DATA_PINNED) |
---|
305 | | - type = CURSEG_COLD_DATA; |
---|
306 | 332 | return (struct curseg_info *)(SM_I(sbi)->curseg_array + type); |
---|
307 | 333 | } |
---|
308 | 334 | |
---|
.. | .. |
---|
334 | 360 | } |
---|
335 | 361 | |
---|
336 | 362 | static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi, |
---|
337 | | - unsigned int segno) |
---|
| 363 | + unsigned int segno, bool use_section) |
---|
338 | 364 | { |
---|
| 365 | + if (use_section && __is_large_section(sbi)) { |
---|
| 366 | + unsigned int start_segno = START_SEGNO(segno); |
---|
| 367 | + unsigned int blocks = 0; |
---|
| 368 | + int i; |
---|
| 369 | + |
---|
| 370 | + for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) { |
---|
| 371 | + struct seg_entry *se = get_seg_entry(sbi, start_segno); |
---|
| 372 | + |
---|
| 373 | + blocks += se->ckpt_valid_blocks; |
---|
| 374 | + } |
---|
| 375 | + return blocks; |
---|
| 376 | + } |
---|
339 | 377 | return get_seg_entry(sbi, segno)->ckpt_valid_blocks; |
---|
340 | 378 | } |
---|
341 | 379 | |
---|
.. | .. |
---|
407 | 445 | unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); |
---|
408 | 446 | unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno); |
---|
409 | 447 | unsigned int next; |
---|
| 448 | + unsigned int usable_segs = f2fs_usable_segs_in_sec(sbi, segno); |
---|
410 | 449 | |
---|
411 | 450 | spin_lock(&free_i->segmap_lock); |
---|
412 | 451 | clear_bit(segno, free_i->free_segmap); |
---|
.. | .. |
---|
414 | 453 | |
---|
415 | 454 | next = find_next_bit(free_i->free_segmap, |
---|
416 | 455 | start_segno + sbi->segs_per_sec, start_segno); |
---|
417 | | - if (next >= start_segno + sbi->segs_per_sec) { |
---|
| 456 | + if (next >= start_segno + usable_segs) { |
---|
418 | 457 | clear_bit(secno, free_i->free_secmap); |
---|
419 | 458 | free_i->free_sections++; |
---|
420 | 459 | } |
---|
.. | .. |
---|
434 | 473 | } |
---|
435 | 474 | |
---|
436 | 475 | static inline void __set_test_and_free(struct f2fs_sb_info *sbi, |
---|
437 | | - unsigned int segno) |
---|
| 476 | + unsigned int segno, bool inmem) |
---|
438 | 477 | { |
---|
439 | 478 | struct free_segmap_info *free_i = FREE_I(sbi); |
---|
440 | 479 | unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); |
---|
441 | 480 | unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno); |
---|
442 | 481 | unsigned int next; |
---|
| 482 | + unsigned int usable_segs = f2fs_usable_segs_in_sec(sbi, segno); |
---|
443 | 483 | |
---|
444 | 484 | spin_lock(&free_i->segmap_lock); |
---|
445 | 485 | if (test_and_clear_bit(segno, free_i->free_segmap)) { |
---|
446 | 486 | free_i->free_segments++; |
---|
447 | 487 | |
---|
448 | | - if (IS_CURSEC(sbi, secno)) |
---|
| 488 | + if (!inmem && IS_CURSEC(sbi, secno)) |
---|
449 | 489 | goto skip_free; |
---|
450 | 490 | next = find_next_bit(free_i->free_segmap, |
---|
451 | 491 | start_segno + sbi->segs_per_sec, start_segno); |
---|
452 | | - if (next >= start_segno + sbi->segs_per_sec) { |
---|
| 492 | + if (next >= start_segno + usable_segs) { |
---|
453 | 493 | if (test_and_clear_bit(secno, free_i->free_secmap)) |
---|
454 | 494 | free_i->free_sections++; |
---|
455 | 495 | } |
---|
.. | .. |
---|
496 | 536 | return FREE_I(sbi)->free_segments; |
---|
497 | 537 | } |
---|
498 | 538 | |
---|
499 | | -static inline int reserved_segments(struct f2fs_sb_info *sbi) |
---|
| 539 | +static inline unsigned int reserved_segments(struct f2fs_sb_info *sbi) |
---|
500 | 540 | { |
---|
501 | | - return SM_I(sbi)->reserved_segments; |
---|
| 541 | + return SM_I(sbi)->reserved_segments + |
---|
| 542 | + SM_I(sbi)->additional_reserved_segments; |
---|
502 | 543 | } |
---|
503 | 544 | |
---|
504 | 545 | static inline unsigned int free_sections(struct f2fs_sb_info *sbi) |
---|
.. | .. |
---|
528 | 569 | |
---|
529 | 570 | static inline int reserved_sections(struct f2fs_sb_info *sbi) |
---|
530 | 571 | { |
---|
531 | | - return GET_SEC_FROM_SEG(sbi, (unsigned int)reserved_segments(sbi)); |
---|
| 572 | + return GET_SEC_FROM_SEG(sbi, reserved_segments(sbi)); |
---|
532 | 573 | } |
---|
533 | 574 | |
---|
534 | | -static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi) |
---|
| 575 | +static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, |
---|
| 576 | + unsigned int node_blocks, unsigned int dent_blocks) |
---|
535 | 577 | { |
---|
536 | | - unsigned int node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + |
---|
537 | | - get_pages(sbi, F2FS_DIRTY_DENTS); |
---|
538 | | - unsigned int dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS); |
---|
| 578 | + |
---|
539 | 579 | unsigned int segno, left_blocks; |
---|
540 | 580 | int i; |
---|
541 | 581 | |
---|
542 | 582 | /* check current node segment */ |
---|
543 | 583 | for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) { |
---|
544 | 584 | segno = CURSEG_I(sbi, i)->segno; |
---|
545 | | - left_blocks = sbi->blocks_per_seg - |
---|
546 | | - get_seg_entry(sbi, segno)->ckpt_valid_blocks; |
---|
| 585 | + left_blocks = f2fs_usable_blks_in_seg(sbi, segno) - |
---|
| 586 | + get_seg_entry(sbi, segno)->ckpt_valid_blocks; |
---|
547 | 587 | |
---|
548 | 588 | if (node_blocks > left_blocks) |
---|
549 | 589 | return false; |
---|
.. | .. |
---|
551 | 591 | |
---|
552 | 592 | /* check current data segment */ |
---|
553 | 593 | segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno; |
---|
554 | | - left_blocks = sbi->blocks_per_seg - |
---|
| 594 | + left_blocks = f2fs_usable_blks_in_seg(sbi, segno) - |
---|
555 | 595 | get_seg_entry(sbi, segno)->ckpt_valid_blocks; |
---|
556 | 596 | if (dent_blocks > left_blocks) |
---|
557 | 597 | return false; |
---|
.. | .. |
---|
561 | 601 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, |
---|
562 | 602 | int freed, int needed) |
---|
563 | 603 | { |
---|
564 | | - int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); |
---|
565 | | - int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); |
---|
566 | | - int imeta_secs = get_blocktype_secs(sbi, F2FS_DIRTY_IMETA); |
---|
| 604 | + unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) + |
---|
| 605 | + get_pages(sbi, F2FS_DIRTY_DENTS) + |
---|
| 606 | + get_pages(sbi, F2FS_DIRTY_IMETA); |
---|
| 607 | + unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS); |
---|
| 608 | + unsigned int node_secs = total_node_blocks / BLKS_PER_SEC(sbi); |
---|
| 609 | + unsigned int dent_secs = total_dent_blocks / BLKS_PER_SEC(sbi); |
---|
| 610 | + unsigned int node_blocks = total_node_blocks % BLKS_PER_SEC(sbi); |
---|
| 611 | + unsigned int dent_blocks = total_dent_blocks % BLKS_PER_SEC(sbi); |
---|
| 612 | + unsigned int free, need_lower, need_upper; |
---|
567 | 613 | |
---|
568 | 614 | if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
---|
569 | 615 | return false; |
---|
570 | 616 | |
---|
571 | | - if (free_sections(sbi) + freed == reserved_sections(sbi) + needed && |
---|
572 | | - has_curseg_enough_space(sbi)) |
---|
| 617 | + free = free_sections(sbi) + freed; |
---|
| 618 | + need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed; |
---|
| 619 | + need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0); |
---|
| 620 | + |
---|
| 621 | + if (free > need_upper) |
---|
573 | 622 | return false; |
---|
574 | | - return (free_sections(sbi) + freed) <= |
---|
575 | | - (node_secs + 2 * dent_secs + imeta_secs + |
---|
576 | | - reserved_sections(sbi) + needed); |
---|
| 623 | + else if (free <= need_lower) |
---|
| 624 | + return true; |
---|
| 625 | + return !has_curseg_enough_space(sbi, node_blocks, dent_blocks); |
---|
577 | 626 | } |
---|
578 | 627 | |
---|
579 | 628 | static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) |
---|
.. | .. |
---|
610 | 659 | * pages over min_fsync_blocks. (=default option) |
---|
611 | 660 | * F2FS_IPU_ASYNC - do IPU given by asynchronous write requests. |
---|
612 | 661 | * F2FS_IPU_NOCACHE - disable IPU bio cache. |
---|
613 | | - * F2FS_IPUT_DISABLE - disable IPU. (=default option in LFS mode) |
---|
| 662 | + * F2FS_IPU_HONOR_OPU_WRITE - use OPU write prior to IPU write if inode has |
---|
| 663 | + * FI_OPU_WRITE flag. |
---|
| 664 | + * F2FS_IPU_DISABLE - disable IPU. (=default option in LFS mode) |
---|
614 | 665 | */ |
---|
615 | 666 | #define DEF_MIN_IPU_UTIL 70 |
---|
616 | 667 | #define DEF_MIN_FSYNC_BLOCKS 8 |
---|
.. | .. |
---|
626 | 677 | F2FS_IPU_FSYNC, |
---|
627 | 678 | F2FS_IPU_ASYNC, |
---|
628 | 679 | F2FS_IPU_NOCACHE, |
---|
| 680 | + F2FS_IPU_HONOR_OPU_WRITE, |
---|
629 | 681 | }; |
---|
630 | 682 | |
---|
631 | 683 | static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, |
---|
.. | .. |
---|
673 | 725 | bool is_valid = test_bit_le(0, raw_sit->valid_map) ? true : false; |
---|
674 | 726 | int valid_blocks = 0; |
---|
675 | 727 | int cur_pos = 0, next_pos; |
---|
| 728 | + unsigned int usable_blks_per_seg = f2fs_usable_blks_in_seg(sbi, segno); |
---|
676 | 729 | |
---|
677 | 730 | /* check bitmap with valid block count */ |
---|
678 | 731 | do { |
---|
679 | 732 | if (is_valid) { |
---|
680 | 733 | next_pos = find_next_zero_bit_le(&raw_sit->valid_map, |
---|
681 | | - sbi->blocks_per_seg, |
---|
| 734 | + usable_blks_per_seg, |
---|
682 | 735 | cur_pos); |
---|
683 | 736 | valid_blocks += next_pos - cur_pos; |
---|
684 | 737 | } else |
---|
685 | 738 | next_pos = find_next_bit_le(&raw_sit->valid_map, |
---|
686 | | - sbi->blocks_per_seg, |
---|
| 739 | + usable_blks_per_seg, |
---|
687 | 740 | cur_pos); |
---|
688 | 741 | cur_pos = next_pos; |
---|
689 | 742 | is_valid = !is_valid; |
---|
690 | | - } while (cur_pos < sbi->blocks_per_seg); |
---|
| 743 | + } while (cur_pos < usable_blks_per_seg); |
---|
691 | 744 | |
---|
692 | 745 | if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) { |
---|
693 | 746 | f2fs_err(sbi, "Mismatch valid blocks %d vs. %d", |
---|
.. | .. |
---|
696 | 749 | return -EFSCORRUPTED; |
---|
697 | 750 | } |
---|
698 | 751 | |
---|
| 752 | + if (usable_blks_per_seg < sbi->blocks_per_seg) |
---|
| 753 | + f2fs_bug_on(sbi, find_next_bit_le(&raw_sit->valid_map, |
---|
| 754 | + sbi->blocks_per_seg, |
---|
| 755 | + usable_blks_per_seg) != sbi->blocks_per_seg); |
---|
| 756 | + |
---|
699 | 757 | /* check segment usage, and check boundary of a given segment number */ |
---|
700 | | - if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg |
---|
| 758 | + if (unlikely(GET_SIT_VBLOCKS(raw_sit) > usable_blks_per_seg |
---|
701 | 759 | || segno > TOTAL_SEGS(sbi) - 1)) { |
---|
702 | 760 | f2fs_err(sbi, "Wrong valid blocks %d or segno %u", |
---|
703 | 761 | GET_SIT_VBLOCKS(raw_sit), segno); |
---|