Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

f2fs: support non-4KB block size without packed_ssa feature

Currently, F2FS requires the packed_ssa feature to be enabled when
utilizing non-4KB block sizes (e.g., 16KB). This restriction limits
the flexibility of filesystem formatting options.

This patch allows F2FS to support non-4KB block sizes even when the
packed_ssa feature is disabled. It adjusts the SSA calculation logic to
correctly handle summary entries in larger blocks without the packed
layout.

Cc: stable@kernel.org
Fixes: 7ee8bc3942f2 ("f2fs: revert summary entry count from 2048 to 512 in 16kb block support")
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Daeho Jeong and committed by
Jaegeuk Kim
e48e16f3 1dd3b437

+165 -122
+37 -15
fs/f2fs/f2fs.h
··· 545 545 #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats)) 546 546 #define sits_in_cursum(jnl) (le16_to_cpu((jnl)->n_sits)) 547 547 548 - #define nat_in_journal(jnl, i) ((jnl)->nat_j.entries[i].ne) 549 - #define nid_in_journal(jnl, i) ((jnl)->nat_j.entries[i].nid) 550 - #define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se) 551 - #define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno) 548 + #define nat_in_journal(jnl, i) \ 549 + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].ne) 550 + #define nid_in_journal(jnl, i) \ 551 + (((struct nat_journal_entry *)(jnl)->nat_j.entries)[i].nid) 552 + #define sit_in_journal(jnl, i) \ 553 + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].se) 554 + #define segno_in_journal(jnl, i) \ 555 + (((struct sit_journal_entry *)(jnl)->sit_j.entries)[i].segno) 552 556 553 - #define MAX_NAT_JENTRIES(jnl) (NAT_JOURNAL_ENTRIES - nats_in_cursum(jnl)) 554 - #define MAX_SIT_JENTRIES(jnl) (SIT_JOURNAL_ENTRIES - sits_in_cursum(jnl)) 557 + #define sum_entries(sum) ((struct f2fs_summary *)(sum)) 558 + #define sum_journal(sbi, sum) \ 559 + ((struct f2fs_journal *)((char *)(sum) + \ 560 + ((sbi)->entries_in_sum * sizeof(struct f2fs_summary)))) 561 + #define sum_footer(sbi, sum) \ 562 + ((struct summary_footer *)((char *)(sum) + (sbi)->sum_blocksize - \ 563 + sizeof(struct summary_footer))) 564 + 565 + #define MAX_NAT_JENTRIES(sbi, jnl) ((sbi)->nat_journal_entries - nats_in_cursum(jnl)) 566 + #define MAX_SIT_JENTRIES(sbi, jnl) ((sbi)->sit_journal_entries - sits_in_cursum(jnl)) 555 567 556 568 static inline int update_nats_in_cursum(struct f2fs_journal *journal, int i) 557 569 { ··· 579 567 580 568 journal->n_sits = cpu_to_le16(before + i); 581 569 return before; 582 - } 583 - 584 - static inline bool __has_cursum_space(struct f2fs_journal *journal, 585 - int size, int type) 586 - { 587 - if (type == NAT_JOURNAL) 588 - return size <= MAX_NAT_JENTRIES(journal); 589 - return size <= MAX_SIT_JENTRIES(journal); 590 570 } 591 571 592 572 /* for inline stuff */ ··· 1813 1809 bool readdir_ra; /* readahead inode in readdir */ 1814 1810 unsigned int max_io_bytes; /* max io bytes to merge IOs */ 1815 1811 1812 + /* variable summary block units */ 1813 + unsigned int sum_blocksize; /* sum block size */ 1814 + unsigned int sums_per_block; /* sum block count per block */ 1815 + unsigned int entries_in_sum; /* entry count in sum block */ 1816 + unsigned int sum_entry_size; /* total entry size in sum block */ 1817 + unsigned int sum_journal_size; /* journal size in sum block */ 1818 + unsigned int nat_journal_entries; /* nat journal entry count in the journal */ 1819 + unsigned int sit_journal_entries; /* sit journal entry count in the journal */ 1820 + 1816 1821 block_t user_block_count; /* # of user blocks */ 1817 1822 block_t total_valid_block_count; /* # of valid blocks */ 1818 1823 block_t discard_blks; /* discard command candidats */ ··· 2861 2848 static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi) 2862 2849 { 2863 2850 return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); 2851 + } 2852 + 2853 + static inline bool __has_cursum_space(struct f2fs_sb_info *sbi, 2854 + struct f2fs_journal *journal, int size, int type) 2855 + { 2856 + if (type == NAT_JOURNAL) 2857 + return size <= MAX_NAT_JENTRIES(sbi, journal); 2858 + return size <= MAX_SIT_JENTRIES(sbi, journal); 2864 2859 } 2865 2860 2866 2861 extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync); ··· 4014 3993 block_t len); 4015 3994 void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk); 4016 3995 void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk); 4017 - int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type, 3996 + int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi, 3997 + struct f2fs_journal *journal, int type, 4018 3998 unsigned int val, int alloc); 4019 3999 void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); 4020 4000 int f2fs_check_and_fix_write_pointer(struct f2fs_sb_info *sbi);
+12 -11
fs/f2fs/gc.c
··· 1782 1782 1783 1783 sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); 1784 1784 1785 - segno = rounddown(segno, SUMS_PER_BLOCK); 1786 - sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK); 1785 + segno = rounddown(segno, sbi->sums_per_block); 1786 + sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, sbi->sums_per_block); 1787 1787 /* readahead multi ssa blocks those have contiguous address */ 1788 1788 if (__is_large_section(sbi)) 1789 1789 f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), ··· 1793 1793 while (segno < end_segno) { 1794 1794 struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno); 1795 1795 1796 - segno += SUMS_PER_BLOCK; 1796 + segno += sbi->sums_per_block; 1797 1797 if (IS_ERR(sum_folio)) { 1798 1798 int err = PTR_ERR(sum_folio); 1799 1799 1800 - end_segno = segno - SUMS_PER_BLOCK; 1801 - segno = rounddown(start_segno, SUMS_PER_BLOCK); 1800 + end_segno = segno - sbi->sums_per_block; 1801 + segno = rounddown(start_segno, sbi->sums_per_block); 1802 1802 while (segno < end_segno) { 1803 1803 sum_folio = filemap_get_folio(META_MAPPING(sbi), 1804 1804 GET_SUM_BLOCK(sbi, segno)); 1805 1805 folio_put_refs(sum_folio, 2); 1806 - segno += SUMS_PER_BLOCK; 1806 + segno += sbi->sums_per_block; 1807 1807 } 1808 1808 return err; 1809 1809 } ··· 1819 1819 /* find segment summary of victim */ 1820 1820 struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi), 1821 1821 GET_SUM_BLOCK(sbi, segno)); 1822 - unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK) 1823 - + SUMS_PER_BLOCK; 1822 + unsigned int block_end_segno = rounddown(segno, sbi->sums_per_block) 1823 + + sbi->sums_per_block; 1824 1824 1825 1825 if (block_end_segno > end_segno) 1826 1826 block_end_segno = end_segno; ··· 1846 1846 migrated >= sbi->migration_granularity) 1847 1847 continue; 1848 1848 1849 - sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno); 1850 - if (type != GET_SUM_TYPE((&sum->footer))) { 1849 + sum = SUM_BLK_PAGE_ADDR(sbi, sum_folio, cur_segno); 1850 + if (type != GET_SUM_TYPE(sum_footer(sbi, sum))) { 1851 1851 f2fs_err(sbi, "Inconsistent segment (%u) type " 1852 1852 "[%d, %d] in SSA and SIT", 1853 1853 cur_segno, type, 1854 - GET_SUM_TYPE((&sum->footer))); 1854 + GET_SUM_TYPE( 1855 + sum_footer(sbi, sum))); 1855 1856 f2fs_stop_checkpoint(sbi, false, 1856 1857 STOP_CP_REASON_CORRUPTED_SUMMARY); 1857 1858 continue;
+6 -6
fs/f2fs/node.c
··· 606 606 goto retry; 607 607 } 608 608 609 - i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0); 609 + i = f2fs_lookup_journal_in_cursum(sbi, journal, NAT_JOURNAL, nid, 0); 610 610 if (i >= 0) { 611 611 ne = nat_in_journal(journal, i); 612 612 node_info_from_raw_nat(ni, &ne); ··· 2955 2955 /* scan the node segment */ 2956 2956 last_offset = BLKS_PER_SEG(sbi); 2957 2957 addr = START_BLOCK(sbi, segno); 2958 - sum_entry = &sum->entries[0]; 2958 + sum_entry = sum_entries(sum); 2959 2959 2960 2960 for (i = 0; i < last_offset; i += nrpages, addr += nrpages) { 2961 2961 nrpages = bio_max_segs(last_offset - i); ··· 3096 3096 * #2, flush nat entries to nat page. 3097 3097 */ 3098 3098 if (enabled_nat_bits(sbi, cpc) || 3099 - !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) 3099 + !__has_cursum_space(sbi, journal, set->entry_cnt, NAT_JOURNAL)) 3100 3100 to_journal = false; 3101 3101 3102 3102 if (to_journal) { ··· 3119 3119 f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR); 3120 3120 3121 3121 if (to_journal) { 3122 - offset = f2fs_lookup_journal_in_cursum(journal, 3122 + offset = f2fs_lookup_journal_in_cursum(sbi, journal, 3123 3123 NAT_JOURNAL, nid, 1); 3124 3124 f2fs_bug_on(sbi, offset < 0); 3125 3125 raw_ne = &nat_in_journal(journal, offset); ··· 3190 3190 * into nat entry set. 3191 3191 */ 3192 3192 if (enabled_nat_bits(sbi, cpc) || 3193 - !__has_cursum_space(journal, 3193 + !__has_cursum_space(sbi, journal, 3194 3194 nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) 3195 3195 remove_nats_in_journal(sbi); 3196 3196 ··· 3201 3201 set_idx = setvec[found - 1]->set + 1; 3202 3202 for (idx = 0; idx < found; idx++) 3203 3203 __adjust_nat_entry_set(setvec[idx], &sets, 3204 - MAX_NAT_JENTRIES(journal)); 3204 + MAX_NAT_JENTRIES(sbi, journal)); 3205 3205 } 3206 3206 3207 3207 /* flush dirty nats in nat entry set */
+3 -3
fs/f2fs/recovery.c
··· 514 514 struct curseg_info *curseg = CURSEG_I(sbi, i); 515 515 516 516 if (curseg->segno == segno) { 517 - sum = curseg->sum_blk->entries[blkoff]; 517 + sum = sum_entries(curseg->sum_blk)[blkoff]; 518 518 goto got_it; 519 519 } 520 520 } ··· 522 522 sum_folio = f2fs_get_sum_folio(sbi, segno); 523 523 if (IS_ERR(sum_folio)) 524 524 return PTR_ERR(sum_folio); 525 - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno); 526 - sum = sum_node->entries[blkoff]; 525 + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, segno); 526 + sum = sum_entries(sum_node)[blkoff]; 527 527 f2fs_folio_put(sum_folio, true); 528 528 got_it: 529 529 /* Use the locked dnode page and inode */
+46 -40
fs/f2fs/segment.c
··· 2674 2674 valid_sum_count += f2fs_curseg_valid_blocks(sbi, i); 2675 2675 } 2676 2676 2677 - sum_in_page = (PAGE_SIZE - 2 * SUM_JOURNAL_SIZE - 2677 + sum_in_page = (sbi->sum_blocksize - 2 * sbi->sum_journal_size - 2678 2678 SUM_FOOTER_SIZE) / SUMMARY_SIZE; 2679 2679 if (valid_sum_count <= sum_in_page) 2680 2680 return 1; 2681 2681 else if ((valid_sum_count - sum_in_page) <= 2682 - (PAGE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE) 2682 + (sbi->sum_blocksize - SUM_FOOTER_SIZE) / SUMMARY_SIZE) 2683 2683 return 2; 2684 2684 return 3; 2685 2685 } ··· 2699 2699 { 2700 2700 struct folio *folio; 2701 2701 2702 - if (SUMS_PER_BLOCK == 1) 2702 + if (!f2fs_sb_has_packed_ssa(sbi)) 2703 2703 folio = f2fs_grab_meta_folio(sbi, blk_addr); 2704 2704 else 2705 2705 folio = f2fs_get_meta_folio_retry(sbi, blk_addr); ··· 2717 2717 { 2718 2718 struct folio *folio; 2719 2719 2720 - if (SUMS_PER_BLOCK == 1) 2720 + if (!f2fs_sb_has_packed_ssa(sbi)) 2721 2721 return f2fs_update_meta_page(sbi, (void *)sum_blk, 2722 2722 GET_SUM_BLOCK(sbi, segno)); 2723 2723 ··· 2725 2725 if (IS_ERR(folio)) 2726 2726 return; 2727 2727 2728 - memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk)); 2728 + memcpy(SUM_BLK_PAGE_ADDR(sbi, folio, segno), sum_blk, 2729 + sbi->sum_blocksize); 2729 2730 folio_mark_dirty(folio); 2730 2731 f2fs_folio_put(folio, true); 2731 2732 } ··· 2745 2744 mutex_lock(&curseg->curseg_mutex); 2746 2745 2747 2746 down_read(&curseg->journal_rwsem); 2748 - memcpy(&dst->journal, curseg->journal, SUM_JOURNAL_SIZE); 2747 + memcpy(sum_journal(sbi, dst), curseg->journal, sbi->sum_journal_size); 2749 2748 up_read(&curseg->journal_rwsem); 2750 2749 2751 - memcpy(dst->entries, src->entries, SUM_ENTRY_SIZE); 2752 - memcpy(&dst->footer, &src->footer, SUM_FOOTER_SIZE); 2750 + memcpy(sum_entries(dst), sum_entries(src), sbi->sum_entry_size); 2751 + memcpy(sum_footer(sbi, dst), sum_footer(sbi, src), SUM_FOOTER_SIZE); 2753 2752 2754 2753 mutex_unlock(&curseg->curseg_mutex); 2755 2754 ··· 2922 2921 curseg->next_blkoff = 0; 2923 2922 curseg->next_segno = NULL_SEGNO; 2924 2923 2925 - sum_footer = &(curseg->sum_blk->footer); 2924 + sum_footer = sum_footer(sbi, curseg->sum_blk); 2926 2925 memset(sum_footer, 0, sizeof(struct summary_footer)); 2927 2926 2928 2927 sanity_check_seg_type(sbi, seg_type); ··· 3068 3067 sum_folio = f2fs_get_sum_folio(sbi, new_segno); 3069 3068 if (IS_ERR(sum_folio)) { 3070 3069 /* GC won't be able to use stale summary pages by cp_error */ 3071 - memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE); 3070 + memset(curseg->sum_blk, 0, sbi->sum_entry_size); 3072 3071 return PTR_ERR(sum_folio); 3073 3072 } 3074 - sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno); 3075 - memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); 3073 + sum_node = SUM_BLK_PAGE_ADDR(sbi, sum_folio, new_segno); 3074 + memcpy(curseg->sum_blk, sum_node, sbi->sum_entry_size); 3076 3075 f2fs_folio_put(sum_folio, true); 3077 3076 return 0; 3078 3077 } ··· 3806 3805 3807 3806 f2fs_wait_discard_bio(sbi, *new_blkaddr); 3808 3807 3809 - curseg->sum_blk->entries[curseg->next_blkoff] = *sum; 3808 + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum; 3810 3809 if (curseg->alloc_type == SSR) { 3811 3810 curseg->next_blkoff = f2fs_find_next_ssr_block(sbi, curseg); 3812 3811 } else { ··· 4175 4174 } 4176 4175 4177 4176 curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr); 4178 - curseg->sum_blk->entries[curseg->next_blkoff] = *sum; 4177 + sum_entries(curseg->sum_blk)[curseg->next_blkoff] = *sum; 4179 4178 4180 4179 if (!recover_curseg || recover_newaddr) { 4181 4180 if (!from_gc) ··· 4295 4294 4296 4295 /* Step 1: restore nat cache */ 4297 4296 seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); 4298 - memcpy(seg_i->journal, kaddr, SUM_JOURNAL_SIZE); 4297 + memcpy(seg_i->journal, kaddr, sbi->sum_journal_size); 4299 4298 4300 4299 /* Step 2: restore sit cache */ 4301 4300 seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); 4302 - memcpy(seg_i->journal, kaddr + SUM_JOURNAL_SIZE, SUM_JOURNAL_SIZE); 4303 - offset = 2 * SUM_JOURNAL_SIZE; 4301 + memcpy(seg_i->journal, kaddr + sbi->sum_journal_size, sbi->sum_journal_size); 4302 + offset = 2 * sbi->sum_journal_size; 4304 4303 4305 4304 /* Step 3: restore summary entries */ 4306 4305 for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { ··· 4322 4321 struct f2fs_summary *s; 4323 4322 4324 4323 s = (struct f2fs_summary *)(kaddr + offset); 4325 - seg_i->sum_blk->entries[j] = *s; 4324 + sum_entries(seg_i->sum_blk)[j] = *s; 4326 4325 offset += SUMMARY_SIZE; 4327 - if (offset + SUMMARY_SIZE <= PAGE_SIZE - 4326 + if (offset + SUMMARY_SIZE <= sbi->sum_blocksize - 4328 4327 SUM_FOOTER_SIZE) 4329 4328 continue; 4330 4329 ··· 4380 4379 4381 4380 if (IS_NODESEG(type)) { 4382 4381 if (__exist_node_summaries(sbi)) { 4383 - struct f2fs_summary *ns = &sum->entries[0]; 4382 + struct f2fs_summary *ns = sum_entries(sum); 4384 4383 int i; 4385 4384 4386 4385 for (i = 0; i < BLKS_PER_SEG(sbi); i++, ns++) { ··· 4400 4399 4401 4400 /* update journal info */ 4402 4401 down_write(&curseg->journal_rwsem); 4403 - memcpy(curseg->journal, &sum->journal, SUM_JOURNAL_SIZE); 4402 + memcpy(curseg->journal, sum_journal(sbi, sum), sbi->sum_journal_size); 4404 4403 up_write(&curseg->journal_rwsem); 4405 4404 4406 - memcpy(curseg->sum_blk->entries, sum->entries, SUM_ENTRY_SIZE); 4407 - memcpy(&curseg->sum_blk->footer, &sum->footer, SUM_FOOTER_SIZE); 4405 + memcpy(sum_entries(curseg->sum_blk), sum_entries(sum), 4406 + sbi->sum_entry_size); 4407 + memcpy(sum_footer(sbi, curseg->sum_blk), sum_footer(sbi, sum), 4408 + SUM_FOOTER_SIZE); 4408 4409 curseg->next_segno = segno; 4409 4410 reset_curseg(sbi, type, 0); 4410 4411 curseg->alloc_type = ckpt->alloc_type[type]; ··· 4450 4447 } 4451 4448 4452 4449 /* sanity check for summary blocks */ 4453 - if (nats_in_cursum(nat_j) > NAT_JOURNAL_ENTRIES || 4454 - sits_in_cursum(sit_j) > SIT_JOURNAL_ENTRIES) { 4450 + if (nats_in_cursum(nat_j) > sbi->nat_journal_entries || 4451 + sits_in_cursum(sit_j) > sbi->sit_journal_entries) { 4455 4452 f2fs_err(sbi, "invalid journal entries nats %u sits %u", 4456 4453 nats_in_cursum(nat_j), sits_in_cursum(sit_j)); 4457 4454 return -EINVAL; ··· 4475 4472 4476 4473 /* Step 1: write nat cache */ 4477 4474 seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); 4478 - memcpy(kaddr, seg_i->journal, SUM_JOURNAL_SIZE); 4479 - written_size += SUM_JOURNAL_SIZE; 4475 + memcpy(kaddr, seg_i->journal, sbi->sum_journal_size); 4476 + written_size += sbi->sum_journal_size; 4480 4477 4481 4478 /* Step 2: write sit cache */ 4482 4479 seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); 4483 - memcpy(kaddr + written_size, seg_i->journal, SUM_JOURNAL_SIZE); 4484 - written_size += SUM_JOURNAL_SIZE; 4480 + memcpy(kaddr + written_size, seg_i->journal, sbi->sum_journal_size); 4481 + written_size += sbi->sum_journal_size; 4485 4482 4486 4483 /* Step 3: write summary entries */ 4487 4484 for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { ··· 4494 4491 written_size = 0; 4495 4492 } 4496 4493 summary = (struct f2fs_summary *)(kaddr + written_size); 4497 - *summary = seg_i->sum_blk->entries[j]; 4494 + *summary = sum_entries(seg_i->sum_blk)[j]; 4498 4495 written_size += SUMMARY_SIZE; 4499 4496 4500 4497 if (written_size + SUMMARY_SIZE <= PAGE_SIZE - ··· 4539 4536 write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); 4540 4537 } 4541 4538 4542 - int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type, 4543 - unsigned int val, int alloc) 4539 + int f2fs_lookup_journal_in_cursum(struct f2fs_sb_info *sbi, 4540 + struct f2fs_journal *journal, int type, 4541 + unsigned int val, int alloc) 4544 4542 { 4545 4543 int i; 4546 4544 ··· 4550 4546 if (le32_to_cpu(nid_in_journal(journal, i)) == val) 4551 4547 return i; 4552 4548 } 4553 - if (alloc && __has_cursum_space(journal, 1, NAT_JOURNAL)) 4549 + if (alloc && __has_cursum_space(sbi, journal, 1, NAT_JOURNAL)) 4554 4550 return update_nats_in_cursum(journal, 1); 4555 4551 } else if (type == SIT_JOURNAL) { 4556 4552 for (i = 0; i < sits_in_cursum(journal); i++) 4557 4553 if (le32_to_cpu(segno_in_journal(journal, i)) == val) 4558 4554 return i; 4559 - if (alloc && __has_cursum_space(journal, 1, SIT_JOURNAL)) 4555 + if (alloc && __has_cursum_space(sbi, journal, 1, SIT_JOURNAL)) 4560 4556 return update_sits_in_cursum(journal, 1); 4561 4557 } 4562 4558 return -1; ··· 4704 4700 * entries, remove all entries from journal and add and account 4705 4701 * them in sit entry set. 4706 4702 */ 4707 - if (!__has_cursum_space(journal, sit_i->dirty_sentries, SIT_JOURNAL) || 4708 - !to_journal) 4703 + if (!__has_cursum_space(sbi, journal, 4704 + sit_i->dirty_sentries, SIT_JOURNAL) || !to_journal) 4709 4705 remove_sits_in_journal(sbi); 4710 4706 4711 4707 /* ··· 4722 4718 unsigned int segno = start_segno; 4723 4719 4724 4720 if (to_journal && 4725 - !__has_cursum_space(journal, ses->entry_cnt, SIT_JOURNAL)) 4721 + !__has_cursum_space(sbi, journal, ses->entry_cnt, 4722 + SIT_JOURNAL)) 4726 4723 to_journal = false; 4727 4724 4728 4725 if (to_journal) { ··· 4751 4746 } 4752 4747 4753 4748 if (to_journal) { 4754 - offset = f2fs_lookup_journal_in_cursum(journal, 4749 + offset = f2fs_lookup_journal_in_cursum(sbi, journal, 4755 4750 SIT_JOURNAL, segno, 1); 4756 4751 f2fs_bug_on(sbi, offset < 0); 4757 4752 segno_in_journal(journal, offset) = ··· 4958 4953 4959 4954 for (i = 0; i < NO_CHECK_TYPE; i++) { 4960 4955 mutex_init(&array[i].curseg_mutex); 4961 - array[i].sum_blk = f2fs_kzalloc(sbi, PAGE_SIZE, GFP_KERNEL); 4956 + array[i].sum_blk = f2fs_kzalloc(sbi, sbi->sum_blocksize, 4957 + GFP_KERNEL); 4962 4958 if (!array[i].sum_blk) 4963 4959 return -ENOMEM; 4964 4960 init_rwsem(&array[i].journal_rwsem); 4965 4961 array[i].journal = f2fs_kzalloc(sbi, 4966 - sizeof(struct f2fs_journal), GFP_KERNEL); 4962 + sbi->sum_journal_size, GFP_KERNEL); 4967 4963 if (!array[i].journal) 4968 4964 return -ENOMEM; 4969 4965 array[i].seg_type = log_type_to_seg_type(i);
+4 -5
fs/f2fs/segment.h
··· 90 90 #define GET_ZONE_FROM_SEG(sbi, segno) \ 91 91 GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) 92 92 93 - #define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE) 94 93 #define GET_SUM_BLOCK(sbi, segno) \ 95 - (SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK)) 96 - #define GET_SUM_BLKOFF(segno) (segno % SUMS_PER_BLOCK) 97 - #define SUM_BLK_PAGE_ADDR(folio, segno) \ 98 - (folio_address(folio) + GET_SUM_BLKOFF(segno) * F2FS_SUM_BLKSIZE) 94 + (SM_I(sbi)->ssa_blkaddr + (segno / (sbi)->sums_per_block)) 95 + #define GET_SUM_BLKOFF(sbi, segno) (segno % (sbi)->sums_per_block) 96 + #define SUM_BLK_PAGE_ADDR(sbi, folio, segno) \ 97 + (folio_address(folio) + GET_SUM_BLKOFF(sbi, segno) * (sbi)->sum_blocksize) 99 98 100 99 #define GET_SUM_TYPE(footer) ((footer)->entry_type) 101 100 #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
+12 -14
fs/f2fs/super.c
··· 4104 4104 if (sanity_check_area_boundary(sbi, folio, index)) 4105 4105 return -EFSCORRUPTED; 4106 4106 4107 - /* 4108 - * Check for legacy summary layout on 16KB+ block devices. 4109 - * Modern f2fs-tools packs multiple 4KB summary areas into one block, 4110 - * whereas legacy versions used one block per summary, leading 4111 - * to a much larger SSA. 4112 - */ 4113 - if (SUMS_PER_BLOCK > 1 && 4114 - !(__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_PACKED_SSA))) { 4115 - f2fs_info(sbi, "Error: Device formatted with a legacy version. " 4116 - "Please reformat with a tool supporting the packed ssa " 4117 - "feature for block sizes larger than 4kb."); 4118 - return -EOPNOTSUPP; 4119 - } 4120 - 4121 4107 return 0; 4122 4108 } 4123 4109 ··· 4314 4328 spin_lock_init(&sbi->gc_remaining_trials_lock); 4315 4329 atomic64_set(&sbi->current_atomic_write, 0); 4316 4330 sbi->max_lock_elapsed_time = MAX_LOCK_ELAPSED_TIME; 4331 + 4332 + sbi->sum_blocksize = f2fs_sb_has_packed_ssa(sbi) ? 4333 + 4096 : sbi->blocksize; 4334 + sbi->sums_per_block = sbi->blocksize / sbi->sum_blocksize; 4335 + sbi->entries_in_sum = sbi->sum_blocksize / 8; 4336 + sbi->sum_entry_size = SUMMARY_SIZE * sbi->entries_in_sum; 4337 + sbi->sum_journal_size = sbi->sum_blocksize - SUM_FOOTER_SIZE - 4338 + sbi->sum_entry_size; 4339 + sbi->nat_journal_entries = (sbi->sum_journal_size - 2) / 4340 + sizeof(struct nat_journal_entry); 4341 + sbi->sit_journal_entries = (sbi->sum_journal_size - 2) / 4342 + sizeof(struct sit_journal_entry); 4317 4343 4318 4344 sbi->dir_level = DEF_DIR_LEVEL; 4319 4345 sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
+45 -28
include/linux/f2fs_fs.h
··· 17 17 #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ 18 18 #define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */ 19 19 #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ 20 - #define F2FS_SUM_BLKSIZE 4096 /* only support 4096 byte sum block */ 21 20 #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ 22 21 #define F2FS_EXTENSION_LEN 8 /* max size of extension */ 23 22 ··· 441 442 * from node's page's beginning to get a data block address. 442 443 * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node) 443 444 */ 444 - #define ENTRIES_IN_SUM (F2FS_SUM_BLKSIZE / 8) 445 445 #define SUMMARY_SIZE (7) /* sizeof(struct f2fs_summary) */ 446 446 #define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ 447 - #define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) 448 447 449 448 /* a summary entry for a block in a segment */ 450 449 struct f2fs_summary { ··· 465 468 __le32 check_sum; /* summary checksum */ 466 469 } __packed; 467 470 468 - #define SUM_JOURNAL_SIZE (F2FS_SUM_BLKSIZE - SUM_FOOTER_SIZE -\ 469 - SUM_ENTRY_SIZE) 470 - #define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ 471 - sizeof(struct nat_journal_entry)) 472 - #define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\ 473 - sizeof(struct nat_journal_entry)) 474 - #define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ 475 - sizeof(struct sit_journal_entry)) 476 - #define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\ 477 - sizeof(struct sit_journal_entry)) 478 - 479 - /* Reserved area should make size of f2fs_extra_info equals to 480 - * that of nat_journal and sit_journal. 481 - */ 482 - #define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8) 483 - 484 471 /* 485 472 * frequently updated NAT/SIT entries can be stored in the spare area in 486 473 * summary blocks ··· 479 498 struct f2fs_nat_entry ne; 480 499 } __packed; 481 500 501 + /* 502 + * The nat_journal structure is a placeholder whose actual size varies depending 503 + * on the use of packed_ssa. Therefore, it must always be accessed only through 504 + * specific sets of macros and fields, and size calculations should use 505 + * size-related macros instead of sizeof(). 506 + * Relevant macros: sbi->nat_journal_entries, nat_in_journal(), 507 + * nid_in_journal(), MAX_NAT_JENTRIES(). 508 + */ 482 509 struct nat_journal { 483 - struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES]; 484 - __u8 reserved[NAT_JOURNAL_RESERVED]; 510 + struct nat_journal_entry entries[0]; 485 511 } __packed; 486 512 487 513 struct sit_journal_entry { ··· 496 508 struct f2fs_sit_entry se; 497 509 } __packed; 498 510 511 + /* 512 + * The sit_journal structure is a placeholder whose actual size varies depending 513 + * on the use of packed_ssa. Therefore, it must always be accessed only through 514 + * specific sets of macros and fields, and size calculations should use 515 + * size-related macros instead of sizeof(). 516 + * Relevant macros: sbi->sit_journal_entries, sit_in_journal(), 517 + * segno_in_journal(), MAX_SIT_JENTRIES(). 518 + */ 499 519 struct sit_journal { 500 - struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES]; 501 - __u8 reserved[SIT_JOURNAL_RESERVED]; 520 + struct sit_journal_entry entries[0]; 502 521 } __packed; 503 522 504 523 struct f2fs_extra_info { 505 524 __le64 kbytes_written; 506 - __u8 reserved[EXTRA_INFO_RESERVED]; 525 + __u8 reserved[]; 507 526 } __packed; 508 527 509 528 struct f2fs_journal { ··· 526 531 }; 527 532 } __packed; 528 533 529 - /* Block-sized summary block structure */ 534 + /* 535 + * Block-sized summary block structure 536 + * 537 + * The f2fs_summary_block structure is a placeholder whose actual size varies 538 + * depending on the use of packed_ssa. Therefore, it must always be accessed 539 + * only through specific sets of macros and fields, and size calculations should 540 + * use size-related macros instead of sizeof(). 541 + * Relevant macros: sbi->sum_blocksize, sbi->entries_in_sum, 542 + * sbi->sum_entry_size, sum_entries(), sum_journal(), sum_footer(). 543 + * 544 + * Summary Block Layout 545 + * 546 + * +-----------------------+ <--- Block Start 547 + * | struct f2fs_summary | 548 + * | entries[0] | 549 + * | ... | 550 + * | entries[N-1] | 551 + * +-----------------------+ 552 + * | struct f2fs_journal | 553 + * +-----------------------+ 554 + * | struct summary_footer | 555 + * +-----------------------+ <--- Block End 556 + */ 530 557 struct f2fs_summary_block { 531 - struct f2fs_summary entries[ENTRIES_IN_SUM]; 532 - struct f2fs_journal journal; 533 - struct summary_footer footer; 558 + struct f2fs_summary entries[0]; 559 + // struct f2fs_journal journal; 560 + // struct summary_footer footer; 534 561 } __packed; 535 562 536 563 /*