diff options
| author | Mark Brown <broonie@kernel.org> | 2026-09-14 11:04:50 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-14 11:04:50 +0100 |
| commit | d72c8fbae9df1a72ffa0ddb65e18432174a4366e (patch) | |
| tree | a59ddafa545c55f251812e4175c6822bf810a2c9 | |
| parent | f537ae92161ed1e51c3fd9f8cda1b4f4670e98a8 (diff) | |
| parent | 6a0dda6838b65609590890bdfe4ffb9c2ab031a1 (diff) | |
| download | linux-next-d72c8fbae9df1a72ffa0ddb65e18432174a4366e.tar.gz linux-next-d72c8fbae9df1a72ffa0ddb65e18432174a4366e.zip | |
Merge branch 'dev' of https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
| -rw-r--r-- | fs/f2fs/checkpoint.c | 77 | ||||
| -rw-r--r-- | fs/f2fs/data.c | 85 | ||||
| -rw-r--r-- | fs/f2fs/debug.c | 4 | ||||
| -rw-r--r-- | fs/f2fs/dir.c | 51 | ||||
| -rw-r--r-- | fs/f2fs/extent_cache.c | 9 | ||||
| -rw-r--r-- | fs/f2fs/f2fs.h | 128 | ||||
| -rw-r--r-- | fs/f2fs/file.c | 85 | ||||
| -rw-r--r-- | fs/f2fs/gc.c | 27 | ||||
| -rw-r--r-- | fs/f2fs/inline.c | 11 | ||||
| -rw-r--r-- | fs/f2fs/inode.c | 25 | ||||
| -rw-r--r-- | fs/f2fs/node.c | 171 | ||||
| -rw-r--r-- | fs/f2fs/node.h | 87 | ||||
| -rw-r--r-- | fs/f2fs/recovery.c | 4 | ||||
| -rw-r--r-- | fs/f2fs/segment.c | 114 | ||||
| -rw-r--r-- | fs/f2fs/segment.h | 32 | ||||
| -rw-r--r-- | fs/f2fs/shrinker.c | 2 | ||||
| -rw-r--r-- | fs/f2fs/super.c | 84 | ||||
| -rw-r--r-- | fs/f2fs/sysfs.c | 10 | ||||
| -rw-r--r-- | fs/f2fs/verity.c | 6 | ||||
| -rw-r--r-- | fs/f2fs/xattr.c | 10 | ||||
| -rw-r--r-- | fs/f2fs/xattr.h | 11 | ||||
| -rw-r--r-- | include/linux/f2fs_fs.h | 135 |
22 files changed, 693 insertions, 475 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4b59f30ef45d..712c4508f38c 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -288,7 +288,7 @@ repeat: return ERR_PTR(err); } - f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, F2FS_BLKSIZE(sbi)); folio_lock(folio); if (unlikely(!is_meta_folio(folio))) { @@ -476,18 +476,18 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, switch (type) { case META_NAT: if (unlikely(blkno >= - NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid))) + NAT_BLOCK_OFFSET(sbi, NM_I(sbi)->max_nid))) blkno = 0; /* get nat block addr */ fio.new_blkaddr = current_nat_addr(sbi, - blkno * NAT_ENTRY_PER_BLOCK); + blkno * NAT_ENTRY_PER_BLOCK(sbi)); break; case META_SIT: if (unlikely(blkno >= TOTAL_SEGS(sbi))) goto out; /* get sit block addr */ fio.new_blkaddr = current_sit_addr(sbi, - blkno * SIT_ENTRY_PER_BLOCK); + blkno * SIT_ENTRY_PER_BLOCK(sbi)); break; case META_SSA: case META_CP: @@ -513,7 +513,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, if (!err) f2fs_update_iostat(sbi, NULL, FS_META_READ_IO, - F2FS_BLKSIZE); + F2FS_BLKSIZE(sbi)); } out: blk_finish_plug(&plug); @@ -825,15 +825,6 @@ static void __clear_ino_bitmap(struct f2fs_sb_info *sbi, nid_t ino, int type) spin_unlock(&im->ino_lock); } -static void f2fs_wait_for_inode_record(struct f2fs_sb_info *sbi, int mode) -{ - if (mode != APPEND_INO && mode != UPDATE_INO) - return; - - /* Let's wait for some pending updates for APPEND_INO and UPDATE_INO. */ - flush_workqueue(sbi->evict_wq); -} - static void __f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, unsigned int devidx, int type) { @@ -887,8 +878,6 @@ void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all) for (i = all ? ORPHAN_INO : FLUSH_INO; i <= FLUSH_INO; i++) { struct inode_management *im = &sbi->im[i]; - f2fs_wait_for_inode_record(sbi, i); - spin_lock(&im->ino_lock); list_for_each_entry_safe(e, tmp, &im->ino_list, list) { list_del(&e->list); @@ -899,6 +888,9 @@ void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all) spin_unlock(&im->ino_lock); } + /* Wait for pending APPEND/UPDATE inode state updates. */ + flush_workqueue(sbi->evict_wq); + for (i = APPEND_INO; i < MAX_INO_ENTRY; i++) { struct inode_management *im = &sbi->im[i]; @@ -1042,6 +1034,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) for (i = 0; i < orphan_blocks; i++) { struct folio *folio; struct f2fs_orphan_block *orphan_blk; + struct f2fs_orphan_footer *footer; unsigned int entry_count; folio = f2fs_get_meta_folio(sbi, start_blk + i); @@ -1051,8 +1044,9 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) } orphan_blk = folio_address(folio); - entry_count = le32_to_cpu(orphan_blk->entry_count); - if (entry_count > F2FS_ORPHANS_PER_BLOCK) { + footer = f2fs_orphan_footer(orphan_blk, sbi); + entry_count = le32_to_cpu(footer->entry_count); + if (entry_count > F2FS_ORPHANS_PER_BLOCK(sbi)) { f2fs_err(sbi, "invalid orphan inode entry count %u", entry_count); set_sbi_flag(sbi, SBI_NEED_FSCK); @@ -1085,6 +1079,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) { struct list_head *head; struct f2fs_orphan_block *orphan_blk = NULL; + struct f2fs_orphan_footer *footer = NULL; unsigned int nentries = 0; unsigned short index = 1; unsigned short orphan_blocks; @@ -1092,7 +1087,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) struct ino_entry *orphan = NULL; struct inode_management *im = &sbi->im[ORPHAN_INO]; - orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num); + orphan_blocks = GET_ORPHAN_BLOCKS(sbi, im->ino_num); /* * we don't need to do spin_lock(&im->ino_lock) here, since all the @@ -1106,20 +1101,21 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) if (!folio) { folio = f2fs_grab_meta_folio(sbi, start_blk++); orphan_blk = folio_address(folio); - memset(orphan_blk, 0, sizeof(*orphan_blk)); + footer = f2fs_orphan_footer(orphan_blk, sbi); + memset(orphan_blk, 0, sbi->blocksize); } orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino); - if (nentries == F2FS_ORPHANS_PER_BLOCK) { + if (nentries == F2FS_ORPHANS_PER_BLOCK(sbi)) { /* - * an orphan block is full of 1020 entries, + * an orphan block is full, * then we need to flush current orphan blocks * and bring another one in memory */ - orphan_blk->blk_addr = cpu_to_le16(index); - orphan_blk->blk_count = cpu_to_le16(orphan_blocks); - orphan_blk->entry_count = cpu_to_le32(nentries); + footer->blk_addr = cpu_to_le16(index); + footer->blk_count = cpu_to_le16(orphan_blocks); + footer->entry_count = cpu_to_le32(nentries); folio_mark_dirty(folio); f2fs_folio_put(folio, true); index++; @@ -1129,24 +1125,25 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) } if (folio) { - orphan_blk->blk_addr = cpu_to_le16(index); - orphan_blk->blk_count = cpu_to_le16(orphan_blocks); - orphan_blk->entry_count = cpu_to_le32(nentries); + footer->blk_addr = cpu_to_le16(index); + footer->blk_count = cpu_to_le16(orphan_blocks); + footer->entry_count = cpu_to_le32(nentries); folio_mark_dirty(folio); f2fs_folio_put(folio, true); } } -static __u32 f2fs_checkpoint_chksum(struct f2fs_checkpoint *ckpt) +static __u32 f2fs_checkpoint_chksum(struct f2fs_sb_info *sbi, + struct f2fs_checkpoint *ckpt) { unsigned int chksum_ofs = le32_to_cpu(ckpt->checksum_offset); __u32 chksum; chksum = f2fs_crc32(ckpt, chksum_ofs); - if (chksum_ofs < CP_CHKSUM_OFFSET) { + if (chksum_ofs < CP_CHKSUM_OFFSET(sbi)) { chksum_ofs += sizeof(chksum); chksum = f2fs_chksum(chksum, (__u8 *)ckpt + chksum_ofs, - F2FS_BLKSIZE - chksum_ofs); + F2FS_BLKSIZE(sbi) - chksum_ofs); } return chksum; } @@ -1166,13 +1163,13 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr, crc_offset = le32_to_cpu((*cp_block)->checksum_offset); if (crc_offset < CP_MIN_CHKSUM_OFFSET || - crc_offset > CP_CHKSUM_OFFSET) { + crc_offset > CP_CHKSUM_OFFSET(sbi)) { f2fs_folio_put(*cp_folio, true); f2fs_warn(sbi, "invalid crc_offset: %zu", crc_offset); return -EINVAL; } - crc = f2fs_checkpoint_chksum(*cp_block); + crc = f2fs_checkpoint_chksum(sbi, *cp_block); if (crc != cur_cp_crc(*cp_block)) { f2fs_folio_put(*cp_folio, true); f2fs_warn(sbi, "invalid crc value"); @@ -1709,7 +1706,7 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi, */ struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr); - memcpy(folio_address(folio), src, PAGE_SIZE); + memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi)); folio_mark_dirty(folio); if (unlikely(!folio_clear_dirty_for_io(folio))) @@ -1824,7 +1821,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) __clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); spin_unlock_irqrestore(&sbi->cp_lock, flags); - orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num); + orphan_blocks = GET_ORPHAN_BLOCKS(sbi, orphan_num); ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + orphan_blocks); @@ -1844,7 +1841,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); - crc32 = f2fs_checkpoint_chksum(ckpt); + crc32 = f2fs_checkpoint_chksum(sbi, ckpt); *((__le32 *)((unsigned char *)ckpt + le32_to_cpu(ckpt->checksum_offset))) = cpu_to_le32(crc32); @@ -1862,15 +1859,15 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) blk = start_blk + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks; for (i = 0; i < nm_i->nat_bits_blocks; i++) f2fs_update_meta_page(sbi, nm_i->nat_bits + - F2FS_BLK_TO_BYTES(i), blk + i); + F2FS_BLK_TO_BYTES(sbi, i), blk + i); } /* write out checkpoint buffer at block 0 */ f2fs_update_meta_page(sbi, ckpt, start_blk++); for (i = 1; i < 1 + cp_payload_blks; i++) - f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE, - start_blk++); + f2fs_update_meta_page(sbi, (char *)ckpt + + i * F2FS_BLKSIZE(sbi), start_blk++); if (orphan_num) { write_orphan_inodes(sbi, start_blk); @@ -2080,7 +2077,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi) sbi->max_orphans = (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS - NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) * - F2FS_ORPHANS_PER_BLOCK; + F2FS_ORPHANS_PER_BLOCK(sbi); } int __init f2fs_create_checkpoint_caches(void) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 21f396ebe22c..ebb0275aa8ff 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -439,7 +439,7 @@ struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi, } if (sector) - *sector = SECTOR_FROM_BLOCK(blk_addr); + *sector = SECTOR_FROM_BLOCK(sbi, blk_addr); return bdev; } @@ -1192,7 +1192,7 @@ static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info *vi, f2fs_bug_on(sbi, 1); inc_page_count(sbi, F2FS_RD_DATA); - f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi)); f2fs_submit_read_bio(sbi, bio, DATA); } @@ -1942,12 +1942,12 @@ static bool __f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len, if (pos + len > i_size_read(inode)) return false; - map.m_lblk = F2FS_BYTES_TO_BLK(pos); + map.m_lblk = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), pos); map.m_next_pgofs = NULL; map.m_next_extent = NULL; map.m_seg_type = NO_CHECK_TYPE; map.m_may_create = false; - last_lblk = F2FS_BLK_ALIGN(pos + len); + last_lblk = F2FS_BLK_ALIGN(F2FS_I_SB(inode), pos + len); while (map.m_lblk < last_lblk) { map.m_len = last_lblk - map.m_lblk; @@ -1990,9 +1990,9 @@ static int f2fs_xattr_fiemap(struct inode *inode, return err; } - phys = F2FS_BLK_TO_BYTES(ni.blk_addr); + phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr); offset = offsetof(struct f2fs_inode, i_addr) + - sizeof(__le32) * (DEF_ADDRS_PER_INODE - + sizeof(__le32) * (DEF_ADDRS_PER_INODE(sbi) - get_inline_xattr_addrs(inode)); phys += offset; @@ -2024,7 +2024,7 @@ static int f2fs_xattr_fiemap(struct inode *inode, return err; } - phys = F2FS_BLK_TO_BYTES(ni.blk_addr); + phys = F2FS_BLK_TO_BYTES(sbi, ni.blk_addr); len = inode->i_sb->s_blocksize; f2fs_folio_put(folio, true); @@ -2043,6 +2043,7 @@ static int f2fs_xattr_fiemap(struct inode *inode, int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_map_blocks map; sector_t start_blk, last_blk, blk_len, max_len; pgoff_t next_pgofs; @@ -2066,7 +2067,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, inode_lock_shared(inode); - maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode)); + maxbytes = F2FS_BLK_TO_BYTES(sbi, max_file_blocks(sbi, inode)); if (start > maxbytes) { ret = -EFBIG; goto out; @@ -2086,10 +2087,10 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, goto out; } - start_blk = F2FS_BYTES_TO_BLK(start); - last_blk = F2FS_BYTES_TO_BLK(start + len - 1); + start_blk = F2FS_BYTES_TO_BLK(sbi, start); + last_blk = F2FS_BYTES_TO_BLK(sbi, start + len - 1); blk_len = last_blk - start_blk + 1; - max_len = F2FS_BYTES_TO_BLK(maxbytes) - start_blk; + max_len = F2FS_BYTES_TO_BLK(sbi, maxbytes) - start_blk; next: memset(&map, 0, sizeof(map)); @@ -2111,7 +2112,7 @@ next: if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) { start_blk = next_pgofs; - if (F2FS_BLK_TO_BYTES(start_blk) < maxbytes) + if (F2FS_BLK_TO_BYTES(sbi, start_blk) < maxbytes) goto prep_next; flags |= FIEMAP_EXTENT_LAST; @@ -2159,14 +2160,14 @@ skip_fill: } else if (compr_appended) { unsigned int appended_blks = cluster_size - count_in_cluster + 1; - size += F2FS_BLK_TO_BYTES(appended_blks); + size += F2FS_BLK_TO_BYTES(sbi, appended_blks); start_blk += appended_blks; compr_cluster = false; } else { - logical = F2FS_BLK_TO_BYTES(start_blk); + logical = F2FS_BLK_TO_BYTES(sbi, start_blk); phys = __is_valid_data_blkaddr(map.m_pblk) ? - F2FS_BLK_TO_BYTES(map.m_pblk) : 0; - size = F2FS_BLK_TO_BYTES(map.m_len); + F2FS_BLK_TO_BYTES(sbi, map.m_pblk) : 0; + size = F2FS_BLK_TO_BYTES(sbi, map.m_len); flags = 0; if (compr_cluster) { @@ -2174,13 +2175,13 @@ skip_fill: count_in_cluster += map.m_len; if (count_in_cluster == cluster_size) { compr_cluster = false; - size += F2FS_BLKSIZE; + size += F2FS_BLKSIZE(sbi); } } else if (map.m_flags & F2FS_MAP_DELALLOC) { flags = FIEMAP_EXTENT_UNWRITTEN; } - start_blk += F2FS_BYTES_TO_BLK(size); + start_blk += F2FS_BYTES_TO_BLK(sbi, size); } prep_next: @@ -2200,7 +2201,8 @@ out: static inline loff_t f2fs_readpage_limit(struct inode *inode) { if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode)) - return F2FS_BLK_TO_BYTES(max_file_blocks(inode)); + return F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), + max_file_blocks(F2FS_I_SB(inode), inode)); return i_size_read(inode); } @@ -2218,7 +2220,7 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi, struct readahead_control *rac) { struct bio *bio = *bio_ret; - const unsigned int blocksize = F2FS_BLKSIZE; + const unsigned int blocksize = F2FS_BLKSIZE(F2FS_I_SB(inode)); sector_t block_in_file; sector_t last_block; sector_t last_block_in_file; @@ -2228,7 +2230,8 @@ static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi, block_in_file = (sector_t)index; last_block = block_in_file + nr_pages; - last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) + + last_block_in_file = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), + f2fs_readpage_limit(inode) + blocksize - 1); if (last_block > last_block_in_file) last_block = last_block_in_file; @@ -2306,7 +2309,7 @@ submit_and_realloc: inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO, - F2FS_BLKSIZE); + F2FS_BLKSIZE(F2FS_I_SB(inode))); *last_block_in_bio = block_nr; out: *bio_ret = bio; @@ -2324,7 +2327,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, struct bio *bio = *bio_ret; unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size; sector_t last_block_in_file; - const unsigned int blocksize = F2FS_BLKSIZE; + const unsigned int blocksize = F2FS_BLKSIZE(sbi); struct decompress_io_ctx *dic = NULL; struct extent_info ei = {}; bool from_dnode = true; @@ -2339,7 +2342,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc)); - last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) + + last_block_in_file = F2FS_BYTES_TO_BLK(sbi, + f2fs_readpage_limit(inode) + blocksize - 1); /* get rid of pages beyond EOF */ @@ -2456,7 +2460,8 @@ submit_and_realloc: refcount_inc(&dic->refcnt); inc_page_count(sbi, F2FS_RD_DATA); - f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, + F2FS_BLKSIZE(sbi)); *last_block_in_bio = blkaddr; } @@ -2630,14 +2635,14 @@ submit_and_realloc: */ f2fs_wait_on_block_writeback(inode, block_nr); - if (!bio_add_folio(bio, folio, F2FS_BLKSIZE, - offset << PAGE_SHIFT)) + if (!bio_add_folio(bio, folio, F2FS_BLKSIZE(F2FS_I_SB(inode)), + offset << PAGE_SHIFT)) goto submit_and_realloc; folio_in_bio = true; inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO, - F2FS_BLKSIZE); + F2FS_BLKSIZE(F2FS_I_SB(inode))); last_block_in_bio = block_nr; } trace_f2fs_read_folio(folio, DATA); @@ -4151,6 +4156,7 @@ static sector_t f2fs_bmap_compress(struct inode *inode, sector_t block) static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) { struct inode *inode = mapping->host; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); sector_t blknr = 0; if (f2fs_has_inline_data(inode)) @@ -4161,7 +4167,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) filemap_write_and_wait(mapping); /* Block number less than F2FS MAX BLOCKS */ - if (unlikely(block >= max_file_blocks(inode))) + if (unlikely(block >= max_file_blocks(sbi, inode))) goto out; if (f2fs_compressed_file(inode)) { @@ -4277,7 +4283,7 @@ static int check_swap_activate(struct swap_info_struct *sis, * to be very smart. */ cur_lblock = 0; - last_lblock = F2FS_BYTES_TO_BLK(i_size_read(inode)); + last_lblock = F2FS_BYTES_TO_BLK(sbi, i_size_read(inode)); while (cur_lblock < last_lblock && cur_lblock < sis->max) { struct f2fs_map_blocks map; @@ -4363,7 +4369,8 @@ retry: out: if (not_aligned) f2fs_warn(sbi, "Swapfile (%u) is not align to section: 1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate(%lu * N)", - not_aligned, blks_per_sec * F2FS_BLKSIZE); + not_aligned, + (unsigned long)blks_per_sec * F2FS_BLKSIZE(sbi)); return ret; } @@ -4532,12 +4539,14 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, unsigned int flags, struct iomap *iomap, struct iomap *srcmap) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_map_blocks map = { NULL, }; pgoff_t next_pgofs = 0; int err; - map.m_lblk = F2FS_BYTES_TO_BLK(offset); - map.m_len = F2FS_BYTES_TO_BLK(offset + length - 1) - map.m_lblk + 1; + map.m_lblk = F2FS_BYTES_TO_BLK(sbi, offset); + map.m_len = F2FS_BYTES_TO_BLK(sbi, offset + length - 1) - + map.m_lblk + 1; map.m_next_pgofs = &next_pgofs; map.m_seg_type = f2fs_rw_hint_to_seg_type(F2FS_I_SB(inode), inode->i_write_hint); @@ -4558,7 +4567,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, if (err) return err; - iomap->offset = F2FS_BLK_TO_BYTES(map.m_lblk); + iomap->offset = F2FS_BLK_TO_BYTES(sbi, map.m_lblk); /* * Sometimes I/O to an encrypted file has to be broken up to guarantee @@ -4578,11 +4587,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR)) return -EINVAL; - iomap->length = F2FS_BLK_TO_BYTES(map.m_len); + iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len); iomap->type = IOMAP_MAPPED; iomap->flags |= IOMAP_F_MERGED; iomap->bdev = map.m_bdev; - iomap->addr = F2FS_BLK_TO_BYTES(map.m_pblk); + iomap->addr = F2FS_BLK_TO_BYTES(sbi, map.m_pblk); if (flags & IOMAP_WRITE && map.m_last_pblk) iomap->private = (void *)map.m_last_pblk; @@ -4591,11 +4600,11 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, return -ENOTBLK; if (map.m_pblk == NULL_ADDR) { - iomap->length = F2FS_BLK_TO_BYTES(next_pgofs) - + iomap->length = F2FS_BLK_TO_BYTES(sbi, next_pgofs) - iomap->offset; iomap->type = IOMAP_HOLE; } else if (map.m_pblk == NEW_ADDR) { - iomap->length = F2FS_BLK_TO_BYTES(map.m_len); + iomap->length = F2FS_BLK_TO_BYTES(sbi, map.m_len); iomap->type = IOMAP_UNWRITTEN; } else { f2fs_bug_on(F2FS_I_SB(inode), 1); diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index ff379aff4472..a6cfceafe2fe 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -343,9 +343,9 @@ static void update_mem_info(struct f2fs_sb_info *sbi) /* build nm */ si->base_mem += sizeof(struct f2fs_nm_info); si->base_mem += __bitmap_size(sbi, NAT_BITMAP); - si->base_mem += F2FS_BLK_TO_BYTES(NM_I(sbi)->nat_bits_blocks); + si->base_mem += F2FS_BLK_TO_BYTES(sbi, NM_I(sbi)->nat_bits_blocks); si->base_mem += NM_I(sbi)->nat_blocks * - f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK); + f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi)); si->base_mem += NM_I(sbi)->nat_blocks / 8; si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short); diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index fd0e2cd31a81..75ff36a13f60 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -195,7 +195,7 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir, int *max_slots, bool use_hash) { - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr d; dentry_blk = folio_address(dentry_folio); @@ -518,7 +518,7 @@ static int make_empty_dir(struct inode *inode, struct inode *parent, struct folio *folio) { struct folio *dentry_folio; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr d; if (f2fs_has_inline_dentry(inode)) @@ -530,7 +530,7 @@ static int make_empty_dir(struct inode *inode, dentry_blk = folio_address(dentry_folio); - make_dentry_ptr_block(NULL, &d, dentry_blk); + make_dentry_ptr_block(inode, &d, dentry_blk); f2fs_do_make_empty_dir(inode, parent, &d); folio_mark_dirty(dentry_folio); @@ -690,7 +690,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname, unsigned long bidx, block; unsigned int nbucket, nblock; struct folio *dentry_folio = NULL; - struct f2fs_dentry_block *dentry_blk = NULL; + void *dentry_blk = NULL; struct f2fs_dentry_ptr d; struct folio *folio = NULL; int slots, err = 0; @@ -727,9 +727,9 @@ start: return PTR_ERR(dentry_folio); dentry_blk = folio_address(dentry_folio); - bit_pos = f2fs_room_for_filename(&dentry_blk->dentry_bitmap, - slots, NR_DENTRY_IN_BLOCK); - if (bit_pos < NR_DENTRY_IN_BLOCK) + make_dentry_ptr_block(dir, &d, dentry_blk); + bit_pos = f2fs_room_for_filename(d.bitmap, slots, d.max); + if (bit_pos < d.max) goto add_dentry; f2fs_folio_put(dentry_folio, true); @@ -750,7 +750,6 @@ add_dentry: } } - make_dentry_ptr_block(NULL, &d, dentry_blk); f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash, bit_pos); @@ -887,7 +886,8 @@ void f2fs_drop_nlink(struct inode *dir, struct inode *inode) void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio, struct inode *dir, struct inode *inode) { - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; + struct f2fs_dentry_ptr d; unsigned int bit_pos; int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); pgoff_t index = folio->index; @@ -905,18 +905,17 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio, f2fs_folio_wait_writeback(folio, DATA, true, true); dentry_blk = folio_address(folio); - bit_pos = dentry - dentry_blk->dentry; + make_dentry_ptr_block(dir, &d, dentry_blk); + bit_pos = dentry - d.dentry; for (i = 0; i < slots; i++) - __clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); + __clear_bit_le(bit_pos + i, d.bitmap); /* Let's check and deallocate this dentry page */ - bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, - NR_DENTRY_IN_BLOCK, - 0); + bit_pos = find_next_bit_le(d.bitmap, d.max, 0); folio_mark_dirty(folio); - if (bit_pos == NR_DENTRY_IN_BLOCK && - !f2fs_truncate_hole(dir, index, index + 1)) { + if (bit_pos == d.max && + !f2fs_truncate_hole(dir, index, index + 1)) { f2fs_clear_page_cache_dirty_tag(folio); folio_clear_dirty_for_io(folio); folio_clear_uptodate(folio); @@ -938,7 +937,8 @@ bool f2fs_empty_dir(struct inode *dir) { unsigned long bidx = 0; unsigned int bit_pos; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; + struct f2fs_dentry_ptr d; unsigned long nblock = dir_blocks(dir); if (f2fs_has_inline_dentry(dir)) @@ -959,17 +959,16 @@ bool f2fs_empty_dir(struct inode *dir) } dentry_blk = folio_address(dentry_folio); + make_dentry_ptr_block(dir, &d, dentry_blk); if (bidx == 0) bit_pos = 2; else bit_pos = 0; - bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, - NR_DENTRY_IN_BLOCK, - bit_pos); + bit_pos = find_next_bit_le(d.bitmap, d.max, bit_pos); f2fs_folio_put(dentry_folio, false); - if (bit_pos < NR_DENTRY_IN_BLOCK) + if (bit_pos < d.max) return false; bidx++; @@ -1066,10 +1065,12 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(file); unsigned long npages = dir_blocks(inode); - struct f2fs_dentry_block *dentry_blk = NULL; + void *dentry_blk = NULL; struct file_ra_state *ra = &file->f_ra; loff_t start_pos = ctx->pos; - unsigned int n = ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int entries = sbi->dentries_per_block; + unsigned int n = (unsigned long)ctx->pos / entries; struct f2fs_dentry_ptr d; struct fscrypt_str fstr = FSTR_INIT(NULL, 0); int err = 0; @@ -1089,7 +1090,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) goto out_free; } - for (; n < npages; ctx->pos = n * NR_DENTRY_IN_BLOCK) { + for (; n < npages; ctx->pos = n * entries) { struct folio *dentry_folio; pgoff_t next_pgofs; @@ -1122,7 +1123,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) make_dentry_ptr_block(inode, &d, dentry_blk); err = f2fs_fill_dentries(ctx, &d, - n * NR_DENTRY_IN_BLOCK, &fstr); + n * entries, &fstr); f2fs_folio_put(dentry_folio, false); if (err) break; diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 37cf9fa8d537..57217dc5b310 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -904,11 +904,12 @@ static int __get_new_block_age(struct inode *inode, struct extent_info *ei, struct extent_info tei = *ei; /* only fofs and len are valid */ /* - * When I/O is not aligned to a PAGE_SIZE, update will happen to the last - * file block even in seq write. So don't record age for newly last file - * block here. + * When I/O is not aligned to the filesystem block size, update will + * happen to the last file block even in seq write. Do not record the age + * of the new last file block here. */ - if ((f_size >> PAGE_SHIFT) == ei->fofs && f_size & (PAGE_SIZE - 1) && + if ((f_size >> sbi->log_blocksize) == ei->fofs && + f_size & F2FS_BLKSIZE_MASK(sbi) && blkaddr == NEW_ADDR) return -EINVAL; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 9940a6cecf1a..62efc25cd107 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -466,6 +466,7 @@ struct discard_entry { #define MAX_PLIST_NUM 512 #define plist_idx(blk_num) ((blk_num) >= MAX_PLIST_NUM ? \ (MAX_PLIST_NUM - 1) : ((blk_num) - 1)) +#define MAX_DISCARD_DROP_COUNT 512 enum { D_PREP, /* initial */ @@ -602,8 +603,9 @@ static inline int update_sits_in_cursum(struct f2fs_journal *journal, int i) #define DEF_INLINE_RESERVED_SIZE 1 static inline int get_extra_isize(struct inode *inode); static inline int get_inline_xattr_addrs(struct inode *inode); +static inline unsigned int cur_addrs_per_inode(struct inode *inode); #define MAX_INLINE_DATA(inode) (sizeof(__le32) * \ - (CUR_ADDRS_PER_INODE(inode) - \ + (cur_addrs_per_inode(inode) - \ get_inline_xattr_addrs(inode) - \ DEF_INLINE_RESERVED_SIZE)) @@ -669,17 +671,6 @@ struct f2fs_dentry_ptr { int nr_bitmap; }; -static inline void make_dentry_ptr_block(struct inode *inode, - struct f2fs_dentry_ptr *d, struct f2fs_dentry_block *t) -{ - d->inode = inode; - d->max = NR_DENTRY_IN_BLOCK; - d->nr_bitmap = SIZE_OF_DENTRY_BITMAP; - d->bitmap = t->dentry_bitmap; - d->dentry = t->dentry; - d->filename = t->filename; -} - static inline void make_dentry_ptr_inline(struct inode *inode, struct f2fs_dentry_ptr *d, void *t) { @@ -1862,6 +1853,15 @@ struct f2fs_sb_info { unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ unsigned int blocksize; /* block size */ + unsigned int nat_entries_per_block; /* NAT entries in a block */ + unsigned int addrs_per_inode; /* addresses in an inode block */ + unsigned int addrs_per_block; /* addresses in a direct node block */ + unsigned int nids_per_block; /* node IDs in an indirect node block */ + unsigned int sit_entries_per_block; /* SIT entries in a block */ + unsigned int orphans_per_block; /* orphan inodes in a block */ + unsigned int dentries_per_block; /* dentries in a block */ + unsigned int dentry_bitmap_size; /* dentry bitmap size in bytes */ + unsigned int dentry_reserved_size; /* dentry reserved bytes */ unsigned int root_ino_num; /* root inode number*/ unsigned int node_ino_num; /* node inode number*/ unsigned int meta_ino_num; /* meta inode number*/ @@ -2250,6 +2250,47 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio) return F2FS_M_SB(folio->mapping); } +#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block) +#define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block) +#define DEF_ADDRS_PER_INODE(sbi) ((sbi)->addrs_per_inode) +#define DEF_ADDRS_PER_BLOCK(sbi) ((sbi)->addrs_per_block) +#define NIDS_PER_BLOCK(sbi) ((sbi)->nids_per_block) +#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block) +#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \ + F2FS_ORPHANS_PER_BLOCK(sbi)) +#define CP_CHKSUM_OFFSET(sbi) (F2FS_BLKSIZE(sbi) - sizeof(__le32)) + +#define NODE_DIR1_BLOCK(sbi) (DEF_ADDRS_PER_INODE(sbi) + 1) +#define NODE_DIR2_BLOCK(sbi) (DEF_ADDRS_PER_INODE(sbi) + 2) +#define NODE_IND1_BLOCK(sbi) (DEF_ADDRS_PER_INODE(sbi) + 3) +#define NODE_IND2_BLOCK(sbi) (DEF_ADDRS_PER_INODE(sbi) + 4) +#define NODE_DIND_BLOCK(sbi) (DEF_ADDRS_PER_INODE(sbi) + 5) + +static inline struct f2fs_orphan_footer * +f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi) +{ + return (struct f2fs_orphan_footer *) + ((char *)orphan_block + sbi->blocksize - + sizeof(struct f2fs_orphan_footer)); +} + +static inline void make_dentry_ptr_block(struct inode *inode, + struct f2fs_dentry_ptr *d, void *t) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int entries = sbi->dentries_per_block; + unsigned int bitmap_size = sbi->dentry_bitmap_size; + unsigned int reserved_size = sbi->dentry_reserved_size; + + d->inode = inode; + d->max = entries; + d->nr_bitmap = bitmap_size; + d->bitmap = t; + d->dentry = t + bitmap_size + reserved_size; + d->filename = t + bitmap_size + reserved_size + + SIZE_OF_DIR_ENTRY * entries; +} + static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi) { return (struct f2fs_super_block *)(sbi->raw_super); @@ -2270,6 +2311,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi) return (struct f2fs_checkpoint *)(sbi->ckpt); } +static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio) +{ + return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) - + sizeof(struct node_footer); +} + static inline struct f2fs_node *F2FS_NODE(const struct folio *folio) { return (struct f2fs_node *)folio_address(folio); @@ -2280,6 +2327,13 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio) return &((struct f2fs_node *)folio_address(folio))->i; } +static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio) +{ + return folio_address(folio) + F2FS_BLKSIZE(F2FS_F_SB(folio)) - + sizeof(struct node_footer) - + SIZE_OF_I_NID; +} + static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) { return (struct f2fs_nm_info *)(sbi->nm_info); @@ -2566,7 +2620,8 @@ static inline int F2FS_HAS_BLOCKS(struct inode *inode) { block_t xattr_block = F2FS_I(inode)->i_xattr_nid ? 1 : 0; - return (inode->i_blocks >> F2FS_LOG_SECTORS_PER_BLOCK) > xattr_block; + return (inode->i_blocks >> + F2FS_LOG_SECTORS_PER_BLOCK(F2FS_I_SB(inode))) > xattr_block; } static inline bool f2fs_has_xattr_block(unsigned int ofs) @@ -2691,7 +2746,7 @@ static inline bool folio_test_f2fs_##name(const struct folio *folio) \ } \ static inline bool page_private_##name(struct page *page) \ { \ - return PagePrivate(page) && \ + return page_private(page) && \ test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \ test_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ } @@ -2710,9 +2765,9 @@ static inline void folio_set_f2fs_##name(struct folio *folio) \ } \ static inline void set_page_private_##name(struct page *page) \ { \ - if (!PagePrivate(page)) \ - attach_page_private(page, (void *)0); \ - set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); \ + if (!page_private(page)) \ + attach_page_private(page, \ + (void *)BIT(PAGE_PRIVATE_NOT_POINTER)); \ set_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \ } @@ -2772,7 +2827,7 @@ static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, struct inode *inode, block_t count) { - blkcnt_t sectors = count << F2FS_LOG_SECTORS_PER_BLOCK; + blkcnt_t sectors = count << F2FS_LOG_SECTORS_PER_BLOCK(sbi); spin_lock(&sbi->stat_lock); if (unlikely(sbi->total_valid_block_count < count)) { @@ -2924,7 +2979,7 @@ static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag) if (flag == NAT_BITMAP) return tmp_ptr; else - return (unsigned char *)ckpt + F2FS_BLKSIZE; + return (unsigned char *)ckpt + F2FS_BLKSIZE(sbi); } else { offset = (flag == NAT_BITMAP) ? le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0; @@ -3250,13 +3305,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, cond_resched(); } -#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino) - static inline bool IS_INODE(const struct folio *folio) { - struct f2fs_node *p = F2FS_NODE(folio); + struct node_footer *footer = F2FS_NODE_FOOTER(folio); - return RAW_IS_INODE(p); + return footer->nid == footer->ino; } static inline int offset_in_addr(struct f2fs_inode *i) @@ -3265,9 +3318,11 @@ static inline int offset_in_addr(struct f2fs_inode *i) (le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0; } -static inline __le32 *blkaddr_in_node(struct f2fs_node *node) +static inline __le32 *blkaddr_in_node(const struct folio *folio) { - return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr; + struct f2fs_node *node = F2FS_NODE(folio); + + return IS_INODE(folio) ? node->i.i_addr : node->dn.addr; } static inline int f2fs_has_extra_attr(struct inode *inode); @@ -3284,7 +3339,7 @@ static inline unsigned int get_dnode_base(struct inode *inode, static inline __le32 *get_dnode_addr(struct inode *inode, struct folio *node_folio) { - return blkaddr_in_node(F2FS_NODE(node_folio)) + + return blkaddr_in_node(node_folio) + get_dnode_base(inode, node_folio); } @@ -3599,20 +3654,26 @@ static inline bool f2fs_need_compress_data(struct inode *inode) static inline unsigned int addrs_per_page(struct inode *inode, bool is_inode) { - unsigned int addrs = is_inode ? (CUR_ADDRS_PER_INODE(inode) - - get_inline_xattr_addrs(inode)) : DEF_ADDRS_PER_BLOCK; + unsigned int addrs = is_inode ? (cur_addrs_per_inode(inode) - + get_inline_xattr_addrs(inode)) : + DEF_ADDRS_PER_BLOCK(F2FS_I_SB(inode)); if (f2fs_compressed_file(inode)) return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size); return addrs; } +static inline unsigned int cur_addrs_per_inode(struct inode *inode) +{ + return DEF_ADDRS_PER_INODE(F2FS_I_SB(inode)) - get_extra_isize(inode); +} + static inline void *inline_xattr_addr(struct inode *inode, const struct folio *folio) { struct f2fs_inode *ri = F2FS_INODE(folio); - return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE(F2FS_I_SB(inode)) - get_inline_xattr_addrs(inode)]); } @@ -3972,7 +4033,7 @@ void f2fs_inode_synced(struct inode *inode); int f2fs_dquot_initialize(struct inode *inode); int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly); int f2fs_do_quota_sync(struct super_block *sb, int type); -loff_t max_file_blocks(struct inode *inode); +loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode); void f2fs_quota_off_umount(struct super_block *sb); void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); @@ -4064,6 +4125,8 @@ void f2fs_reserve_device_alias(struct f2fs_sb_info *sbi, block_t addr, bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr); int f2fs_start_discard_thread(struct f2fs_sb_info *sbi); void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi); +void f2fs_drop_discard_cmd_range(struct f2fs_sb_info *sbi, + block_t start, block_t len); void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi); bool f2fs_issue_discard_timeout(struct f2fs_sb_info *sbi, bool need_check); void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi, @@ -5218,8 +5281,9 @@ static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi, NULL, 0, DATA); truncate_inode_pages_range(META_MAPPING(sbi), - F2FS_BLK_TO_BYTES((loff_t)blkaddr), - F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1))); + F2FS_BLK_TO_BYTES(sbi, (loff_t)blkaddr), + F2FS_BLK_END_BYTES(sbi, + (loff_t)(blkaddr + cnt - 1))); } static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index edc352569e87..c763fb972e8a 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -110,7 +110,8 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf) ret = filemap_fault(vmf); if (ret & VM_FAULT_LOCKED) f2fs_update_iostat(F2FS_I_SB(inode), inode, - APP_MAPPED_READ_IO, F2FS_BLKSIZE); + APP_MAPPED_READ_IO, + F2FS_BLKSIZE(F2FS_I_SB(inode))); trace_f2fs_filemap_fault(inode, vmf->pgoff, flags, ret); @@ -233,7 +234,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) } folio_mark_dirty(folio); - f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, inode, APP_MAPPED_IO, F2FS_BLKSIZE(sbi)); f2fs_update_time(sbi, REQ_TIME); out_sem: @@ -513,7 +514,8 @@ static bool __found_offset(struct address_space *mapping, static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; - loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode)); + loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), + max_file_blocks(F2FS_I_SB(inode), inode)); struct dnode_of_data dn; pgoff_t pgofs, end_offset; loff_t data_ofs = offset; @@ -537,9 +539,10 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) } } - pgofs = (pgoff_t)(offset >> PAGE_SHIFT); + pgofs = F2FS_BYTES_TO_BLK(F2FS_I_SB(inode), offset); - for (; data_ofs < isize; data_ofs = (loff_t)pgofs << PAGE_SHIFT) { + for (; data_ofs < isize; + data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) { set_new_dnode(&dn, inode, NULL, NULL, 0); err = f2fs_get_dnode_of_data(&dn, pgofs, LOOKUP_NODE); if (err && err != -ENOENT) { @@ -559,7 +562,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) /* find data/hole in dnode block */ for (; dn.ofs_in_node < end_offset; dn.ofs_in_node++, pgofs++, - data_ofs = (loff_t)pgofs << PAGE_SHIFT) { + data_ofs = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), pgofs)) { block_t blkaddr; blkaddr = f2fs_data_blkaddr(&dn); @@ -595,7 +598,8 @@ fail: static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; - loff_t maxbytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode)); + loff_t maxbytes = F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), + max_file_blocks(F2FS_I_SB(inode), inode)); switch (whence) { case SEEK_SET: @@ -846,9 +850,9 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) goto out_err; } - free_from = (pgoff_t)F2FS_BLK_ALIGN(from); + free_from = (pgoff_t)F2FS_BLK_ALIGN(sbi, from); - if (free_from >= max_file_blocks(inode)) + if (free_from >= max_file_blocks(sbi, inode)) goto free_partial; if (lock) @@ -959,9 +963,10 @@ int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock) int f2fs_truncate(struct inode *inode) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int err; - if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) + if (unlikely(f2fs_cp_error(sbi))) return -EIO; if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || @@ -986,8 +991,8 @@ int f2fs_truncate(struct inode *inode) * leak in evict() path. */ truncate_inode_pages_range(inode->i_mapping, - F2FS_BLK_TO_BYTES(0), - F2FS_BLK_END_BYTES(0)); + F2FS_BLK_TO_BYTES(sbi, 0), + F2FS_BLK_END_BYTES(sbi, 0)); return err; } } @@ -1157,7 +1162,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, return -EOPNOTSUPP; if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) && !IS_ALIGNED(attr->ia_size, - F2FS_BLK_TO_BYTES(fi->i_cluster_size))) + F2FS_BLK_TO_BYTES(sbi, fi->i_cluster_size))) return -EINVAL; if (f2fs_is_pinned_file(inode)) { @@ -1173,7 +1178,7 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, * pinned file. */ else if (!IS_ALIGNED(attr->ia_size, - F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi)))) + F2FS_BLK_TO_BYTES(sbi, CAP_BLKS_PER_SEC(sbi)))) return -EINVAL; } } @@ -1667,7 +1672,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len) return -EINVAL; /* collapse range should be aligned to block size of f2fs. */ - if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1)) + if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) || + len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode))) return -EINVAL; ret = f2fs_convert_inline_inode(inode); @@ -1882,7 +1888,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) return -EINVAL; /* insert range should be aligned to block size of f2fs. */ - if (offset & (F2FS_BLKSIZE - 1) || len & (F2FS_BLKSIZE - 1)) + if (offset & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode)) || + len & F2FS_BLKSIZE_MASK(F2FS_I_SB(inode))) return -EINVAL; ret = f2fs_convert_inline_inode(inode); @@ -2644,7 +2651,8 @@ static int f2fs_keep_noreuse_range(struct inode *inode, loff_t offset, loff_t len) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - u64 max_bytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode)); + u64 max_bytes = F2FS_BLK_TO_BYTES(sbi, + max_file_blocks(sbi, inode)); u64 start, end; int ret = 0; @@ -3184,11 +3192,12 @@ static int f2fs_ioc_defragment(struct file *filp, unsigned long arg) return -EFAULT; /* verify alignment of offset & size */ - if (range.start & (F2FS_BLKSIZE - 1) || range.len & (F2FS_BLKSIZE - 1)) + if (range.start & F2FS_BLKSIZE_MASK(sbi) || + range.len & F2FS_BLKSIZE_MASK(sbi)) return -EINVAL; - if (unlikely((range.start + range.len) >> PAGE_SHIFT > - max_file_blocks(inode))) + if (unlikely(F2FS_BYTES_TO_BLK(sbi, range.start + range.len) > + max_file_blocks(sbi, inode))) return -EINVAL; err = mnt_want_write_file(filp); @@ -3270,7 +3279,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, if (src == dst && pos_out > pos_in && pos_out < pos_in + len) goto out_unlock; if (pos_in + len == src->i_size) - len = ALIGN(src->i_size, F2FS_BLKSIZE) - pos_in; + len = ALIGN(src->i_size, F2FS_BLKSIZE(sbi)) - pos_in; if (len == 0) { ret = 0; goto out_unlock; @@ -3288,9 +3297,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, } /* verify the end result is block aligned */ - if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE) || - !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE) || - !IS_ALIGNED(pos_out, F2FS_BLKSIZE)) + if (!IS_ALIGNED(pos_in, F2FS_BLKSIZE(sbi)) || + !IS_ALIGNED(pos_in + len, F2FS_BLKSIZE(sbi)) || + !IS_ALIGNED(pos_out, F2FS_BLKSIZE(sbi))) goto out_unlock; ret = f2fs_convert_inline_inode(src); @@ -3322,9 +3331,9 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, } f2fs_lock_op(sbi, &lc); - ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(pos_in), - F2FS_BYTES_TO_BLK(pos_out), - F2FS_BYTES_TO_BLK(len), false); + ret = __exchange_data_block(src, dst, F2FS_BYTES_TO_BLK(sbi, pos_in), + F2FS_BYTES_TO_BLK(sbi, pos_out), + F2FS_BYTES_TO_BLK(sbi, len), false); if (!ret) { if (dst_max_i_size) @@ -3843,6 +3852,7 @@ static int f2fs_ioc_reserve_dev_alias(struct file *filp) write_unlock(&et->lock); clear_inode_flag(inode, FI_NO_EXTENT); + f2fs_drop_discard_cmd_range(sbi, ei.blk, ei.len); f2fs_reserve_device_alias(sbi, ei.blk, ei.len); i_size_write(inode, (loff_t)ei.len << sbi->log_blocksize); @@ -3990,7 +4000,7 @@ int f2fs_precache_extents(struct inode *inode) map.m_next_extent = &m_next_extent; map.m_seg_type = NO_CHECK_TYPE; map.m_may_create = false; - end = F2FS_BLK_ALIGN(i_size_read(inode)); + end = F2FS_BLK_ALIGN(F2FS_I_SB(inode), i_size_read(inode)); while (map.m_lblk < end) { map.m_len = end - map.m_lblk; @@ -4506,8 +4516,8 @@ unlock_inode: static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode, pgoff_t off, block_t block, block_t len, u32 flags) { - sector_t sector = SECTOR_FROM_BLOCK(block); - sector_t nr_sects = SECTOR_FROM_BLOCK(len); + sector_t sector = SECTOR_FROM_BLOCK(F2FS_I_SB(inode), block); + sector_t nr_sects = SECTOR_FROM_BLOCK(F2FS_I_SB(inode), len); int ret = 0; if (flags & F2FS_TRIM_FILE_DISCARD) { @@ -4584,14 +4594,14 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg) to_end = true; } - if (!IS_ALIGNED(range.start, F2FS_BLKSIZE) || - (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE))) { + if (!IS_ALIGNED(range.start, F2FS_BLKSIZE(sbi)) || + (!to_end && !IS_ALIGNED(end_addr, F2FS_BLKSIZE(sbi)))) { ret = -EINVAL; goto err; } - index = F2FS_BYTES_TO_BLK(range.start); - pg_end = DIV_ROUND_UP(end_addr, F2FS_BLKSIZE); + index = F2FS_BYTES_TO_BLK(sbi, range.start); + pg_end = F2FS_BLK_ALIGN(sbi, end_addr); ret = f2fs_convert_inline_inode(inode); if (ret) @@ -5381,7 +5391,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter, * buffered IO, if DIO meets any holes. */ if (dio && i_size_read(inode) && - (F2FS_BYTES_TO_BLK(pos) < F2FS_BLK_ALIGN(i_size_read(inode)))) + (F2FS_BYTES_TO_BLK(sbi, pos) < + F2FS_BLK_ALIGN(sbi, i_size_read(inode)))) return 0; /* No-wait I/O can't allocate blocks. */ @@ -5402,8 +5413,8 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter, } /* Do not preallocate blocks that will be written partially in 4KB. */ - map.m_lblk = F2FS_BLK_ALIGN(pos); - map.m_len = F2FS_BYTES_TO_BLK(pos + count); + map.m_lblk = F2FS_BLK_ALIGN(sbi, pos); + map.m_len = F2FS_BYTES_TO_BLK(sbi, pos + count); if (map.m_len > map.m_lblk) map.m_len -= map.m_lblk; else diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 0a00180c21dc..bc22dde1cb30 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1066,7 +1066,7 @@ next_step: continue; if (phase == 0) { - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1, + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1, META_NAT, true); continue; } @@ -1123,7 +1123,8 @@ next_step: */ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode) { - unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int indirect_blks = 2 * NIDS_PER_BLOCK(sbi) + 4; unsigned int bidx; if (node_ofs == 0) @@ -1132,11 +1133,12 @@ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode) if (node_ofs <= 2) { bidx = node_ofs - 1; } else if (node_ofs <= indirect_blks) { - int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1); + int dec = (node_ofs - 4) / (NIDS_PER_BLOCK(sbi) + 1); bidx = node_ofs - 2 - dec; } else { - int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); + int dec = (node_ofs - indirect_blks - 3) / + (NIDS_PER_BLOCK(sbi) + 1); bidx = node_ofs - 5 - dec; } @@ -1176,10 +1178,10 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, if (IS_INODE(node_folio)) { base = offset_in_addr(F2FS_INODE(node_folio)); - max_addrs = DEF_ADDRS_PER_INODE; + max_addrs = DEF_ADDRS_PER_INODE(sbi); } else { base = 0; - max_addrs = DEF_ADDRS_PER_BLOCK; + max_addrs = DEF_ADDRS_PER_BLOCK(sbi); } if (base + ofs_in_node >= max_addrs) { @@ -1303,8 +1305,8 @@ got_it: f2fs_put_page(fio.encrypted_page, false); f2fs_folio_put(folio, true); - f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE); - f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE(sbi)); + f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE(sbi)); if (atomic_inode) iput(atomic_inode); @@ -1424,9 +1426,9 @@ static int move_data_block(struct inode *inode, block_t bidx, } f2fs_update_iostat(fio.sbi, inode, FS_DATA_READ_IO, - F2FS_BLKSIZE); + F2FS_BLKSIZE(fio.sbi)); f2fs_update_iostat(fio.sbi, NULL, FS_GDATA_READ_IO, - F2FS_BLKSIZE); + F2FS_BLKSIZE(fio.sbi)); folio_lock(mfolio); if (unlikely(!is_meta_folio(mfolio) || @@ -1477,7 +1479,8 @@ static int move_data_block(struct inode *inode, block_t bidx, fio.new_blkaddr = newaddr; f2fs_submit_page_write(&fio); - f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, F2FS_BLKSIZE); + f2fs_update_iostat(fio.sbi, NULL, FS_GC_DATA_IO, + F2FS_BLKSIZE(fio.sbi)); f2fs_update_data_blkaddr(&dn, newaddr); set_inode_flag(inode, FI_APPEND_WRITE); @@ -1614,7 +1617,7 @@ next_step: continue; if (phase == 0) { - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1, + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), 1, META_NAT, true); continue; } diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index aec06fb4fd76..3e0b9449ffba 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode) static bool inode_has_blocks(struct inode *inode, struct folio *ifolio) { - struct f2fs_inode *ri = F2FS_INODE(ifolio); int i; if (F2FS_HAS_BLOCKS(inode)) return true; for (i = 0; i < DEF_NIDS_PER_INODE; i++) { - if (ri->i_nid[i]) + if (F2FS_INODE_NIDS(ifolio)[i]) return true; } return false; @@ -415,7 +414,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio, { struct folio *folio; struct dnode_of_data dn; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr src, dst; int err; @@ -449,7 +448,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio, * Start by zeroing the full block, to ensure that all unused space is * zeroed and no uninitialized memory is leaked to disk. */ - memset(dentry_blk, 0, F2FS_BLKSIZE); + memset(dentry_blk, 0, F2FS_BLKSIZE(F2FS_I_SB(dir))); make_dentry_ptr_inline(dir, &src, inline_dentry); make_dentry_ptr_block(dir, &dst, dentry_blk); @@ -478,8 +477,8 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio, F2FS_I(dir)->i_inline_xattr_size = 0; f2fs_i_depth_write(dir, 1); - if (i_size_read(dir) < PAGE_SIZE) - f2fs_i_size_write(dir, PAGE_SIZE); + if (i_size_read(dir) < F2FS_BLKSIZE(F2FS_I_SB(dir))) + f2fs_i_size_write(dir, F2FS_BLKSIZE(F2FS_I_SB(dir))); out: f2fs_folio_put(folio, true); return err; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 96cc0e777567..82ebcb338b0c 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) { - struct f2fs_node *node = F2FS_NODE(folio); - struct f2fs_inode *ri = &node->i; - __le32 ino = node->footer.ino; + struct f2fs_inode *ri = F2FS_INODE(folio); + __le32 ino = F2FS_NODE_FOOTER(folio)->ino; __le32 gen = ri->i_generation; __u32 chksum, chksum_seed; __u32 dummy_cs = 0; @@ -166,7 +165,7 @@ static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) chksum = f2fs_chksum(chksum, (__u8 *)&dummy_cs, cs_size); offset += cs_size; chksum = f2fs_chksum(chksum, (__u8 *)ri + offset, - F2FS_BLKSIZE - offset); + F2FS_BLKSIZE(sbi) - offset); return chksum; } @@ -222,11 +221,11 @@ static bool sanity_check_compress_inode(struct inode *inode, return false; } if (le64_to_cpu(ri->i_compr_blocks) > - SECTOR_TO_BLOCK(inode->i_blocks)) { + SECTOR_TO_BLOCK(sbi, inode->i_blocks)) { f2fs_warn(sbi, "%s: inode (ino=%llx) has inconsistent i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix", __func__, inode->i_ino, le64_to_cpu(ri->i_compr_blocks), - SECTOR_TO_BLOCK(inode->i_blocks)); + SECTOR_TO_BLOCK(sbi, inode->i_blocks)); return false; } if (ri->i_log_cluster_size < MIN_COMPRESS_LOG_SIZE || @@ -338,12 +337,13 @@ static bool sanity_check_inode(struct inode *inode, struct folio *node_folio) } if (f2fs_sb_has_flexible_inline_xattr(sbi) && - (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE || + (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE(i_blocksize(inode)) || (f2fs_has_inline_xattr(inode) && fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE))) { - f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %lu", + f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %zu", __func__, inode->i_ino, fi->i_inline_xattr_size, - MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE); + MIN_INLINE_XATTR_SIZE, + (size_t)MAX_INLINE_XATTR_SIZE(i_blocksize(inode))); return false; } @@ -447,7 +447,8 @@ static int do_read_inode(struct inode *inode) i_gid_write(inode, le32_to_cpu(ri->i_gid)); set_nlink(inode, le32_to_cpu(ri->i_links)); inode->i_size = le64_to_cpu(ri->i_size); - inode->i_blocks = SECTOR_FROM_BLOCK(le64_to_cpu(ri->i_blocks) - 1); + inode->i_blocks = SECTOR_FROM_BLOCK(sbi, + le64_to_cpu(ri->i_blocks) - 1); inode_set_atime(inode, le64_to_cpu(ri->i_atime), le32_to_cpu(ri->i_atime_nsec)); @@ -696,6 +697,7 @@ retry: void f2fs_update_inode(struct inode *inode, struct folio *node_folio) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_inode_info *fi = F2FS_I(inode); struct f2fs_inode *ri; struct extent_tree *et = fi->extent_tree[EX_READ]; @@ -712,7 +714,8 @@ void f2fs_update_inode(struct inode *inode, struct folio *node_folio) ri->i_uid = cpu_to_le32(i_uid_read(inode)); ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); - ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(READ_ONCE(inode->i_blocks)) + 1); + ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(sbi, + READ_ONCE(inode->i_blocks)) + 1); if (!f2fs_is_atomic_file(inode) || is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 86c2e67e43b6..68a95d703c4a 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -165,11 +165,11 @@ static struct folio *get_next_nat_folio(struct f2fs_sb_info *sbi, nid_t nid) src_addr = folio_address(src_folio); dst_addr = folio_address(dst_folio); - memcpy(dst_addr, src_addr, PAGE_SIZE); + memcpy(dst_addr, src_addr, F2FS_BLKSIZE(sbi)); folio_mark_dirty(dst_folio); f2fs_folio_put(src_folio, true); - set_to_next_nat(nm_i, nid); + set_to_next_nat(sbi, nm_i, nid); return dst_folio; } @@ -254,10 +254,11 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) __free_nat_entry(e); } -static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, +static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_sb_info *sbi, + struct f2fs_nm_info *nm_i, struct nat_entry *ne) { - nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); + nid_t set = NAT_BLOCK_OFFSET(sbi, ne->ni.nid); struct nat_entry_set *head; head = radix_tree_lookup(&nm_i->nat_set_root, set); @@ -274,14 +275,15 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, return head; } -static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, +static void __set_nat_cache_dirty(struct f2fs_sb_info *sbi, + struct f2fs_nm_info *nm_i, struct nat_entry *ne, bool init_dirty) { struct nat_entry_set *head; bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR; if (!new_ne) - head = __grab_nat_entry_set(nm_i, ne); + head = __grab_nat_entry_set(sbi, nm_i, ne); /* * update entry_cnt in below condition: @@ -527,7 +529,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, nat_set_blkaddr(e, new_blkaddr); if (!__is_valid_data_blkaddr(new_blkaddr)) set_nat_flag(e, IS_CHECKPOINTED, false); - __set_nat_cache_dirty(nm_i, e, init_dirty); + __set_nat_cache_dirty(sbi, nm_i, e, init_dirty); /* update fsync_mark if its inode nat entry is still alive */ if (ni->nid != ni->ino) @@ -578,7 +580,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct f2fs_nm_info *nm_i = NM_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); struct f2fs_journal *journal = curseg->journal; - nid_t start_nid = START_NID(nid); + nid_t start_nid = f2fs_start_nid(sbi, nid); struct f2fs_nat_block *nat_blk; struct folio *folio = NULL; struct f2fs_nat_entry ne; @@ -689,7 +691,7 @@ static void f2fs_ra_node_pages(struct folio *parent, int start, int n) /* Then, try readahead for siblings of the desired node */ end = start + n; - end = min(end, (int)NIDS_PER_BLOCK); + end = min_t(int, end, NIDS_PER_BLOCK(sbi)); for (i = start; i < end; i++) { nid = get_nid(parent, i, false); f2fs_ra_node_page(sbi, nid); @@ -700,9 +702,11 @@ static void f2fs_ra_node_pages(struct folio *parent, int start, int n) pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) { + struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); const long direct_index = ADDRS_PER_INODE(dn->inode); const long direct_blks = ADDRS_PER_BLOCK(dn->inode); - const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK; + const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * + NIDS_PER_BLOCK(sbi); unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode); int cur_level = dn->cur_level; int max_level = dn->max_level; @@ -712,7 +716,7 @@ pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) return pgofs + 1; while (max_level-- > cur_level) - skipped_unit *= NIDS_PER_BLOCK; + skipped_unit *= NIDS_PER_BLOCK(sbi); switch (dn->max_level) { case 3: @@ -738,11 +742,13 @@ pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) static int get_node_path(struct inode *inode, long block, int offset[4], unsigned int noffset[4]) { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); const long direct_index = ADDRS_PER_INODE(inode); const long direct_blks = ADDRS_PER_BLOCK(inode); - const long dptrs_per_blk = NIDS_PER_BLOCK; - const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK; - const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; + const long dptrs_per_blk = NIDS_PER_BLOCK(sbi); + const long indirect_blks = ADDRS_PER_BLOCK(inode) * + NIDS_PER_BLOCK(sbi); + const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK(sbi); int n = 0; int level = 0; @@ -754,7 +760,7 @@ static int get_node_path(struct inode *inode, long block, } block -= direct_index; if (block < direct_blks) { - offset[n++] = NODE_DIR1_BLOCK; + offset[n++] = NODE_DIR1_BLOCK(sbi); noffset[n] = 1; offset[n] = block; level = 1; @@ -762,7 +768,7 @@ static int get_node_path(struct inode *inode, long block, } block -= direct_blks; if (block < direct_blks) { - offset[n++] = NODE_DIR2_BLOCK; + offset[n++] = NODE_DIR2_BLOCK(sbi); noffset[n] = 2; offset[n] = block; level = 1; @@ -770,7 +776,7 @@ static int get_node_path(struct inode *inode, long block, } block -= direct_blks; if (block < indirect_blks) { - offset[n++] = NODE_IND1_BLOCK; + offset[n++] = NODE_IND1_BLOCK(sbi); noffset[n] = 3; offset[n++] = block / direct_blks; noffset[n] = 4 + offset[n - 1]; @@ -780,7 +786,7 @@ static int get_node_path(struct inode *inode, long block, } block -= indirect_blks; if (block < indirect_blks) { - offset[n++] = NODE_IND2_BLOCK; + offset[n++] = NODE_IND2_BLOCK(sbi); noffset[n] = 4 + dptrs_per_blk; offset[n++] = block / direct_blks; noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; @@ -790,7 +796,7 @@ static int get_node_path(struct inode *inode, long block, } block -= indirect_blks; if (block < dindirect_blks) { - offset[n++] = NODE_DIND_BLOCK; + offset[n++] = NODE_DIND_BLOCK(sbi); noffset[n] = 5 + (dptrs_per_blk * 2); offset[n++] = block / indirect_blks; noffset[n] = 6 + (dptrs_per_blk * 2) + @@ -1052,6 +1058,7 @@ static int truncate_dnode(struct dnode_of_data *dn) static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, int ofs, int depth) { + struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); struct dnode_of_data rdn = *dn; struct folio *folio; struct f2fs_node *rn; @@ -1061,7 +1068,7 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, int i, ret; if (dn->nid == 0) - return NIDS_PER_BLOCK + 1; + return NIDS_PER_BLOCK(sbi) + 1; trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); @@ -1072,11 +1079,11 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, return PTR_ERR(folio); } - f2fs_ra_node_pages(folio, ofs, NIDS_PER_BLOCK); + f2fs_ra_node_pages(folio, ofs, NIDS_PER_BLOCK(sbi)); rn = F2FS_NODE(folio); if (depth < 3) { - for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { + for (i = ofs; i < NIDS_PER_BLOCK(sbi); i++, freed++) { child_nid = le32_to_cpu(rn->in.nid[i]); if (child_nid == 0) continue; @@ -1088,16 +1095,16 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, dn->node_changed = true; } } else { - child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; - for (i = ofs; i < NIDS_PER_BLOCK; i++) { + child_nofs = nofs + ofs * (NIDS_PER_BLOCK(sbi) + 1) + 1; + for (i = ofs; i < NIDS_PER_BLOCK(sbi); i++) { child_nid = le32_to_cpu(rn->in.nid[i]); if (child_nid == 0) { - child_nofs += NIDS_PER_BLOCK + 1; + child_nofs += NIDS_PER_BLOCK(sbi) + 1; continue; } rdn.nid = child_nid; ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); - if (ret == (NIDS_PER_BLOCK + 1)) { + if (ret == (NIDS_PER_BLOCK(sbi) + 1)) { if (set_nid(folio, i, 0, false)) dn->node_changed = true; child_nofs += ret; @@ -1154,10 +1161,12 @@ static int truncate_partial_nodes(struct dnode_of_data *dn, nid[i + 1] = get_nid(folios[i], offset[i + 1], false); } - f2fs_ra_node_pages(folios[idx], offset[idx + 1], NIDS_PER_BLOCK); + f2fs_ra_node_pages(folios[idx], offset[idx + 1], + NIDS_PER_BLOCK(F2FS_I_SB(dn->inode))); /* free direct nodes linked to a partial indirect node */ - for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) { + for (i = offset[idx + 1]; + i < NIDS_PER_BLOCK(F2FS_I_SB(dn->inode)); i++) { child_nid = get_nid(folios[idx], i, false); if (!child_nid) continue; @@ -1191,7 +1200,9 @@ fail: } /* - * All the block addresses of data and nodes should be nullified. + * All the node blocks actually belong to the inode will be released. + * If the level is 0, we will simply truncate the dnode, + * or else we should do dynamic truncate for the node pointers with the depth. */ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) { @@ -1238,10 +1249,10 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) err = truncate_partial_nodes(&dn, offset, level); if (err < 0 && err != -ENOENT) goto fail; - nofs += 1 + NIDS_PER_BLOCK; + nofs += 1 + NIDS_PER_BLOCK(sbi); break; case 3: - nofs = 5 + 2 * NIDS_PER_BLOCK; + nofs = 5 + 2 * NIDS_PER_BLOCK(sbi); if (!offset[level - 1]) goto skip_partial; err = truncate_partial_nodes(&dn, offset, level); @@ -1255,23 +1266,16 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) skip_partial: while (cont) { dn.nid = get_nid(folio, offset[0], true); - switch (offset[0]) { - case NODE_DIR1_BLOCK: - case NODE_DIR2_BLOCK: + if (offset[0] == NODE_DIR1_BLOCK(sbi) || + offset[0] == NODE_DIR2_BLOCK(sbi)) { err = truncate_dnode(&dn); - break; - - case NODE_IND1_BLOCK: - case NODE_IND2_BLOCK: + } else if (offset[0] == NODE_IND1_BLOCK(sbi) || + offset[0] == NODE_IND2_BLOCK(sbi)) { err = truncate_nodes(&dn, nofs, offset[1], 2); - break; - - case NODE_DIND_BLOCK: + } else if (offset[0] == NODE_DIND_BLOCK(sbi)) { err = truncate_nodes(&dn, nofs, offset[1], 3); cont = 0; - break; - - default: + } else { BUG(); } if (err == -ENOENT) { @@ -1496,7 +1500,8 @@ static int read_node_folio(struct folio *folio, blk_opf_t op_flags) err = f2fs_submit_page_bio(&fio); if (!err) - f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, FS_NODE_READ_IO, + F2FS_BLKSIZE(sbi)); return err; } @@ -2403,8 +2408,8 @@ static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, bool set, bool build) { struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid); - unsigned int nid_ofs = nid - START_NID(nid); + unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, nid); + unsigned int nid_ofs = nid - f2fs_start_nid(sbi, nid); if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap)) return; @@ -2524,14 +2529,14 @@ static int scan_nat_page(struct f2fs_sb_info *sbi, { struct f2fs_nm_info *nm_i = NM_I(sbi); block_t blk_addr; - unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid); + unsigned int nat_ofs = NAT_BLOCK_OFFSET(sbi, start_nid); int i; __set_bit_le(nat_ofs, nm_i->nat_block_bitmap); - i = start_nid % NAT_ENTRY_PER_BLOCK; + i = start_nid % NAT_ENTRY_PER_BLOCK(sbi); - for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { + for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++, start_nid++) { if (unlikely(start_nid >= nm_i->max_nid)) break; @@ -2587,16 +2592,16 @@ static void scan_free_nid_bits(struct f2fs_sb_info *sbi) continue; if (!nm_i->free_nid_count[i]) continue; - for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) { + for (idx = 0; idx < NAT_ENTRY_PER_BLOCK(sbi); idx++) { idx = find_next_bit_le(nm_i->free_nid_bitmap[i], - NAT_ENTRY_PER_BLOCK, idx); - if (idx >= NAT_ENTRY_PER_BLOCK) + NAT_ENTRY_PER_BLOCK(sbi), idx); + if (idx >= NAT_ENTRY_PER_BLOCK(sbi)) break; - nid = i * NAT_ENTRY_PER_BLOCK + idx; + nid = i * NAT_ENTRY_PER_BLOCK(sbi) + idx; add_free_nid(sbi, nid, true, false); - if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS) + if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS(sbi)) goto out; } } @@ -2617,11 +2622,11 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, if (unlikely(nid >= nm_i->max_nid)) nid = 0; - if (unlikely(nid % NAT_ENTRY_PER_BLOCK)) - nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK; + if (unlikely(nid % NAT_ENTRY_PER_BLOCK(sbi))) + nid = NAT_BLOCK_OFFSET(sbi, nid) * NAT_ENTRY_PER_BLOCK(sbi); /* Enough entries */ - if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) + if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi)) return 0; if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS)) @@ -2631,18 +2636,18 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, /* try to find free nids in free_nid_bitmap */ scan_free_nid_bits(sbi); - if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK) + if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK(sbi)) return 0; } /* readahead nat pages to be scanned */ - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nid), FREE_NID_PAGES, META_NAT, true); f2fs_down_read_trace(&nm_i->nat_tree_lock, &lc); while (1) { - if (!test_bit_le(NAT_BLOCK_OFFSET(nid), + if (!test_bit_le(NAT_BLOCK_OFFSET(sbi, nid), nm_i->nat_block_bitmap)) { struct folio *folio = get_current_nat_folio(sbi, nid); @@ -2668,7 +2673,8 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, } } - nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); + nid += NAT_ENTRY_PER_BLOCK(sbi) - + (nid % NAT_ENTRY_PER_BLOCK(sbi)); if (unlikely(nid >= nm_i->max_nid)) nid = 0; @@ -2684,7 +2690,7 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi, f2fs_up_read_trace(&nm_i->nat_tree_lock, &lc); - f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid), + f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(sbi, nm_i->next_scan_nid), nm_i->ra_nid_pages, META_NAT, false); return 0; @@ -2811,20 +2817,20 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink) struct f2fs_nm_info *nm_i = NM_I(sbi); int nr = nr_shrink; - if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) + if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi)) return 0; if (!mutex_trylock(&nm_i->build_lock)) return 0; - while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) { + while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS(sbi)) { struct free_nid *i, *next; unsigned int batch = SHRINK_NID_BATCH_SIZE; spin_lock(&nm_i->nid_list_lock); list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) { if (!nr_shrink || !batch || - nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS) + nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS(sbi)) break; __remove_free_nid(sbi, i, FREE_NID); kmem_cache_free(free_nid_slab, i); @@ -2916,7 +2922,7 @@ recover_xnid: /* 3: update and set xattr node page dirty */ if (folio) { memcpy(F2FS_NODE(xfolio), F2FS_NODE(folio), - VALID_XATTR_BLOCK_SIZE); + VALID_XATTR_BLOCK_SIZE(inode)); folio_mark_dirty(xfolio); } f2fs_folio_put(xfolio, true); @@ -2998,7 +3004,6 @@ retry: int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum) { - struct f2fs_node *rn; struct f2fs_summary *sum_entry; block_t addr; int i, idx, last_offset, nrpages; @@ -3020,8 +3025,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, if (IS_ERR(folio)) return PTR_ERR(folio); - rn = F2FS_NODE(folio); - sum_entry->nid = rn->footer.nid; + sum_entry->nid = F2FS_NODE_FOOTER(folio)->nid; sum_entry->version = 0; sum_entry->ofs_in_node = 0; sum_entry++; @@ -3074,7 +3078,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi) spin_unlock(&nm_i->nid_list_lock); } - __set_nat_cache_dirty(nm_i, ne, init_dirty); + __set_nat_cache_dirty(sbi, nm_i, ne, init_dirty); } update_nats_in_cursum(journal, -i); up_write(&curseg->journal_rwsem); @@ -3102,7 +3106,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, const struct f2fs_nat_block *nat_blk) { struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK; + unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK(sbi); int valid = 0; int i = 0; @@ -3113,7 +3117,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, valid = 1; i = 1; } - for (; i < NAT_ENTRY_PER_BLOCK; i++) { + for (; i < NAT_ENTRY_PER_BLOCK(sbi); i++) { if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR) valid++; } @@ -3124,7 +3128,7 @@ static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, } __clear_bit_le(nat_index, nm_i->empty_nat_bits); - if (valid == NAT_ENTRY_PER_BLOCK) + if (valid == NAT_ENTRY_PER_BLOCK(sbi)) __set_bit_le(nat_index, nm_i->full_nat_bits); else __clear_bit_le(nat_index, nm_i->full_nat_bits); @@ -3135,7 +3139,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, { struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); struct f2fs_journal *journal = curseg->journal; - nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; + nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK(sbi); bool to_journal = true; struct f2fs_nat_block *nat_blk; struct nat_entry *ne, *cur; @@ -3293,9 +3297,10 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) if (!enabled_nat_bits(sbi, NULL)) return 0; - nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); + nm_i->nat_bits_blocks = F2FS_BLK_ALIGN(sbi, + (nat_bits_bytes << 1) + 8); nm_i->nat_bits = f2fs_kvzalloc(sbi, - F2FS_BLK_TO_BYTES(nm_i->nat_bits_blocks), GFP_KERNEL); + F2FS_BLK_TO_BYTES(sbi, nm_i->nat_bits_blocks), GFP_KERNEL); if (!nm_i->nat_bits) return -ENOMEM; @@ -3308,8 +3313,8 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) if (IS_ERR(folio)) return PTR_ERR(folio); - memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(i), - folio_address(folio), F2FS_BLKSIZE); + memcpy(nm_i->nat_bits + F2FS_BLK_TO_BYTES(sbi, i), + folio_address(folio), F2FS_BLKSIZE(sbi)); f2fs_folio_put(folio, true); } @@ -3342,8 +3347,8 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi) __set_bit_le(i, nm_i->nat_block_bitmap); - nid = i * NAT_ENTRY_PER_BLOCK; - last_nid = nid + NAT_ENTRY_PER_BLOCK; + nid = i * NAT_ENTRY_PER_BLOCK(sbi); + last_nid = nid + NAT_ENTRY_PER_BLOCK(sbi); spin_lock(&NM_I(sbi)->nid_list_lock); for (; nid < last_nid; nid++) @@ -3373,7 +3378,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi) /* segment_count_nat includes pair segment so divide to 2. */ nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); - nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks; + nm_i->max_nid = NAT_ENTRY_PER_BLOCK(sbi) * nm_i->nat_blocks; /* not used nids: 0, node, meta, (and root counted as valid node) */ nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count - @@ -3436,7 +3441,7 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi) for (i = 0; i < nm_i->nat_blocks; i++) { nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi, - f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL); + f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK(sbi)), GFP_KERNEL); if (!nm_i->free_nid_bitmap[i]) return -ENOMEM; } diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 5e114f352099..c265739f2105 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -6,14 +6,21 @@ * http://www.samsung.com/ */ /* start node id of a node block dedicated to the given node id */ -#define START_NID(nid) (((nid) / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK) +static inline nid_t f2fs_start_nid(struct f2fs_sb_info *sbi, nid_t nid) +{ + unsigned int entries = NAT_ENTRY_PER_BLOCK(sbi); + + return (nid / entries) * entries; +} /* node block offset on the NAT area dedicated to the given start node id */ -#define NAT_BLOCK_OFFSET(start_nid) ((start_nid) / NAT_ENTRY_PER_BLOCK) +#define NAT_BLOCK_OFFSET(sbi, start_nid) \ + ((start_nid) / NAT_ENTRY_PER_BLOCK(sbi)) /* # of pages to perform synchronous readahead before building free nids */ #define FREE_NID_PAGES 8 -#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES) +#define MAX_FREE_NIDS(sbi) ((unsigned long)NAT_ENTRY_PER_BLOCK(sbi) * \ + FREE_NID_PAGES) /* size of free nid batch when shrinking */ #define SHRINK_NID_BATCH_SIZE 8 @@ -208,7 +215,7 @@ static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start) * OLD = (segment_off * 512) * 2 + off_in_segment * NEW = 2 * (segment_off * 512 + off_in_segment) - off_in_segment */ - block_off = NAT_BLOCK_OFFSET(start); + block_off = NAT_BLOCK_OFFSET(sbi, start); block_addr = (pgoff_t)(nm_i->nat_blkaddr + (block_off << 1) - @@ -230,9 +237,10 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi, return block_addr + nm_i->nat_blkaddr; } -static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) +static inline void set_to_next_nat(struct f2fs_sb_info *sbi, + struct f2fs_nm_info *nm_i, nid_t start_nid) { - unsigned int block_off = NAT_BLOCK_OFFSET(start_nid); + unsigned int block_off = NAT_BLOCK_OFFSET(sbi, start_nid); f2fs_change_bit(block_off, nm_i->nat_bitmap); #ifdef CONFIG_F2FS_CHECK_FS @@ -242,73 +250,68 @@ static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) static inline nid_t ino_of_node(const struct folio *node_folio) { - struct f2fs_node *rn = F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.ino); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino); } static inline nid_t nid_of_node(const struct folio *node_folio) { - struct f2fs_node *rn = F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.nid); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid); } static inline unsigned int ofs_of_node(const struct folio *node_folio) { - struct f2fs_node *rn = F2FS_NODE(node_folio); - unsigned flag = le32_to_cpu(rn->footer.flag); + unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag); return flag >> OFFSET_BIT_SHIFT; } static inline __u64 cpver_of_node(const struct folio *node_folio) { - struct f2fs_node *rn = F2FS_NODE(node_folio); - return le64_to_cpu(rn->footer.cp_ver); + return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver); } static inline block_t next_blkaddr_of_node(const struct folio *node_folio) { - struct f2fs_node *rn = F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.next_blkaddr); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr); } static inline void fill_node_footer(const struct folio *folio, nid_t nid, nid_t ino, unsigned int ofs, bool reset) { struct f2fs_node *rn = F2FS_NODE(folio); + struct node_footer *footer = F2FS_NODE_FOOTER(folio); unsigned int old_flag = 0; if (reset) - memset(rn, 0, sizeof(*rn)); + memset(rn, 0, F2FS_BLKSIZE(F2FS_F_SB(folio))); else - old_flag = le32_to_cpu(rn->footer.flag); + old_flag = le32_to_cpu(footer->flag); - rn->footer.nid = cpu_to_le32(nid); - rn->footer.ino = cpu_to_le32(ino); + footer->nid = cpu_to_le32(nid); + footer->ino = cpu_to_le32(ino); /* should remain old flag bits such as COLD_BIT_SHIFT */ - rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | + footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | (old_flag & OFFSET_BIT_MASK)); } static inline void copy_node_footer(const struct folio *dst, const struct folio *src) { - struct f2fs_node *src_rn = F2FS_NODE(src); - struct f2fs_node *dst_rn = F2FS_NODE(dst); - memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); + memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src), + sizeof(struct node_footer)); } static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr) { struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio)); - struct f2fs_node *rn = F2FS_NODE(folio); + struct node_footer *footer = F2FS_NODE_FOOTER(folio); __u64 cp_ver = cur_cp_version(ckpt); if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) cp_ver |= (cur_cp_crc(ckpt) << 32); - rn->footer.cp_ver = cpu_to_le64(cp_ver); - rn->footer.next_blkaddr = cpu_to_le32(blkaddr); + footer->cp_ver = cpu_to_le64(cp_ver); + footer->next_blkaddr = cpu_to_le32(blkaddr); } static inline bool is_recoverable_dnode(const struct folio *folio) @@ -349,17 +352,18 @@ static inline bool is_recoverable_dnode(const struct folio *folio) */ static inline bool IS_DNODE(const struct folio *node_folio) { + struct f2fs_sb_info *sbi = F2FS_F_SB(node_folio); unsigned int ofs = ofs_of_node(node_folio); if (f2fs_has_xattr_block(ofs)) return true; - if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || - ofs == 5 + 2 * NIDS_PER_BLOCK) + if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK(sbi) || + ofs == 5 + 2 * NIDS_PER_BLOCK(sbi)) return false; - if (ofs >= 6 + 2 * NIDS_PER_BLOCK) { - ofs -= 6 + 2 * NIDS_PER_BLOCK; - if (!((long int)ofs % (NIDS_PER_BLOCK + 1))) + if (ofs >= 6 + 2 * NIDS_PER_BLOCK(sbi)) { + ofs -= 6 + 2 * NIDS_PER_BLOCK(sbi); + if (!((long)ofs % (NIDS_PER_BLOCK(sbi) + 1))) return false; } return true; @@ -367,12 +371,15 @@ static inline bool IS_DNODE(const struct folio *node_folio) static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) { + struct f2fs_sb_info *sbi = F2FS_F_SB(folio); struct f2fs_node *rn = F2FS_NODE(folio); + __le32 *inode_nids = F2FS_INODE_NIDS(folio); f2fs_folio_wait_writeback(folio, NODE, true, true); if (i) - rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); + inode_nids[off - NODE_DIR1_BLOCK(sbi)] = + cpu_to_le32(nid); else rn->in.nid[off] = cpu_to_le32(nid); return folio_mark_dirty(folio); @@ -381,9 +388,11 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) static inline nid_t get_nid(const struct folio *folio, int off, bool i) { struct f2fs_node *rn = F2FS_NODE(folio); + const __le32 *inode_nids = F2FS_INODE_NIDS(folio); + int nid_index = off - NODE_DIR1_BLOCK(F2FS_F_SB(folio)); if (i) - return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); + return le32_to_cpu(inode_nids[nid_index]); return le32_to_cpu(rn->in.nid[off]); } @@ -396,8 +405,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i) static inline int is_node(const struct folio *folio, int type) { - struct f2fs_node *rn = F2FS_NODE(folio); - return le32_to_cpu(rn->footer.flag) & BIT(type); + return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type); } #define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT) @@ -406,14 +414,13 @@ static inline int is_node(const struct folio *folio, int type) static inline void __set_mark(const struct folio *folio, bool mark, int type) { - struct f2fs_node *rn = F2FS_NODE(folio); - unsigned int flag = le32_to_cpu(rn->footer.flag); - + struct node_footer *footer = F2FS_NODE_FOOTER(folio); + unsigned int flag = le32_to_cpu(footer->flag); if (mark) flag |= BIT(type); else flag &= ~BIT(type); - rn->footer.flag = cpu_to_le32(flag); + footer->flag = cpu_to_le32(flag); } static inline void set_cold_node(const struct folio *folio, bool is_dir) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index aaa5227739c8..b52718741ddc 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -734,9 +734,9 @@ retry_dn: } if (!file_keep_isize(inode) && - (i_size_read(inode) <= ((loff_t)index << PAGE_SHIFT))) + (i_size_read(inode) <= F2FS_BLK_TO_BYTES(sbi, index))) f2fs_i_size_write(inode, - (loff_t)(index + 1) << PAGE_SHIFT); + F2FS_BLK_TO_BYTES(sbi, index + 1)); /* * dest is reserved block, invalidate src block diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 63b712d3d599..2d0f49745626 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -512,10 +512,10 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) /* check the # of cached NAT entries */ if (!f2fs_available_free_memory(sbi, NAT_ENTRIES)) - f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK); + f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK(sbi)); if (!f2fs_available_free_memory(sbi, FREE_NIDS)) - f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS); + f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS(sbi)); else f2fs_build_free_nids(sbi, false, false); @@ -1310,13 +1310,14 @@ static void __submit_zone_reset_cmd(struct f2fs_sb_info *sbi, /* sanity check on discard range */ __check_sit_bitmap(sbi, dc->di.lstart, dc->di.lstart + dc->di.len); - bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(dc->di.start); + bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, dc->di.start); bio->bi_private = dc; bio->bi_end_io = f2fs_submit_discard_endio; submit_bio(bio); atomic_inc(&dcc->issued_discard); - f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO, dc->di.len * F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, FS_ZONE_RESET_IO, + dc->di.len * F2FS_BLKSIZE(sbi)); } #endif @@ -1327,7 +1328,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, { struct block_device *bdev = dc->bdev; unsigned int max_discard_blocks = - SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); + SECTOR_TO_BLOCK(sbi, bdev_max_discard_sectors(bdev)); struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; struct list_head *wait_list = (dpolicy->type == DPOLICY_FSTRIM) ? &(dcc->fstrim_list) : &(dcc->wait_list); @@ -1389,8 +1390,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, dc->di.len += len; - __blkdev_issue_discard(bdev, SECTOR_FROM_BLOCK(start), - SECTOR_FROM_BLOCK(len), GFP_NOFS, &bio); + __blkdev_issue_discard(bdev, SECTOR_FROM_BLOCK(sbi, start), + SECTOR_FROM_BLOCK(sbi, len), GFP_NOFS, &bio); f2fs_bug_on(sbi, !bio); /* @@ -1419,7 +1420,8 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, atomic_inc(&dcc->issued_discard); - f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO, len * F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, FS_DISCARD_IO, + len * F2FS_BLKSIZE(sbi)); lstart += len; start += len; @@ -1518,7 +1520,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi, struct discard_info di = {0}; struct rb_node **insert_p = NULL, *insert_parent = NULL; unsigned int max_discard_blocks = - SECTOR_TO_BLOCK(bdev_max_discard_sectors(bdev)); + SECTOR_TO_BLOCK(sbi, bdev_max_discard_sectors(bdev)); block_t end = lstart + len; dc = __lookup_discard_cmd_ret(&dcc->root, lstart, @@ -1871,6 +1873,60 @@ static unsigned int __wait_all_discard_cmd(struct f2fs_sb_info *sbi, return discard_blks; } +void f2fs_drop_discard_cmd_range(struct f2fs_sb_info *sbi, + block_t start, block_t len) +{ + struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info; + struct discard_cmd *prev_dc = NULL, *next_dc = NULL; + struct rb_node **insert_p = NULL, *insert_parent = NULL; + struct discard_cmd *dc, *wait_dc; + u64 cur = start; + u64 end = (u64)start + len; + int count; + + if (!f2fs_realtime_discard_enable(sbi)) + return; + +next: + count = 0; + wait_dc = NULL; + + mutex_lock(&dcc->cmd_lock); + while (cur < end) { + dc = __lookup_discard_cmd_ret(&dcc->root, cur, + &prev_dc, &next_dc, &insert_p, &insert_parent); + if (!dc) + dc = next_dc; + + if (!dc || (u64)dc->di.lstart >= end) + break; + + if (dc->state == D_PREP) { + cur = (u64)dc->di.lstart + dc->di.len; + __remove_discard_cmd(sbi, dc); + if (++count >= MAX_DISCARD_DROP_COUNT) + break; + continue; + } + + dc->ref++; + cur = (u64)dc->di.lstart + dc->di.len; + wait_dc = dc; + break; + } + mutex_unlock(&dcc->cmd_lock); + + if (wait_dc) { + __wait_one_discard_bio(sbi, wait_dc); + goto next; + } + + if (count >= MAX_DISCARD_DROP_COUNT) { + cond_resched(); + goto next; + } +} + /* This should be covered by global mutex, &sit_i->sentry_lock */ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr) { @@ -2041,8 +2097,8 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi, /* For sequential zones, reset the zone write pointer */ if (f2fs_blkz_is_seq(sbi, devi, blkstart)) { - sector = SECTOR_FROM_BLOCK(blkstart); - nr_sects = SECTOR_FROM_BLOCK(blklen); + sector = SECTOR_FROM_BLOCK(sbi, blkstart); + nr_sects = SECTOR_FROM_BLOCK(sbi, blklen); div64_u64_rem(sector, bdev_zone_sectors(bdev), &remainder); if (remainder || nr_sects != bdev_zone_sectors(bdev)) { @@ -2797,7 +2853,7 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi, if (IS_ERR(folio)) return; - memcpy(folio_address(folio), src, PAGE_SIZE); + memcpy(folio_address(folio), src, F2FS_BLKSIZE(sbi)); folio_mark_dirty(folio); f2fs_folio_put(folio, true); } @@ -3592,8 +3648,8 @@ skip: int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) { - __u64 start = F2FS_BYTES_TO_BLK(range->start); - __u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1; + __u64 start = F2FS_BYTES_TO_BLK(sbi, range->start); + __u64 end = start + F2FS_BYTES_TO_BLK(sbi, range->len) - 1; unsigned int start_segno, end_segno; block_t start_block, end_block; struct cp_control cpc; @@ -3624,7 +3680,8 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) } cpc.reason = CP_DISCARD; - cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen)); + cpc.trim_minlen = max_t(__u64, 1, + F2FS_BYTES_TO_BLK(sbi, range->minlen)); cpc.trim_start = start_segno; cpc.trim_end = end_segno; @@ -3658,7 +3715,7 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range) start_block, end_block); out: if (!err) - range->len = F2FS_BLK_TO_BYTES(trimmed); + range->len = F2FS_BLK_TO_BYTES(sbi, trimmed); return err; } @@ -4149,7 +4206,7 @@ void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct folio *folio, f2fs_submit_page_write(&fio); stat_inc_meta_count(sbi, folio->index); - f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, NULL, io_type, F2FS_BLKSIZE(sbi)); } void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio) @@ -4159,7 +4216,8 @@ void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio) set_summary(&sum, nid, 0, 0); do_write_page(&sum, fio); - f2fs_update_iostat(fio->sbi, NULL, fio->io_type, F2FS_BLKSIZE); + f2fs_update_iostat(fio->sbi, NULL, fio->io_type, + F2FS_BLKSIZE(fio->sbi)); } void f2fs_outplace_write_data(struct dnode_of_data *dn, @@ -4175,7 +4233,8 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn, do_write_page(&sum, fio); f2fs_update_data_blkaddr(dn, fio->new_blkaddr); - f2fs_update_iostat(sbi, dn->inode, fio->io_type, F2FS_BLKSIZE); + f2fs_update_iostat(sbi, dn->inode, fio->io_type, + F2FS_BLKSIZE(sbi)); } int f2fs_inplace_write_data(struct f2fs_io_info *fio) @@ -4217,7 +4276,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio) f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1); f2fs_update_iostat(fio->sbi, fio_inode(fio), - fio->io_type, F2FS_BLKSIZE); + fio->io_type, F2FS_BLKSIZE(fio->sbi)); } return err; @@ -4706,7 +4765,7 @@ static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi, seg_info_to_sit_folio(sbi, folio, start); folio_mark_dirty(folio); - set_to_next_sit(sit_i, start); + set_to_next_sit(sbi, sit_i, start); return folio; } @@ -4745,10 +4804,11 @@ static void adjust_sit_entry_set(struct sit_entry_set *ses, list_move_tail(&ses->set_list, head); } -static void add_sit_entry(unsigned int segno, struct list_head *head) +static void add_sit_entry(struct f2fs_sb_info *sbi, unsigned int segno, + struct list_head *head) { struct sit_entry_set *ses; - unsigned int start_segno = START_SEGNO(segno); + unsigned int start_segno = f2fs_start_segno(sbi, segno); list_for_each_entry(ses, head, set_list) { if (ses->start_segno == start_segno) { @@ -4773,7 +4833,7 @@ static void add_sits_in_set(struct f2fs_sb_info *sbi) unsigned int segno; for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi)) - add_sit_entry(segno, set_list); + add_sit_entry(sbi, segno, set_list); } static void remove_sits_in_journal(struct f2fs_sb_info *sbi) @@ -4791,7 +4851,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info *sbi) dirtied = __mark_sit_entry_dirty(sbi, segno); if (!dirtied) - add_sit_entry(segno, &SM_I(sbi)->sit_entry_set); + add_sit_entry(sbi, segno, &SM_I(sbi)->sit_entry_set); } update_sits_in_cursum(journal, -i); up_write(&curseg->journal_rwsem); @@ -4841,7 +4901,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) struct folio *folio = NULL; struct f2fs_sit_block *raw_sit = NULL; unsigned int start_segno = ses->start_segno; - unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK, + unsigned int end = min(start_segno + SIT_ENTRY_PER_BLOCK(sbi), (unsigned long)MAIN_SEGS(sbi)); unsigned int segno = start_segno; @@ -5006,7 +5066,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi) sit_i->written_valid_blocks = 0; sit_i->bitmap_size = sit_bitmap_size; sit_i->dirty_sentries = 0; - sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; + sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK(sbi); sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time); sit_i->mounted_time = ktime_get_boottime_seconds(); init_rwsem(&sit_i->sentry_lock); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 5949aa5200ac..cc0428b614da 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -102,19 +102,22 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, #define SIT_ENTRY_OFFSET(sit_i, segno) \ ((segno) % (sit_i)->sents_per_block) -#define SIT_BLOCK_OFFSET(segno) \ - ((segno) / SIT_ENTRY_PER_BLOCK) -#define START_SEGNO(segno) \ - (SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK) +#define SIT_BLOCK_OFFSET(sbi, segno) \ + ((segno) / SIT_ENTRY_PER_BLOCK(sbi)) +static inline unsigned int +f2fs_start_segno(struct f2fs_sb_info *sbi, unsigned int segno) +{ + return SIT_BLOCK_OFFSET(sbi, segno) * SIT_ENTRY_PER_BLOCK(sbi); +} #define SIT_BLK_CNT(sbi) \ - DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK) + DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK(sbi)) #define f2fs_bitmap_size(nr) \ (BITS_TO_LONGS(nr) * sizeof(unsigned long)) -#define SECTOR_FROM_BLOCK(blk_addr) \ - (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK) -#define SECTOR_TO_BLOCK(sectors) \ - ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK) +#define SECTOR_FROM_BLOCK(sbi, blk_addr) \ + (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK(sbi)) +#define SECTOR_TO_BLOCK(sbi, sectors) \ + ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK(sbi)) /* * In the victim_sel_policy->alloc_mode, there are three block allocation modes. @@ -424,12 +427,12 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi, struct f2fs_sit_block *raw_sit; struct seg_entry *se; struct f2fs_sit_entry *rs; - unsigned int end = min(start + SIT_ENTRY_PER_BLOCK, + unsigned int end = min(start + SIT_ENTRY_PER_BLOCK(sbi), (unsigned long)MAIN_SEGS(sbi)); int i; raw_sit = folio_address(folio); - memset(raw_sit, 0, PAGE_SIZE); + memset(raw_sit, 0, F2FS_BLKSIZE(sbi)); for (i = 0; i < end - start; i++) { rs = &raw_sit->entries[i]; se = get_seg_entry(sbi, start + i); @@ -869,7 +872,7 @@ static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, unsigned int start) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int offset = SIT_BLOCK_OFFSET(start); + unsigned int offset = SIT_BLOCK_OFFSET(sbi, start); block_t blk_addr = sit_i->sit_base_addr + offset; f2fs_bug_on(sbi, !valid_main_segno(sbi, start)); @@ -894,9 +897,10 @@ static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, return block_addr + sit_i->sit_base_addr; } -static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) +static inline void set_to_next_sit(struct f2fs_sb_info *sbi, + struct sit_info *sit_i, unsigned int start) { - unsigned int block_off = SIT_BLOCK_OFFSET(start); + unsigned int block_off = SIT_BLOCK_OFFSET(sbi, start); f2fs_change_bit(block_off, sit_i->sit_bitmap); } diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 4f6bf5926de4..e3e0a7e89406 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -23,7 +23,7 @@ static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi) static unsigned long __count_free_nids(struct f2fs_sb_info *sbi) { - long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS; + long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS(sbi); return count > 0 ? count : 0; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1314b6ccced9..f96abecb3c55 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -855,9 +855,11 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param) break; case Opt_inline_xattr_size: if (result.int_32 < MIN_INLINE_XATTR_SIZE || - result.int_32 > MAX_INLINE_XATTR_SIZE) { + result.int_32 > + MAX_INLINE_XATTR_SIZE(F2FS_MAX_BLKSIZE)) { f2fs_err(NULL, "inline xattr size is out of range: %u ~ %u", - (u32)MIN_INLINE_XATTR_SIZE, (u32)MAX_INLINE_XATTR_SIZE); + (u32)MIN_INLINE_XATTR_SIZE, + (u32)MAX_INLINE_XATTR_SIZE(F2FS_MAX_BLKSIZE)); return -EINVAL; } ctx_set_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE); @@ -1596,6 +1598,8 @@ static int f2fs_check_opt_consistency(struct fs_context *fc, } if (ctx_test_opt(ctx, F2FS_MOUNT_INLINE_XATTR_SIZE)) { + int min_size, max_size; + if (!f2fs_sb_has_extra_attr(sbi) || !f2fs_sb_has_flexible_inline_xattr(sbi)) { f2fs_err(sbi, "extra_attr or flexible_inline_xattr feature is off"); @@ -1605,6 +1609,15 @@ static int f2fs_check_opt_consistency(struct fs_context *fc, f2fs_err(sbi, "inline_xattr_size option should be set with inline_xattr option"); return -EINVAL; } + min_size = MIN_INLINE_XATTR_SIZE; + max_size = MAX_INLINE_XATTR_SIZE(F2FS_BLKSIZE(sbi)); + + if (F2FS_OPTION(sbi).inline_xattr_size < min_size || + F2FS_OPTION(sbi).inline_xattr_size > max_size) { + f2fs_err(sbi, "inline xattr size is out of range: %d ~ %d", + min_size, max_size); + return -EINVAL; + } } if (ctx_test_opt(ctx, F2FS_MOUNT_ATGC) && @@ -3871,13 +3884,13 @@ static const struct export_operations f2fs_export_ops = { .get_parent = f2fs_get_parent, }; -loff_t max_file_blocks(struct inode *inode) +loff_t max_file_blocks(struct f2fs_sb_info *sbi, struct inode *inode) { loff_t result = 0; loff_t leaf_count; /* - * note: previously, result is equal to (DEF_ADDRS_PER_INODE - + * note: previously, result is equal to (DEF_ADDRS_PER_INODE(sbi) - * DEFAULT_INLINE_XATTR_ADDRS), but now f2fs try to reserve more * space in inode.i_addr, it will be more safe to reassign * result as zero. @@ -3886,17 +3899,17 @@ loff_t max_file_blocks(struct inode *inode) if (inode && f2fs_compressed_file(inode)) leaf_count = ADDRS_PER_BLOCK(inode); else - leaf_count = DEF_ADDRS_PER_BLOCK; + leaf_count = DEF_ADDRS_PER_BLOCK(sbi); /* two direct node blocks */ result += (leaf_count * 2); /* two indirect node blocks */ - leaf_count *= NIDS_PER_BLOCK; + leaf_count *= NIDS_PER_BLOCK(sbi); result += (leaf_count * 2); /* one double indirect node block */ - leaf_count *= NIDS_PER_BLOCK; + leaf_count *= NIDS_PER_BLOCK(sbi); result += leaf_count; /* @@ -3905,7 +3918,8 @@ loff_t max_file_blocks(struct inode *inode) * fit within U32_MAX + 1 data units. */ - result = umin(result, F2FS_BYTES_TO_BLK(((loff_t)U32_MAX + 1) * 4096)); + result = umin(result, F2FS_BYTES_TO_BLK(sbi, + ((loff_t)U32_MAX + 1) * 4096)); return result; } @@ -3931,7 +3945,7 @@ static int __f2fs_commit_super(struct f2fs_sb_info *sbi, struct folio *folio, bio = bio_alloc(sbi->sb->s_bdev, 1, opf, GFP_NOFS); /* it doesn't need to set crypto context for superblock update */ - bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(folio->index); + bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, folio->index); if (!bio_add_folio(bio, folio, folio_size(folio), 0)) f2fs_bug_on(sbi, 1); @@ -4065,10 +4079,10 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, } /* only support block_size equals to PAGE_SIZE */ - if (le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE_BITS) { + if (le32_to_cpu(raw_super->log_blocksize) != PAGE_SHIFT) { f2fs_info(sbi, "Invalid log_blocksize (%u), supports only %u", le32_to_cpu(raw_super->log_blocksize), - F2FS_BLKSIZE_BITS); + PAGE_SHIFT); return -EFSCORRUPTED; } @@ -4329,7 +4343,7 @@ skip_cross: return 1; } - sit_blk_cnt = DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK); + sit_blk_cnt = DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK(sbi)); if (sit_bitmap_size * 8 < sit_blk_cnt) { f2fs_err(sbi, "Wrong bitmap size: sit: %u, sit_blk_cnt:%u", sit_bitmap_size, sit_blk_cnt); @@ -4357,7 +4371,7 @@ skip_cross: nat_blocks = nat_segs << log_blocks_per_seg; nat_bits_bytes = nat_blocks / BITS_PER_BYTE; - nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); + nat_bits_blocks = F2FS_BLK_ALIGN(sbi, (nat_bits_bytes << 1) + 8); if (__is_set_ckpt_flags(ckpt, CP_NAT_BITS_FLAG) && (cp_payload + F2FS_CP_PACKS + NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) { @@ -4382,6 +4396,22 @@ static void init_sb_info(struct f2fs_sb_info *sbi) le32_to_cpu(raw_super->log_sectors_per_block); sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize); sbi->blocksize = BIT(sbi->log_blocksize); + sbi->nat_entries_per_block = sbi->blocksize / + sizeof(struct f2fs_nat_entry); + sbi->addrs_per_inode = F2FS_DEF_ADDRS_PER_INODE(sbi->blocksize); + sbi->addrs_per_block = (sbi->blocksize - + sizeof(struct node_footer)) / sizeof(__le32); + sbi->nids_per_block = sbi->addrs_per_block; + sbi->sit_entries_per_block = sbi->blocksize / + sizeof(struct f2fs_sit_entry); + sbi->orphans_per_block = (sbi->blocksize - + sizeof(struct f2fs_orphan_footer)) / sizeof(__le32); + sbi->dentries_per_block = (BITS_PER_BYTE * sbi->blocksize) / + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1); + sbi->dentry_bitmap_size = DIV_ROUND_UP(sbi->dentries_per_block, + BITS_PER_BYTE); + sbi->dentry_reserved_size = sbi->blocksize - sbi->dentry_bitmap_size - + (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * sbi->dentries_per_block; sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); sbi->blocks_per_seg = BIT(sbi->log_blocks_per_seg); sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); @@ -4389,7 +4419,7 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sbi->total_sections = le32_to_cpu(raw_super->section_count); sbi->total_node_count = SEGS_TO_BLKS(sbi, ((le32_to_cpu(raw_super->segment_count_nat) / 2) * - NAT_ENTRY_PER_BLOCK)); + NAT_ENTRY_PER_BLOCK(sbi))); sbi->allocate_section_hint = le32_to_cpu(raw_super->section_count); sbi->allocate_section_policy = ALLOCATE_FORWARD_NOHINT; F2FS_ROOT_INO(sbi) = le32_to_cpu(raw_super->root_ino); @@ -4490,7 +4520,7 @@ static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx, { struct f2fs_report_zones_args *rz_args = data; block_t unusable_blocks = (zone->len - zone->capacity) >> - F2FS_LOG_SECTORS_PER_BLOCK; + F2FS_LOG_SECTORS_PER_BLOCK(rz_args->sbi); if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL) return 0; @@ -4533,10 +4563,10 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) zone_sectors = bdev_zone_sectors(bdev); if (sbi->blocks_per_blkz && sbi->blocks_per_blkz != - SECTOR_TO_BLOCK(zone_sectors)) + SECTOR_TO_BLOCK(sbi, zone_sectors)) return -EINVAL; - sbi->blocks_per_blkz = SECTOR_TO_BLOCK(zone_sectors); - FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(nr_sectors), + sbi->blocks_per_blkz = SECTOR_TO_BLOCK(sbi, zone_sectors); + FDEV(devi).nr_blkz = div_u64(SECTOR_TO_BLOCK(sbi, nr_sectors), sbi->blocks_per_blkz); if (nr_sectors & (zone_sectors - 1)) FDEV(devi).nr_blkz++; @@ -5125,12 +5155,6 @@ try_onemore: } mutex_init(&sbi->flush_lock); - /* set a block size */ - if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) { - f2fs_err(sbi, "unable to set blocksize"); - goto free_sbi; - } - err = read_raw_super_block(sbi, &raw_super, &valid_super_block, &recovery); if (err) @@ -5138,6 +5162,14 @@ try_onemore: sb->s_fs_info = sbi; sbi->raw_super = raw_super; + init_sb_info(sbi); + + /* set a block size */ + if (unlikely(!sb_set_blocksize(sb, sbi->blocksize))) { + f2fs_err(sbi, "unable to set blocksize %u", sbi->blocksize); + err = -EINVAL; + goto free_sb_buf; + } sbi->max_atc_write_bio_size = UINT_MAX; INIT_WORK(&sbi->s_error_work, f2fs_record_error_work); @@ -5161,7 +5193,7 @@ try_onemore: if (err) goto free_options; - sb->s_maxbytes = max_file_blocks(NULL) << + sb->s_maxbytes = max_file_blocks(sbi, NULL) << le32_to_cpu(raw_super->log_blocksize); sb->s_max_links = F2FS_LINK_MAX; @@ -5217,8 +5249,6 @@ try_onemore: if (err) goto free_bio_info; - init_sb_info(sbi); - err = f2fs_init_iostat(sbi); if (err) goto free_bio_info; diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index 811e350a1430..aaca9ed9b169 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -1871,8 +1871,8 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq, struct f2fs_sb_info *sbi = F2FS_SB(sb); int i; - seq_printf(seq, "Address Layout : %5luB Block address (# of Segments)\n", - F2FS_BLKSIZE); + seq_printf(seq, "Address Layout : %5uB Block address (# of Segments)\n", + F2FS_BLKSIZE(sbi)); seq_printf(seq, " SB : %12s\n", "0/1024B"); seq_printf(seq, " seg0_blkaddr : 0x%010x\n", SEG0_BLKADDR(sbi)); seq_printf(seq, " Checkpoint : 0x%010x (%10d)\n", @@ -1889,13 +1889,13 @@ static int __maybe_unused disk_map_seq_show(struct seq_file *seq, seq_printf(seq, " Main : 0x%010x (%10d)\n", SM_I(sbi)->main_blkaddr, le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count_main)); - seq_printf(seq, " Block size : %12lu KB\n", F2FS_BLKSIZE >> 10); + seq_printf(seq, " Block size : %12u KB\n", F2FS_BLKSIZE(sbi) >> 10); seq_printf(seq, " Segment size : %12d MB\n", - (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10); + (BLKS_PER_SEG(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10); seq_printf(seq, " Segs/Sections : %12d\n", SEGS_PER_SEC(sbi)); seq_printf(seq, " Section size : %12d MB\n", - (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS - 10)) >> 10); + (BLKS_PER_SEC(sbi) << (F2FS_BLKSIZE_BITS(sbi) - 10)) >> 10); seq_printf(seq, " # of Sections : %12d\n", le32_to_cpu(F2FS_RAW_SUPER(sbi)->section_count)); diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index 39f482515445..ee838f880c4a 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -75,7 +75,8 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count, struct address_space *mapping = inode->i_mapping; const struct address_space_operations *aops = mapping->a_ops; - if (pos + count > F2FS_BLK_TO_BYTES(max_file_blocks(inode))) + if (pos + count > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), + max_file_blocks(F2FS_I_SB(inode), inode))) return -EFBIG; while (count) { @@ -239,7 +240,8 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf, /* Get the descriptor */ if (pos + size < pos || - pos + size > F2FS_BLK_TO_BYTES(max_file_blocks(inode)) || + pos + size > F2FS_BLK_TO_BYTES(F2FS_I_SB(inode), + max_file_blocks(F2FS_I_SB(inode), inode)) || pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) { f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr"); f2fs_handle_error(F2FS_I_SB(inode), diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 6728d1488cad..98059e583b09 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -310,7 +310,8 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr) return PTR_ERR(xfolio); xattr_addr = folio_address(xfolio); - memcpy(txattr_addr + inline_size, xattr_addr, VALID_XATTR_BLOCK_SIZE); + memcpy(txattr_addr + inline_size, xattr_addr, + VALID_XATTR_BLOCK_SIZE(inode)); f2fs_folio_put(xfolio, true); return 0; @@ -393,7 +394,7 @@ static int read_all_xattrs(struct inode *inode, struct folio *ifolio, { struct f2fs_xattr_header *header; nid_t xnid = F2FS_I(inode)->i_xattr_nid; - unsigned int size = VALID_XATTR_BLOCK_SIZE; + unsigned int size = VALID_XATTR_BLOCK_SIZE(inode); unsigned int inline_size = inline_xattr_size(inode); void *txattr_addr; int err; @@ -502,7 +503,8 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, if (inline_size) memcpy(inline_addr, txattr_addr, inline_size); - memcpy(xattr_addr, txattr_addr + inline_size, VALID_XATTR_BLOCK_SIZE); + memcpy(xattr_addr, txattr_addr + inline_size, + VALID_XATTR_BLOCK_SIZE(inode)); if (inline_size) folio_mark_dirty(ifolio ? ifolio : in_folio); @@ -848,4 +850,4 @@ int __init f2fs_init_xattr_cache(void) void f2fs_destroy_xattr_cache(void) { kmem_cache_destroy(inline_xattr_slab); -}
\ No newline at end of file +} diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index bce3d93e4755..75beab2d1ee3 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -71,21 +71,22 @@ struct f2fs_xattr_entry { for (entry = XATTR_FIRST_ENTRY(addr);\ !IS_XATTR_LAST_ENTRY(entry);\ entry = XATTR_NEXT_ENTRY(entry)) -#define VALID_XATTR_BLOCK_SIZE (PAGE_SIZE - sizeof(struct node_footer)) +#define VALID_XATTR_BLOCK_SIZE(i) (i_blocksize(i) - \ + sizeof(struct node_footer)) #define XATTR_PADDING_SIZE (sizeof(__u32)) #define XATTR_SIZE(i) ((F2FS_I(i)->i_xattr_nid ? \ - VALID_XATTR_BLOCK_SIZE : 0) + \ + VALID_XATTR_BLOCK_SIZE(i) : 0) + \ (inline_xattr_size(i))) #define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + \ - VALID_XATTR_BLOCK_SIZE) + VALID_XATTR_BLOCK_SIZE(i)) #define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \ sizeof(struct f2fs_xattr_header) - \ sizeof(struct f2fs_xattr_entry)) #define MIN_INLINE_XATTR_SIZE (sizeof(struct f2fs_xattr_header) / sizeof(__le32)) -#define MAX_INLINE_XATTR_SIZE \ - (DEF_ADDRS_PER_INODE - \ +#define MAX_INLINE_XATTR_SIZE(blocksize) \ + (F2FS_DEF_ADDRS_PER_INODE(blocksize) - \ F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \ DEF_INLINE_RESERVED_SIZE - \ MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index bb2b6cd5d507..92a11e984d7a 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -14,9 +14,9 @@ #define F2FS_SUPER_OFFSET 1024 /* byte-size offset */ #define F2FS_MIN_LOG_SECTOR_SIZE 9 /* 9 bits for 512 bytes */ #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */ -#define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ -#define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */ -#define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ +#define F2FS_MIN_LOG_BLOCKSIZE 12 +#define F2FS_MIN_BLKSIZE 4096UL +#define F2FS_MAX_BLKSIZE PAGE_SIZE #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_EXTENSION_LEN 8 /* max size of extension */ @@ -24,11 +24,20 @@ #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */ -#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1) -#define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS) -#define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS) -#define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1) -#define F2FS_BLK_ALIGN(x) (F2FS_BYTES_TO_BLK((x) + F2FS_BLKSIZE - 1)) +#define F2FS_BLKSIZE(sbi) ((sbi)->blocksize) +#define F2FS_BLKSIZE_BITS(sbi) ((sbi)->log_blocksize) +#define F2FS_BLKSIZE_MASK(sbi) (F2FS_BLKSIZE(sbi) - 1) +#define F2FS_LOG_SECTORS_PER_BLOCK(sbi) (F2FS_BLKSIZE_BITS(sbi) - 9) +#define F2FS_BLKS_PER_PAGE(sbi) (PAGE_SIZE / F2FS_BLKSIZE(sbi)) +#define F2FS_BYTES_TO_BLK(sbi, bytes) \ + ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS(sbi)) +#define F2FS_BLK_TO_BYTES(sbi, blk) \ + ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS(sbi)) +#define F2FS_BLK_END_BYTES(sbi, blk) \ + (F2FS_BLK_TO_BYTES(sbi, (blk) + 1) - 1) +#define F2FS_BLK_ALIGN(sbi, bytes) \ + F2FS_BYTES_TO_BLK(sbi, (unsigned long long)(bytes) + \ + F2FS_BLKSIZE(sbi) - 1) /* 0, 1(node nid), 2(meta nid) are reserved node id */ #define F2FS_RESERVED_NODE_NUM 3 @@ -214,20 +223,27 @@ struct f2fs_checkpoint { unsigned char sit_nat_version_bitmap[]; } __packed; -#define CP_CHKSUM_OFFSET (F2FS_BLKSIZE - sizeof(__le32)) /* default chksum offset in checkpoint */ #define CP_MIN_CHKSUM_OFFSET \ (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap)) /* * For orphan inode management + * + * The number of inode entries in an orphan block depends on the filesystem + * block size. Its exact on-disk layout is: + * + * 0 blocksize - 16 blocksize + * +--------------------------+--------------------------+ + * | ino[0] ... ino[n - 1] | struct f2fs_orphan_footer | + * +--------------------------+--------------------------+ + * + * n = (blocksize - sizeof(struct f2fs_orphan_footer)) / sizeof(__le32) */ -#define F2FS_ORPHANS_PER_BLOCK ((F2FS_BLKSIZE - 4 * sizeof(__le32)) / sizeof(__le32)) - -#define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \ - F2FS_ORPHANS_PER_BLOCK) - struct f2fs_orphan_block { - __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */ + DECLARE_FLEX_ARRAY(__le32, ino); +} __packed; + +struct f2fs_orphan_footer { __le32 reserved; /* reserved */ __le16 blk_addr; /* block index in current CP */ __le16 blk_count; /* Number of orphan inode blocks in CP */ @@ -260,27 +276,15 @@ struct node_footer { } __packed; /* Address Pointers in an Inode */ -#define DEF_ADDRS_PER_INODE ((F2FS_BLKSIZE - OFFSET_OF_END_OF_I_EXT \ - - SIZE_OF_I_NID \ - - sizeof(struct node_footer)) / sizeof(__le32)) -#define CUR_ADDRS_PER_INODE(inode) (DEF_ADDRS_PER_INODE - \ - get_extra_isize(inode)) +#define F2FS_DEF_ADDRS_PER_INODE(blocksize) \ + (((blocksize) - OFFSET_OF_END_OF_I_EXT - SIZE_OF_I_NID - \ + sizeof(struct node_footer)) / sizeof(__le32)) #define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */ #define ADDRS_PER_INODE(inode) addrs_per_page(inode, true) /* Address Pointers in a Direct Block */ -#define DEF_ADDRS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32)) #define ADDRS_PER_BLOCK(inode) addrs_per_page(inode, false) -/* Node IDs in an Indirect Block */ -#define NIDS_PER_BLOCK ((F2FS_BLKSIZE - sizeof(struct node_footer)) / sizeof(__le32)) - #define ADDRS_PER_PAGE(folio, inode) (addrs_per_page(inode, IS_INODE(folio))) -#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) -#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) -#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) -#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) -#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) - #define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ #define F2FS_INLINE_DATA 0x02 /* file inline data flag */ #define F2FS_INLINE_DENTRY 0x04 /* file inline dentry flag */ @@ -339,18 +343,26 @@ struct f2fs_inode { */ __le32 i_extra_end[0]; /* for attribute size calculation */ } __packed; - __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ + DECLARE_FLEX_ARRAY(__le32, i_addr); /* data block pointers */ }; - __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2), - double_indirect(1) node id */ + /* + * __le32 i_nid[DEF_NIDS_PER_INODE]; + * direct(2), indirect(2), double_indirect(1) node IDs + * + * It is stored immediately before the node footer at the end of the + * filesystem block. Its offset depends on the filesystem block size, so + * locate it dynamically with F2FS_INODE_NIDS(). + */ } __packed; struct direct_node { - __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */ + /* The address count depends on the filesystem block size. */ + DECLARE_FLEX_ARRAY(__le32, addr); /* array of data block address */ } __packed; struct indirect_node { - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */ + /* The node ID count depends on the filesystem block size. */ + DECLARE_FLEX_ARRAY(__le32, nid); /* array of data block address */ } __packed; enum { @@ -369,14 +381,18 @@ struct f2fs_node { struct direct_node dn; struct indirect_node in; }; - struct node_footer footer; + /* + * struct node_footer footer; + * + * It is stored at the end of the filesystem block, after the inode or + * direct/indirect node data. Its offset depends on the filesystem block + * size, so locate it dynamically with F2FS_NODE_FOOTER(). + */ } __packed; /* * For NAT entries */ -#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_nat_entry)) - struct f2fs_nat_entry { __u8 version; /* latest version of cached nat entry */ __le32 ino; /* inode number */ @@ -384,7 +400,8 @@ struct f2fs_nat_entry { } __packed; struct f2fs_nat_block { - struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK]; + /* The entry count depends on the filesystem block size. */ + DECLARE_FLEX_ARRAY(struct f2fs_nat_entry, entries); } __packed; /* @@ -396,8 +413,6 @@ struct f2fs_nat_block { * Not allow to change this. */ #define SIT_VBLOCK_MAP_SIZE 64 -#define SIT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_sit_entry)) - /* * F2FS uses 4 bytes to represent block address. As a result, supported size of * disk is 16 TB for a 4K page size and 64 TB for a 16K page size and it equals @@ -424,8 +439,13 @@ struct f2fs_sit_entry { __le64 mtime; /* segment age for cleaning */ } __packed; +/* + * The on-disk SIT block is a filesystem-block-sized array of SIT entries. + * Its entry count depends on the filesystem block size, so it must be + * calculated by the caller rather than implied by this C structure. + */ struct f2fs_sit_block { - struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK]; + DECLARE_FLEX_ARRAY(struct f2fs_sit_entry, entries); } __packed; /* @@ -595,15 +615,7 @@ typedef __le32 f2fs_hash_t; * dentry, when converting inline dentry we should handle this carefully. */ -/* the number of dentry in a block */ -#define NR_DENTRY_IN_BLOCK ((BITS_PER_BYTE * F2FS_BLKSIZE) / \ - ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1)) #define SIZE_OF_DIR_ENTRY 11 /* by byte */ -#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ - BITS_PER_BYTE) -#define SIZE_OF_RESERVED (F2FS_BLKSIZE - ((SIZE_OF_DIR_ENTRY + \ - F2FS_SLOT_LEN) * \ - NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) #define MIN_INLINE_DENTRY_SIZE 40 /* just include '.' and '..' entries */ /* One directory entry slot representing F2FS_SLOT_LEN-sized file name */ @@ -614,14 +626,21 @@ struct f2fs_dir_entry { __u8 file_type; /* file type */ } __packed; -/* Block-sized directory entry block */ -struct f2fs_dentry_block { - /* validity bitmap for directory entries in each block */ - __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; - __u8 reserved[SIZE_OF_RESERVED]; - struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK]; - __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; -} __packed; +/* + * A dentry block is laid out as follows, where the number of entries and all + * offsets are determined by the filesystem block size at runtime: + * + * 0 blocksize + * +--------+----------+-------------------+-----------------------+ + * | bitmap | reserved | dir_entry[entries]| filename[entries][8] | + * +--------+----------+-------------------+-----------------------+ + * + * entries = (BITS_PER_BYTE * blocksize) / + * ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1) + * bitmap_size = DIV_ROUND_UP(entries, BITS_PER_BYTE) + * reserved_size = blocksize - bitmap_size - + * (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * entries + */ #define F2FS_DEF_PROJID 0 /* default project ID */ |
