From 126ce7214d213412bd4a23c731626ee7fe4cb4ec Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 2 Apr 2019 18:52:22 +0800 Subject: f2fs: add tracepoint for f2fs_file_write_iter() This patch adds tracepoint for f2fs_file_write_iter(). Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- include/trace/events/f2fs.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'include') diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index a3916b4dd57e..353a6fff2b80 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -533,6 +533,37 @@ TRACE_EVENT(f2fs_truncate_partial_nodes, __entry->err) ); +TRACE_EVENT(f2fs_file_write_iter, + + TP_PROTO(struct inode *inode, unsigned long offset, + unsigned long length, int ret), + + TP_ARGS(inode, offset, length, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned long, offset) + __field(unsigned long, length) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->offset = offset; + __entry->length = length; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, " + "offset = %lu, length = %lu, written(err) = %d", + show_dev_ino(__entry), + __entry->offset, + __entry->length, + __entry->ret) +); + TRACE_EVENT(f2fs_map_blocks, TP_PROTO(struct inode *inode, struct f2fs_map_blocks *map, int ret), -- cgit v1.2.3-71-gd317 From d02a6e6174a772fa90c5efa51a55a04e6d8c0006 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 25 Mar 2019 21:08:19 +0800 Subject: f2fs: allow address pointer number of dnode aligning to specified size This patch expands scalability of dnode layout, it allows address pointer number of dnode aligning to specified size (now, the size is one byte by default), and later the number can align to compress cluster size (1 << n bytes, n=[2,..)), it can avoid cluster acrossing two dnode, making design of compress meta layout simple. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/f2fs.h | 9 ++++++++- fs/f2fs/file.c | 7 ++++--- fs/f2fs/gc.c | 2 +- fs/f2fs/node.c | 10 +++++----- fs/f2fs/super.c | 2 +- include/linux/f2fs_fs.h | 7 ++++--- 6 files changed, 23 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4c6fe137962d..9a9dc20e295b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2574,7 +2574,14 @@ static inline int f2fs_has_inline_xattr(struct inode *inode) static inline unsigned int addrs_per_inode(struct inode *inode) { - return CUR_ADDRS_PER_INODE(inode) - get_inline_xattr_addrs(inode); + unsigned int addrs = CUR_ADDRS_PER_INODE(inode) - + get_inline_xattr_addrs(inode); + return ALIGN_DOWN(addrs, 1); +} + +static inline unsigned int addrs_per_block(struct inode *inode) +{ + return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, 1); } static inline void *inline_xattr_addr(struct inode *inode, struct page *page) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f34c6820c44e..920d66fc2c89 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -552,7 +552,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count) void f2fs_truncate_data_blocks(struct dnode_of_data *dn) { - f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK); + f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK(dn->inode)); } static int truncate_partial_data_page(struct inode *inode, u64 from, @@ -1006,7 +1006,8 @@ next_dnode: } else if (ret == -ENOENT) { if (dn.max_level == 0) return -ENOENT; - done = min((pgoff_t)ADDRS_PER_BLOCK - dn.ofs_in_node, len); + done = min((pgoff_t)ADDRS_PER_BLOCK(inode) - dn.ofs_in_node, + len); blkaddr += done; do_replace += done; goto next; @@ -1157,7 +1158,7 @@ static int __exchange_data_block(struct inode *src_inode, int ret; while (len) { - olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len); + olen = min((pgoff_t)4 * ADDRS_PER_BLOCK(src_inode), len); src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode), array_size(olen, sizeof(block_t)), diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index a66a8752e5f6..ba30ec90952f 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -591,7 +591,7 @@ block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode) int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); bidx = node_ofs - 5 - dec; } - return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(inode); + return bidx * ADDRS_PER_BLOCK(inode) + ADDRS_PER_INODE(inode); } static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index e29d5f6735ae..057362a821a0 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -600,9 +600,9 @@ static void f2fs_ra_node_pages(struct page *parent, int start, int n) pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) { const long direct_index = ADDRS_PER_INODE(dn->inode); - const long direct_blks = ADDRS_PER_BLOCK; - const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; - unsigned int skipped_unit = ADDRS_PER_BLOCK; + const long direct_blks = ADDRS_PER_BLOCK(dn->inode); + const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK; + unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode); int cur_level = dn->cur_level; int max_level = dn->max_level; pgoff_t base = 0; @@ -636,9 +636,9 @@ static int get_node_path(struct inode *inode, long block, int offset[4], unsigned int noffset[4]) { const long direct_index = ADDRS_PER_INODE(inode); - const long direct_blks = ADDRS_PER_BLOCK; + const long direct_blks = ADDRS_PER_BLOCK(inode); const long dptrs_per_blk = NIDS_PER_BLOCK; - const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; + const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK; const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; int n = 0; int level = 0; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index cbbb1e35070d..fefc8cc6e756 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2276,7 +2276,7 @@ static const struct export_operations f2fs_export_ops = { static loff_t max_file_blocks(void) { loff_t result = 0; - loff_t leaf_count = ADDRS_PER_BLOCK; + loff_t leaf_count = DEF_ADDRS_PER_BLOCK; /* * note: previously, result is equal to (DEF_ADDRS_PER_INODE - diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index f5740423b002..55da9abed023 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -198,11 +198,12 @@ struct f2fs_extent { get_extra_isize(inode)) #define DEF_NIDS_PER_INODE 5 /* Node IDs in an Inode */ #define ADDRS_PER_INODE(inode) addrs_per_inode(inode) -#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ +#define DEF_ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ +#define ADDRS_PER_BLOCK(inode) addrs_per_block(inode) #define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ #define ADDRS_PER_PAGE(page, inode) \ - (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK) + (IS_INODE(page) ? ADDRS_PER_INODE(inode) : ADDRS_PER_BLOCK(inode)) #define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) #define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) @@ -267,7 +268,7 @@ struct f2fs_inode { } __packed; struct direct_node { - __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */ + __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */ } __packed; struct indirect_node { -- cgit v1.2.3-71-gd317 From d7eb8f1cdfaefcd41b716ef0ed1745b43c6c4fc9 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 22 Apr 2019 17:33:52 +0800 Subject: f2fs: allow unfixed f2fs_checkpoint.checksum_offset Previously, f2fs_checkpoint.checksum_offset points fixed position of f2fs_checkpoint structure: "#define CP_CHKSUM_OFFSET 4092" It is unnecessary, and it breaks the consecutiveness of nat and sit bitmap stored across checkpoint park block and payload blocks. This patch allows f2fs to handle unfixed .checksum_offset. In addition, for the case checksum value is stored in the middle of checkpoint park, calculating checksum value with superposition method like we did for inode_checksum. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 27 +++++++++++++++++++++------ include/linux/f2fs_fs.h | 4 ++++ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index f42b0015724b..af77655e65b2 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -758,13 +758,27 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) } } +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(sbi, ckpt, chksum_ofs); + if (chksum_ofs < CP_CHKSUM_OFFSET) { + chksum_ofs += sizeof(chksum); + chksum = f2fs_chksum(sbi, chksum, (__u8 *)ckpt + chksum_ofs, + F2FS_BLKSIZE - chksum_ofs); + } + return chksum; +} + static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr, struct f2fs_checkpoint **cp_block, struct page **cp_page, unsigned long long *version) { - unsigned long blk_size = sbi->blocksize; size_t crc_offset = 0; - __u32 crc = 0; + __u32 crc; *cp_page = f2fs_get_meta_page(sbi, cp_addr); if (IS_ERR(*cp_page)) @@ -773,15 +787,16 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr, *cp_block = (struct f2fs_checkpoint *)page_address(*cp_page); crc_offset = le32_to_cpu((*cp_block)->checksum_offset); - if (crc_offset > (blk_size - sizeof(__le32))) { + if (crc_offset < CP_MIN_CHKSUM_OFFSET || + crc_offset > CP_CHKSUM_OFFSET) { f2fs_put_page(*cp_page, 1); f2fs_msg(sbi->sb, KERN_WARNING, "invalid crc_offset: %zu", crc_offset); return -EINVAL; } - crc = cur_cp_crc(*cp_block); - if (!f2fs_crc_valid(sbi, crc, *cp_block, crc_offset)) { + crc = f2fs_checkpoint_chksum(sbi, *cp_block); + if (crc != cur_cp_crc(*cp_block)) { f2fs_put_page(*cp_page, 1); f2fs_msg(sbi->sb, KERN_WARNING, "invalid crc value"); return -EINVAL; @@ -1389,7 +1404,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_crc32(sbi, ckpt, le32_to_cpu(ckpt->checksum_offset)); + crc32 = f2fs_checkpoint_chksum(sbi, ckpt); *((__le32 *)((unsigned char *)ckpt + le32_to_cpu(ckpt->checksum_offset))) = cpu_to_le32(crc32); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 55da9abed023..65559900d4d7 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -164,6 +164,10 @@ struct f2fs_checkpoint { unsigned char sit_nat_version_bitmap[1]; } __packed; +#define CP_CHKSUM_OFFSET 4092 /* default chksum offset in checkpoint */ +#define CP_MIN_CHKSUM_OFFSET \ + (offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap)) + /* * For orphan inode management */ -- cgit v1.2.3-71-gd317 From d764834378a9870ca56e9b2977ea46e9911ec358 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 15 Apr 2019 15:22:19 +0800 Subject: f2fs: add tracepoint for f2fs_filemap_fault() This patch adds tracepoint for f2fs_filemap_fault(). Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 ++ include/trace/events/f2fs.h | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'include') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 3baa39e3e1fd..45b45f37d347 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -39,6 +39,8 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf) ret = filemap_fault(vmf); up_read(&F2FS_I(inode)->i_mmap_sem); + trace_f2fs_filemap_fault(inode, vmf->pgoff, (unsigned long)ret); + return ret; } diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 353a6fff2b80..53b96f12300c 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -1284,6 +1284,32 @@ DEFINE_EVENT(f2fs__page, f2fs_commit_inmem_page, TP_ARGS(page, type) ); +TRACE_EVENT(f2fs_filemap_fault, + + TP_PROTO(struct inode *inode, pgoff_t index, unsigned long ret), + + TP_ARGS(inode, index, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(pgoff_t, index) + __field(unsigned long, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->index = index; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, index = %lu, ret = %lx", + show_dev_ino(__entry), + (unsigned long)__entry->index, + __entry->ret) +); + TRACE_EVENT(f2fs_writepages, TP_PROTO(struct inode *inode, struct writeback_control *wbc, int type), -- cgit v1.2.3-71-gd317