summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-09-14 11:04:50 +0100
committerMark Brown <broonie@kernel.org>2026-09-14 11:04:50 +0100
commitd72c8fbae9df1a72ffa0ddb65e18432174a4366e (patch)
treea59ddafa545c55f251812e4175c6822bf810a2c9
parentf537ae92161ed1e51c3fd9f8cda1b4f4670e98a8 (diff)
parent6a0dda6838b65609590890bdfe4ffb9c2ab031a1 (diff)
downloadlinux-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.c77
-rw-r--r--fs/f2fs/data.c85
-rw-r--r--fs/f2fs/debug.c4
-rw-r--r--fs/f2fs/dir.c51
-rw-r--r--fs/f2fs/extent_cache.c9
-rw-r--r--fs/f2fs/f2fs.h128
-rw-r--r--fs/f2fs/file.c85
-rw-r--r--fs/f2fs/gc.c27
-rw-r--r--fs/f2fs/inline.c11
-rw-r--r--fs/f2fs/inode.c25
-rw-r--r--fs/f2fs/node.c171
-rw-r--r--fs/f2fs/node.h87
-rw-r--r--fs/f2fs/recovery.c4
-rw-r--r--fs/f2fs/segment.c114
-rw-r--r--fs/f2fs/segment.h32
-rw-r--r--fs/f2fs/shrinker.c2
-rw-r--r--fs/f2fs/super.c84
-rw-r--r--fs/f2fs/sysfs.c10
-rw-r--r--fs/f2fs/verity.c6
-rw-r--r--fs/f2fs/xattr.c10
-rw-r--r--fs/f2fs/xattr.h11
-rw-r--r--include/linux/f2fs_fs.h135
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 */