From c40a59df7f03f6f391ede703cfda459b58050f90 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 2 Jun 2025 09:36:09 -0700 Subject: [PATCH] ANDROID: Avoid ABI Breakage function symbol 'int __traceiter_f2fs_submit_folio_write(void*, struct folio*, struct f2fs_io_info*)' changed CRC changed from 0x3f6478e5 to 0xdf0f2fbe type 'struct f2fs_sb_info' changed member 'unsigned int first_zoned_segno' was removed member 'unsigned int first_seq_zone_segno' was added type 'struct sec_entry' changed byte size changed from 4 to 8 member 'unsigned int ckpt_valid_blocks' was added Bug: 407985454 Change-Id: I09f5c72c87301e6c833d59b57cc44ec9596e9c23 Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 2 +- fs/f2fs/segment.c | 27 +++++++++++++++++++++------ fs/f2fs/segment.h | 35 +++++++++++++++++++++++++++++++---- fs/f2fs/super.c | 2 +- 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 069100e011e6..cdeea4a731b3 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1782,7 +1782,7 @@ struct f2fs_sb_info { unsigned int dirty_device; /* for checkpoint data flush */ spinlock_t dev_lock; /* protect dirty_device */ bool aligned_blksize; /* all devices has the same logical blksize */ - unsigned int first_seq_zone_segno; /* first segno in sequential zone */ + unsigned int first_zoned_segno; /* first segno in sequential zone */ /* For write statistics */ u64 sectors_written_start; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index e49df84bceac..ce49e6910397 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2492,7 +2492,8 @@ static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_ent if (!f2fs_test_bit(offset + i, se->ckpt_valid_map)) { se->ckpt_valid_blocks -= 1; if (__is_large_section(sbi)) - get_sec_entry(sbi, segno)->ckpt_valid_blocks -= 1; + android_get_sec_entry(sbi, segno)-> + ckpt_valid_blocks -= 1; } } @@ -2539,14 +2540,16 @@ static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry if (!f2fs_test_and_set_bit(offset, se->ckpt_valid_map)) { se->ckpt_valid_blocks++; if (__is_large_section(sbi)) - get_sec_entry(sbi, segno)->ckpt_valid_blocks++; + android_get_sec_entry(sbi, segno)-> + ckpt_valid_blocks++; } } if (!f2fs_test_bit(offset, se->ckpt_valid_map)) { se->ckpt_valid_blocks += del; if (__is_large_section(sbi)) - get_sec_entry(sbi, segno)->ckpt_valid_blocks += del; + android_get_sec_entry(sbi, segno)-> + ckpt_valid_blocks += del; } if (__is_large_section(sbi)) @@ -2798,7 +2801,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_PRIOR_CONV || pinning) segno = 0; else - segno = max(sbi->first_seq_zone_segno, *newseg); + segno = max(sbi->first_zoned_segno, *newseg); hint = GET_SEC_FROM_SEG(sbi, segno); } #endif @@ -2810,7 +2813,7 @@ find_other_zone: if (secno >= MAIN_SECS(sbi) && f2fs_sb_has_blkzoned(sbi)) { /* Write only to sequential zones */ if (sbi->blkzone_alloc_policy == BLKZONE_ALLOC_ONLY_SEQ) { - hint = GET_SEC_FROM_SEG(sbi, sbi->first_seq_zone_segno); + hint = GET_SEC_FROM_SEG(sbi, sbi->first_zoned_segno); secno = find_next_zero_bit(free_i->free_secmap, MAIN_SECS(sbi), hint); } else secno = find_first_zero_bit(free_i->free_secmap, @@ -3336,7 +3339,7 @@ retry: if (f2fs_sb_has_blkzoned(sbi) && err == -EAGAIN && gc_required) { f2fs_down_write(&sbi->gc_lock); - err = f2fs_gc_range(sbi, 0, sbi->first_seq_zone_segno - 1, + err = f2fs_gc_range(sbi, 0, sbi->first_zoned_segno - 1, true, ZONED_PIN_SEC_REQUIRED_COUNT); f2fs_up_write(&sbi->gc_lock); @@ -4826,6 +4829,14 @@ static int build_sit_info(struct f2fs_sb_info *sbi) GFP_KERNEL); if (!sit_i->sec_entries) return -ENOMEM; + + f2fs_bug_on(sbi, android_sec_entries); + android_sec_entries = + f2fs_kvzalloc(sbi, array_size(sizeof(struct android_sec_entry), + MAIN_SECS(sbi)), + GFP_KERNEL); + if (!android_sec_entries) + return -ENOMEM; } /* get information related with SIT */ @@ -5800,6 +5811,10 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) kfree(sit_i->tmp_map); kvfree(sit_i->sentries); + if (__is_large_section(sbi)) { + kvfree(android_sec_entries); + android_sec_entries = NULL; + } kvfree(sit_i->sec_entries); kvfree(sit_i->dirty_sentries_bitmap); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 239291dbae3e..459f34e77fa9 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -211,6 +211,15 @@ struct seg_entry { struct sec_entry { unsigned int valid_blocks; /* # of valid blocks in a section */ +}; + +/* + * This is supposed to be in the above struct sec_entry from the below + * patch merged in 6.16-rc1, but applied to avoid ABI breakages in Android. + * + * deecd282bc39 "f2fs: add ckpt_valid_blocks to the section entry" in 6.16+ + */ +struct android_sec_entry { unsigned int ckpt_valid_blocks; /* # of valid blocks last cp in a section */ }; @@ -332,6 +341,22 @@ static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi, return &sit_i->sec_entries[GET_SEC_FROM_SEG(sbi, segno)]; } +/* + * This is shared with all other mounts, but ensure only /data will + * get memory allocated when a large section is defined. + * Note, the below android_* are only applied to android16-6.12, since + * the orignal patch [1] adds ckpt_valid_blocks in struct sec_entry, + * which breaks ABI. + * + * [1] deecd282bc39 "f2fs: add ckpt_valid_blocks to the section entry" in 6.16+ + */ +static struct android_sec_entry *android_sec_entries = NULL; +static inline struct android_sec_entry *android_get_sec_entry( + struct f2fs_sb_info *sbi, unsigned int segno) +{ + return &android_sec_entries[GET_SEC_FROM_SEG(sbi, segno)]; +} + static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, unsigned int segno, bool use_section) { @@ -349,7 +374,7 @@ static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi, unsigned int segno, bool use_section) { if (use_section && __is_large_section(sbi)) - return get_sec_entry(sbi, segno)->ckpt_valid_blocks; + return android_get_sec_entry(sbi, segno)->ckpt_valid_blocks; else return get_seg_entry(sbi, segno)->ckpt_valid_blocks; } @@ -367,7 +392,7 @@ static inline void set_ckpt_valid_blocks(struct f2fs_sb_info *sbi, blocks += se->ckpt_valid_blocks; } - get_sec_entry(sbi, segno)->ckpt_valid_blocks = blocks; + android_get_sec_entry(sbi, segno)->ckpt_valid_blocks = blocks; } #ifdef CONFIG_F2FS_CHECK_FS @@ -385,11 +410,13 @@ static inline void sanity_check_valid_blocks(struct f2fs_sb_info *sbi, blocks += se->ckpt_valid_blocks; } - if (blocks != get_sec_entry(sbi, segno)->ckpt_valid_blocks) { + if (blocks != android_get_sec_entry(sbi, segno)->ckpt_valid_blocks) { f2fs_err(sbi, "Inconsistent ckpt valid blocks: " "seg entry(%d) vs sec entry(%d) at secno %d", - blocks, get_sec_entry(sbi, segno)->ckpt_valid_blocks, secno); + blocks, + android_get_sec_entry(sbi, segno)->ckpt_valid_blocks, + secno); f2fs_bug_on(sbi, 1); } } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 2940c22bc173..9e3ebc24ba42 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4778,7 +4778,7 @@ try_onemore: sbi->sectors_written_start = f2fs_get_sectors_written(sbi); /* get segno of first zoned block device */ - sbi->first_seq_zone_segno = get_first_seq_zone_segno(sbi); + sbi->first_zoned_segno = get_first_seq_zone_segno(sbi); /* Read accumulated write IO statistics if exists */ seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);