From 39bee2e6acc2522d88feb324b18178b34cb7b75a Mon Sep 17 00:00:00 2001 From: Sergey Shtylyov Date: Tue, 20 Dec 2022 20:17:32 +0300 Subject: f2fs: file: drop useless initializer in expand_inode_data() In expand_inode_data(), the 'new_size' local variable is initialized to the result of i_size_read(), however this value isn't ever used, so we can drop this initializer... Found by Linux Verification Center (linuxtesting.org) with the SVACE static analysis tool. Signed-off-by: Sergey Shtylyov Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index ecbc8c135b49..6426b50b70b8 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1697,7 +1697,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset, .err_gc_skipped = true, .nr_free_secs = 0 }; pgoff_t pg_start, pg_end; - loff_t new_size = i_size_read(inode); + loff_t new_size; loff_t off_end; block_t expanded = 0; int err; -- cgit v1.2.3 From cf342d3beda000b4c60990755ca7800de5038785 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Nov 2022 10:15:15 +0100 Subject: f2fs: add a f2fs_get_block_locked helper This allows to keep the f2fs_do_map_lock based locking scheme private to data.c. Signed-off-by: Christoph Hellwig Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 16 ++++++++++++++-- fs/f2fs/f2fs.h | 3 +-- fs/f2fs/file.c | 4 +--- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e80d7d250993..904dfd1f16d0 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1212,7 +1212,7 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index) return err; } -int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index) +static int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index) { if (f2fs_lookup_read_extent_cache_block(dn->inode, index, &dn->data_blkaddr)) @@ -1451,7 +1451,7 @@ alloc: return 0; } -void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) +static void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) { if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (lock) @@ -1466,6 +1466,18 @@ void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) } } +int f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); + int err; + + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); + err = f2fs_get_block(dn, index); + f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); + + return err; +} + /* * f2fs_map_blocks() tries to find or build mapping relationship which * maps continuous logical blocks to physical blocks, and return such diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index cc737f2a9e82..744cb442085f 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3800,7 +3800,7 @@ void f2fs_set_data_blkaddr(struct dnode_of_data *dn); void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr); int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count); int f2fs_reserve_new_block(struct dnode_of_data *dn); -int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index); +int f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index); int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index); struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index, blk_opf_t op_flags, bool for_write, pgoff_t *next_pgofs); @@ -3811,7 +3811,6 @@ struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, struct page *f2fs_get_new_data_page(struct inode *inode, struct page *ipage, pgoff_t index, bool new_i_size); int f2fs_do_write_data_page(struct f2fs_io_info *fio); -void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock); int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int create, int flag); int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 6426b50b70b8..705a7eb4df99 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -113,10 +113,8 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf) if (need_alloc) { /* block allocation */ - f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, true); set_new_dnode(&dn, inode, NULL, NULL, 0); - err = f2fs_get_block(&dn, page->index); - f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, false); + err = f2fs_get_block_locked(&dn, page->index); } #ifdef CONFIG_F2FS_FS_COMPRESSION -- cgit v1.2.3 From cd8fc5226bef3a1fda13a0e61794a039ca46744a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 28 Nov 2022 10:15:20 +0100 Subject: f2fs: remove the create argument to f2fs_map_blocks The create argument is always identicaly to map->m_may_create, so use that consistently. Signed-off-by: Christoph Hellwig Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/data.c | 63 +++++++++++++++++++-------------------------- fs/f2fs/f2fs.h | 3 +-- fs/f2fs/file.c | 12 ++++----- include/trace/events/f2fs.h | 11 +++----- 4 files changed, 38 insertions(+), 51 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e6f94591717b..1cc5c6cb3146 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1477,8 +1477,7 @@ int f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index) * maps continuous logical blocks to physical blocks, and return such * info via f2fs_map_blocks structure. */ -int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, - int create, int flag) +int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) { unsigned int maxblocks = map->m_len; struct dnode_of_data dn; @@ -1507,38 +1506,31 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, pgofs = (pgoff_t)map->m_lblk; end = pgofs + maxblocks; - if (!create && f2fs_lookup_read_extent_cache(inode, pgofs, &ei)) { - if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO && - map->m_may_create) - goto next_dnode; + if (map->m_may_create || + !f2fs_lookup_read_extent_cache(inode, pgofs, &ei)) + goto next_dnode; - map->m_pblk = ei.blk + pgofs - ei.fofs; - map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs); - map->m_flags = F2FS_MAP_MAPPED; - if (map->m_next_extent) - *map->m_next_extent = pgofs + map->m_len; + /* Found the map in read extent cache */ + map->m_pblk = ei.blk + pgofs - ei.fofs; + map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs); + map->m_flags = F2FS_MAP_MAPPED; + if (map->m_next_extent) + *map->m_next_extent = pgofs + map->m_len; - /* for hardware encryption, but to avoid potential issue in future */ - if (flag == F2FS_GET_BLOCK_DIO) - f2fs_wait_on_block_writeback_range(inode, + /* for hardware encryption, but to avoid potential issue in future */ + if (flag == F2FS_GET_BLOCK_DIO) + f2fs_wait_on_block_writeback_range(inode, map->m_pblk, map->m_len); - if (map->m_multidev_dio) { - block_t blk_addr = map->m_pblk; - - bidx = f2fs_target_device_index(sbi, map->m_pblk); + if (map->m_multidev_dio) { + bidx = f2fs_target_device_index(sbi, map->m_pblk); - map->m_bdev = FDEV(bidx).bdev; - map->m_pblk -= FDEV(bidx).start_blk; - map->m_len = min(map->m_len, + map->m_bdev = FDEV(bidx).bdev; + map->m_pblk -= FDEV(bidx).start_blk; + map->m_len = min(map->m_len, FDEV(bidx).end_blk + 1 - map->m_pblk); - - if (map->m_may_create) - f2fs_update_device_state(sbi, inode->i_ino, - blk_addr, map->m_len); - } - goto out; } + goto out; next_dnode: if (map->m_may_create) @@ -1602,7 +1594,7 @@ next_block: set_inode_flag(inode, FI_APPEND_WRITE); } } else { - if (create) { + if (map->m_may_create) { if (unlikely(f2fs_cp_error(sbi))) { err = -EIO; goto sync_out; @@ -1776,7 +1768,7 @@ unlock_out: f2fs_balance_fs(sbi, dn.node_changed); } out: - trace_f2fs_map_blocks(inode, map, create, flag, err); + trace_f2fs_map_blocks(inode, map, flag, err); return err; } @@ -1798,7 +1790,7 @@ bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len) while (map.m_lblk < last_lblk) { map.m_len = last_lblk - map.m_lblk; - err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DEFAULT); if (err || map.m_len == 0) return false; map.m_lblk += map.m_len; @@ -1972,7 +1964,7 @@ next: map.m_len = cluster_size - count_in_cluster; } - ret = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_FIEMAP); + ret = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); if (ret) goto out; @@ -2105,7 +2097,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page, map->m_lblk = block_in_file; map->m_len = last_block - block_in_file; - ret = f2fs_map_blocks(inode, map, 0, F2FS_GET_BLOCK_DEFAULT); + ret = f2fs_map_blocks(inode, map, F2FS_GET_BLOCK_DEFAULT); if (ret) goto out; got_it: @@ -3807,7 +3799,7 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) map.m_next_pgofs = NULL; map.m_seg_type = NO_CHECK_TYPE; - if (!f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_BMAP)) + if (!f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_BMAP)) blknr = map.m_pblk; } out: @@ -3915,7 +3907,7 @@ retry: map.m_seg_type = NO_CHECK_TYPE; map.m_may_create = false; - ret = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_FIEMAP); + ret = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); if (ret) goto out; @@ -4140,8 +4132,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, if (flags & IOMAP_WRITE) map.m_may_create = true; - err = f2fs_map_blocks(inode, &map, flags & IOMAP_WRITE, - F2FS_GET_BLOCK_DIO); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DIO); if (err) return err; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 744cb442085f..60f421fe14ee 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3811,8 +3811,7 @@ struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, struct page *f2fs_get_new_data_page(struct inode *inode, struct page *ipage, pgoff_t index, bool new_i_size); int f2fs_do_write_data_page(struct f2fs_io_info *fio); -int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, - int create, int flag); +int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag); int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); int f2fs_encrypt_one_page(struct f2fs_io_info *fio); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 705a7eb4df99..939c7247c367 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1743,7 +1743,7 @@ next_alloc: f2fs_unlock_op(sbi); map.m_seg_type = CURSEG_COLD_DATA_PINNED; - err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_PRE_DIO); file_dont_truncate(inode); f2fs_up_write(&sbi->pin_sem); @@ -1756,7 +1756,7 @@ next_alloc: map.m_len = expanded; } else { - err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_PRE_AIO); expanded = map.m_len; } out_err: @@ -2604,7 +2604,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, */ while (map.m_lblk < pg_end) { map.m_len = pg_end - map.m_lblk; - err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DEFAULT); if (err) goto out; @@ -2651,7 +2651,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, do_map: map.m_len = pg_end - map.m_lblk; - err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DEFAULT); if (err) goto clear_out; @@ -3225,7 +3225,7 @@ int f2fs_precache_extents(struct inode *inode) map.m_len = end - map.m_lblk; f2fs_down_write(&fi->i_gc_rwsem[WRITE]); - err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_PRECACHE); + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_PRECACHE); f2fs_up_write(&fi->i_gc_rwsem[WRITE]); if (err) return err; @@ -4464,7 +4464,7 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter, flag = F2FS_GET_BLOCK_PRE_AIO; } - ret = f2fs_map_blocks(inode, &map, 1, flag); + ret = f2fs_map_blocks(inode, &map, flag); /* -ENOSPC|-EDQUOT are fine to report the number of allocated blocks. */ if (ret < 0 && !((ret == -ENOSPC || ret == -EDQUOT) && map.m_len > 0)) return ret; diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 31d994e6b4ca..9183a0a11e26 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -569,10 +569,10 @@ TRACE_EVENT(f2fs_file_write_iter, ); TRACE_EVENT(f2fs_map_blocks, - TP_PROTO(struct inode *inode, struct f2fs_map_blocks *map, - int create, int flag, int ret), + TP_PROTO(struct inode *inode, struct f2fs_map_blocks *map, int flag, + int ret), - TP_ARGS(inode, map, create, flag, ret), + TP_ARGS(inode, map, flag, ret), TP_STRUCT__entry( __field(dev_t, dev) @@ -584,7 +584,6 @@ TRACE_EVENT(f2fs_map_blocks, __field(int, m_seg_type) __field(bool, m_may_create) __field(bool, m_multidev_dio) - __field(int, create) __field(int, flag) __field(int, ret) ), @@ -599,7 +598,6 @@ TRACE_EVENT(f2fs_map_blocks, __entry->m_seg_type = map->m_seg_type; __entry->m_may_create = map->m_may_create; __entry->m_multidev_dio = map->m_multidev_dio; - __entry->create = create; __entry->flag = flag; __entry->ret = ret; ), @@ -607,7 +605,7 @@ TRACE_EVENT(f2fs_map_blocks, TP_printk("dev = (%d,%d), ino = %lu, file offset = %llu, " "start blkaddr = 0x%llx, len = 0x%llx, flags = %u, " "seg_type = %d, may_create = %d, multidevice = %d, " - "create = %d, flag = %d, err = %d", + "flag = %d, err = %d", show_dev_ino(__entry), (unsigned long long)__entry->m_lblk, (unsigned long long)__entry->m_pblk, @@ -616,7 +614,6 @@ TRACE_EVENT(f2fs_map_blocks, __entry->m_seg_type, __entry->m_may_create, __entry->m_multidev_dio, - __entry->create, __entry->flag, __entry->ret) ); -- cgit v1.2.3 From 5eaac835f27f2de6b73412d7c24e755733b49de0 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 16 Dec 2022 23:50:00 +0800 Subject: f2fs: fix to avoid potential deadlock There is a potential deadlock reported by syzbot as below: F2FS-fs (loop2): invalid crc value F2FS-fs (loop2): Found nat_bits in checkpoint F2FS-fs (loop2): Mounted with checkpoint version = 48b305e4 ====================================================== WARNING: possible circular locking dependency detected 6.1.0-rc8-syzkaller-33330-ga5541c0811a0 #0 Not tainted ------------------------------------------------------ syz-executor.2/32123 is trying to acquire lock: ffff0000c0e1a608 (&mm->mmap_lock){++++}-{3:3}, at: __might_fault+0x54/0xb4 mm/memory.c:5644 but task is already holding lock: ffff0001317c6088 (&sbi->sb_lock){++++}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2205 [inline] ffff0001317c6088 (&sbi->sb_lock){++++}-{3:3}, at: f2fs_ioc_get_encryption_pwsalt fs/f2fs/file.c:2334 [inline] ffff0001317c6088 (&sbi->sb_lock){++++}-{3:3}, at: __f2fs_ioctl+0x1370/0x3318 fs/f2fs/file.c:4151 which lock already depends on the new lock. Chain exists of: &mm->mmap_lock --> &nm_i->nat_tree_lock --> &sbi->sb_lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&sbi->sb_lock); lock(&nm_i->nat_tree_lock); lock(&sbi->sb_lock); lock(&mm->mmap_lock); Let's try to avoid above deadlock condition by moving __might_fault() out of sbi->sb_lock coverage. Fixes: 95fa90c9e5a7 ("f2fs: support recording errors into superblock") Link: https://lore.kernel.org/linux-f2fs-devel/000000000000cd5fe305ef617fe2@google.com/T/#u Reported-by: syzbot+4793f6096d174c90b4f7@syzkaller.appspotmail.com Signed-off-by: Chao Yu Reviewed-by: Eric Biggers Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 939c7247c367..bef0ee57e88d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2336,6 +2336,7 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + u8 encrypt_pw_salt[16]; int err; if (!f2fs_sb_has_encrypt(sbi)) @@ -2360,12 +2361,14 @@ static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) goto out_err; } got_it: - if (copy_to_user((__u8 __user *)arg, sbi->raw_super->encrypt_pw_salt, - 16)) - err = -EFAULT; + memcpy(encrypt_pw_salt, sbi->raw_super->encrypt_pw_salt, 16); out_err: f2fs_up_write(&sbi->sb_lock); mnt_drop_write_file(filp); + + if (!err && copy_to_user((__u8 __user *)arg, encrypt_pw_salt, 16)) + err = -EFAULT; + return err; } -- cgit v1.2.3 From 1cd7565449de6e838ff5a3fa75fbd2ce58c6d955 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 21 Dec 2022 03:12:12 +0800 Subject: f2fs: add a f2fs_ prefix to punch_hole() and expand_inode_data() For example, f2fs_collapse_range(), f2fs_collapse_range(), f2fs_insert_range(), the functions used in f2fs_fallocate() are all prefixed with f2fs_, so let's keep the name consistent. Signed-off-by: Yangtao Li Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index bef0ee57e88d..58b4200f7fdf 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1110,7 +1110,7 @@ int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) return 0; } -static int punch_hole(struct inode *inode, loff_t offset, loff_t len) +static int f2fs_punch_hole(struct inode *inode, loff_t offset, loff_t len) { pgoff_t pg_start, pg_end; loff_t off_start, off_end; @@ -1682,7 +1682,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) return ret; } -static int expand_inode_data(struct inode *inode, loff_t offset, +static int f2fs_expand_inode_data(struct inode *inode, loff_t offset, loff_t len, int mode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -1830,7 +1830,7 @@ static long f2fs_fallocate(struct file *file, int mode, if (offset >= inode->i_size) goto out; - ret = punch_hole(inode, offset, len); + ret = f2fs_punch_hole(inode, offset, len); } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { ret = f2fs_collapse_range(inode, offset, len); } else if (mode & FALLOC_FL_ZERO_RANGE) { @@ -1838,7 +1838,7 @@ static long f2fs_fallocate(struct file *file, int mode, } else if (mode & FALLOC_FL_INSERT_RANGE) { ret = f2fs_insert_range(inode, offset, len); } else { - ret = expand_inode_data(inode, offset, len, mode); + ret = f2fs_expand_inode_data(inode, offset, len, mode); } if (!ret) { -- cgit v1.2.3 From c40e15a9a59f79e79d9500f1fd019321ec35b959 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 21 Dec 2022 02:39:04 +0800 Subject: f2fs: merge f2fs_show_injection_info() into time_to_inject() There is no need to additionally use f2fs_show_injection_info() to output information. Concatenate time_to_inject() and __time_to_inject() via a macro. In the new __time_to_inject() function, pass in the caller function name and parent function. In this way, we no longer need the f2fs_show_injection_info() function, and let's remove it. Suggested-by: Chao Yu Signed-off-by: Yangtao Li Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 5 +---- fs/f2fs/data.c | 8 ++------ fs/f2fs/dir.c | 4 +--- fs/f2fs/f2fs.h | 44 ++++++++++++++------------------------------ fs/f2fs/file.c | 4 +--- fs/f2fs/gc.c | 4 +--- fs/f2fs/inode.c | 4 +--- fs/f2fs/node.c | 4 +--- fs/f2fs/segment.c | 5 +---- fs/f2fs/super.c | 8 ++------ 10 files changed, 25 insertions(+), 65 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 56f7d0d6a8b2..d68b3c991888 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -171,10 +171,8 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr, bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type) { - if (time_to_inject(sbi, FAULT_BLKADDR)) { - f2fs_show_injection_info(sbi, FAULT_BLKADDR); + if (time_to_inject(sbi, FAULT_BLKADDR)) return false; - } switch (type) { case META_NAT: @@ -622,7 +620,6 @@ int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi) if (time_to_inject(sbi, FAULT_ORPHAN)) { spin_unlock(&im->ino_lock); - f2fs_show_injection_info(sbi, FAULT_ORPHAN); return -ENOSPC; } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index af906ed6d53d..c940da1c540f 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -295,10 +295,8 @@ static void f2fs_read_end_io(struct bio *bio) iostat_update_and_unbind_ctx(bio, 0); ctx = bio->bi_private; - if (time_to_inject(sbi, FAULT_READ_IO)) { - f2fs_show_injection_info(sbi, FAULT_READ_IO); + if (time_to_inject(sbi, FAULT_READ_IO)) bio->bi_status = BLK_STS_IOERR; - } if (bio->bi_status) { f2fs_finish_read_bio(bio, intask); @@ -335,10 +333,8 @@ static void f2fs_write_end_io(struct bio *bio) iostat_update_and_unbind_ctx(bio, 1); sbi = bio->bi_private; - if (time_to_inject(sbi, FAULT_WRITE_IO)) { - f2fs_show_injection_info(sbi, FAULT_WRITE_IO); + if (time_to_inject(sbi, FAULT_WRITE_IO)) bio->bi_status = BLK_STS_IOERR; - } bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 8e025157f35c..9ccdbe120425 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -732,10 +732,8 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname, } start: - if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH)) { - f2fs_show_injection_info(F2FS_I_SB(dir), FAULT_DIR_DEPTH); + if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH)) return -ENOSPC; - } if (unlikely(current_depth == MAX_DIR_HASH_DEPTH)) return -ENOSPC; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d1fcaa973a53..53d7ca96df63 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1867,12 +1867,10 @@ struct f2fs_sb_info { }; #ifdef CONFIG_F2FS_FAULT_INJECTION -#define f2fs_show_injection_info(sbi, type) \ - printk_ratelimited("%sF2FS-fs (%s) : inject %s in %s of %pS\n", \ - KERN_INFO, sbi->sb->s_id, \ - f2fs_fault_name[type], \ - __func__, __builtin_return_address(0)) -static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) +#define time_to_inject(sbi, type) __time_to_inject(sbi, type, __func__, \ + __builtin_return_address(0)) +static inline bool __time_to_inject(struct f2fs_sb_info *sbi, int type, + const char *func, const char *parent_func) { struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info; @@ -1885,12 +1883,14 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) atomic_inc(&ffi->inject_ops); if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) { atomic_set(&ffi->inject_ops, 0); + printk_ratelimited("%sF2FS-fs (%s) : inject %s in %s of %pS\n", + KERN_INFO, sbi->sb->s_id, f2fs_fault_name[type], + func, parent_func); return true; } return false; } #else -#define f2fs_show_injection_info(sbi, type) do { } while (0) static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type) { return false; @@ -2223,10 +2223,8 @@ static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) static inline int f2fs_trylock_op(struct f2fs_sb_info *sbi) { - if (time_to_inject(sbi, FAULT_LOCK_OP)) { - f2fs_show_injection_info(sbi, FAULT_LOCK_OP); + if (time_to_inject(sbi, FAULT_LOCK_OP)) return 0; - } return f2fs_down_read_trylock(&sbi->cp_rwsem); } @@ -2314,7 +2312,6 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, return ret; if (time_to_inject(sbi, FAULT_BLOCK)) { - f2fs_show_injection_info(sbi, FAULT_BLOCK); release = *count; goto release_quota; } @@ -2594,10 +2591,8 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, return err; } - if (time_to_inject(sbi, FAULT_BLOCK)) { - f2fs_show_injection_info(sbi, FAULT_BLOCK); + if (time_to_inject(sbi, FAULT_BLOCK)) goto enospc; - } spin_lock(&sbi->stat_lock); @@ -2721,11 +2716,8 @@ static inline struct page *f2fs_grab_cache_page(struct address_space *mapping, if (page) return page; - if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC)) { - f2fs_show_injection_info(F2FS_M_SB(mapping), - FAULT_PAGE_ALLOC); + if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC)) return NULL; - } } if (!for_write) @@ -2742,10 +2734,8 @@ static inline struct page *f2fs_pagecache_get_page( struct address_space *mapping, pgoff_t index, int fgp_flags, gfp_t gfp_mask) { - if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_GET)) { - f2fs_show_injection_info(F2FS_M_SB(mapping), FAULT_PAGE_GET); + if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_GET)) return NULL; - } return pagecache_get_page(mapping, index, fgp_flags, gfp_mask); } @@ -2795,10 +2785,8 @@ static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep, if (nofail) return f2fs_kmem_cache_alloc_nofail(cachep, flags); - if (time_to_inject(sbi, FAULT_SLAB_ALLOC)) { - f2fs_show_injection_info(sbi, FAULT_SLAB_ALLOC); + if (time_to_inject(sbi, FAULT_SLAB_ALLOC)) return NULL; - } return kmem_cache_alloc(cachep, flags); } @@ -3372,10 +3360,8 @@ static inline bool is_dot_dotdot(const u8 *name, size_t len) static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi, size_t size, gfp_t flags) { - if (time_to_inject(sbi, FAULT_KMALLOC)) { - f2fs_show_injection_info(sbi, FAULT_KMALLOC); + if (time_to_inject(sbi, FAULT_KMALLOC)) return NULL; - } return kmalloc(size, flags); } @@ -3389,10 +3375,8 @@ static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi, static inline void *f2fs_kvmalloc(struct f2fs_sb_info *sbi, size_t size, gfp_t flags) { - if (time_to_inject(sbi, FAULT_KVMALLOC)) { - f2fs_show_injection_info(sbi, FAULT_KVMALLOC); + if (time_to_inject(sbi, FAULT_KVMALLOC)) return NULL; - } return kvmalloc(size, flags); } diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 58b4200f7fdf..f5c1b7814954 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -782,10 +782,8 @@ int f2fs_truncate(struct inode *inode) trace_f2fs_truncate(inode); - if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE)) { - f2fs_show_injection_info(F2FS_I_SB(inode), FAULT_TRUNCATE); + if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE)) return -EIO; - } err = f2fs_dquot_initialize(inode); if (err) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 7444c392eab1..e59c006c10f7 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -72,11 +72,9 @@ static int gc_thread_func(void *data) continue; } - if (time_to_inject(sbi, FAULT_CHECKPOINT)) { - f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); + if (time_to_inject(sbi, FAULT_CHECKPOINT)) f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT); - } if (!sb_start_write_trylock(sbi->sb)) { stat_other_skip_bggc_count(sbi); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index ff6cf66ed46b..01b9e6f85f6b 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -809,10 +809,8 @@ retry: if (F2FS_HAS_BLOCKS(inode)) err = f2fs_truncate(inode); - if (time_to_inject(sbi, FAULT_EVICT_INODE)) { - f2fs_show_injection_info(sbi, FAULT_EVICT_INODE); + if (time_to_inject(sbi, FAULT_EVICT_INODE)) err = -EIO; - } if (!err) { f2fs_lock_op(sbi); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 558b318f7316..fbd1d25fecc2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -2541,10 +2541,8 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i = NULL; retry: - if (time_to_inject(sbi, FAULT_ALLOC_NID)) { - f2fs_show_injection_info(sbi, FAULT_ALLOC_NID); + if (time_to_inject(sbi, FAULT_ALLOC_NID)) return false; - } spin_lock(&nm_i->nid_list_lock); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index e2f95f46d298..ba8331434703 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -384,10 +384,8 @@ int f2fs_commit_atomic_write(struct inode *inode) */ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need) { - if (time_to_inject(sbi, FAULT_CHECKPOINT)) { - f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); + if (time_to_inject(sbi, FAULT_CHECKPOINT)) f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT); - } /* balance_fs_bg is able to be pending */ if (need && excess_cached_nats(sbi)) @@ -1140,7 +1138,6 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi, dc->len += len; if (time_to_inject(sbi, FAULT_DISCARD)) { - f2fs_show_injection_info(sbi, FAULT_DISCARD); err = -EIO; } else { err = __blkdev_issue_discard(bdev, diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1d057a4c6642..5fc83771042d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1371,10 +1371,8 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) { struct f2fs_inode_info *fi; - if (time_to_inject(F2FS_SB(sb), FAULT_SLAB_ALLOC)) { - f2fs_show_injection_info(F2FS_SB(sb), FAULT_SLAB_ALLOC); + if (time_to_inject(F2FS_SB(sb), FAULT_SLAB_ALLOC)) return NULL; - } fi = alloc_inode_sb(sb, f2fs_inode_cachep, GFP_F2FS_ZERO); if (!fi) @@ -2594,10 +2592,8 @@ retry: int f2fs_dquot_initialize(struct inode *inode) { - if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) { - f2fs_show_injection_info(F2FS_I_SB(inode), FAULT_DQUOT_INIT); + if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) return -ESRCH; - } return dquot_initialize(inode); } -- cgit v1.2.3 From e6261beb0c629403dc58997294dd521bd23664af Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 23 Jan 2023 17:46:01 +0800 Subject: f2fs: allow set compression option of files without blocks Files created by truncate have a size but no blocks, so they can be allowed to set compression option. Fixes: e1e8debec656 ("f2fs: add F2FS_IOC_SET_COMPRESS_OPTION ioctl") Signed-off-by: Yangtao Li Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f5c1b7814954..391da47761e3 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3941,7 +3941,7 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) goto out; } - if (inode->i_size != 0) { + if (F2FS_HAS_BLOCKS(inode)) { ret = -EFBIG; goto out; } -- cgit v1.2.3 From ae267fc1cfe9f941afcb90dc963ee6448dae73cf Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 9 Jan 2023 11:44:51 +0800 Subject: f2fs: fix to abort atomic write only during do_exist() Commit 7a10f0177e11 ("f2fs: don't give partially written atomic data from process crash") attempted to drop atomic write data after process crash, however, f2fs_abort_atomic_write() may be called from noncrash case, fix it by adding missed PF_EXITING check condition f2fs_file_flush(). - application crashs - do_exit - exit_signals -- sets PF_EXITING - exit_files - put_files_struct - close_files - filp_close - flush (f2fs_file_flush) - check atomic_write_task && PF_EXITING - f2fs_abort_atomic_write Fixes: 7a10f0177e11 ("f2fs: don't give partially written atomic data from process crash") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 391da47761e3..eaae2ad3957b 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1876,7 +1876,8 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) * until all the writers close its file. Since this should be done * before dropping file lock, it needs to do in ->flush. */ - if (F2FS_I(inode)->atomic_write_task == current) + if (F2FS_I(inode)->atomic_write_task == current && + (current->flags & PF_EXITING)) f2fs_abort_atomic_write(inode, true); return 0; } -- cgit v1.2.3 From a28bca0f47feb5cdfc22be0e563bd4da2aed74f7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 19 Jan 2023 07:36:21 +0100 Subject: f2fs: factor the read/write tracing logic into a helper Factor the logic to log a path for reads and writs into a helper shared between the read_iter and write_iter methods. Signed-off-by: Christoph Hellwig Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 61 +++++++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index eaae2ad3957b..65199574cd7d 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -4341,6 +4341,27 @@ out: return ret; } +static void f2fs_trace_rw_file_path(struct kiocb *iocb, size_t count, int rw) +{ + struct inode *inode = file_inode(iocb->ki_filp); + char *buf, *path; + + buf = f2fs_kmalloc(F2FS_I_SB(inode), PATH_MAX, GFP_KERNEL); + if (!buf) + return; + path = dentry_path_raw(file_dentry(iocb->ki_filp), buf, PATH_MAX); + if (IS_ERR(path)) + goto free_buf; + if (rw == WRITE) + trace_f2fs_datawrite_start(inode, iocb->ki_pos, count, + current->pid, path, current->comm); + else + trace_f2fs_dataread_start(inode, iocb->ki_pos, count, + current->pid, path, current->comm); +free_buf: + kfree(buf); +} + static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct inode *inode = file_inode(iocb->ki_filp); @@ -4350,24 +4371,9 @@ static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (!f2fs_is_compress_backend_ready(inode)) return -EOPNOTSUPP; - if (trace_f2fs_dataread_start_enabled()) { - char *p = f2fs_kmalloc(F2FS_I_SB(inode), PATH_MAX, GFP_KERNEL); - char *path; - - if (!p) - goto skip_read_trace; + if (trace_f2fs_dataread_start_enabled()) + f2fs_trace_rw_file_path(iocb, iov_iter_count(to), READ); - path = dentry_path_raw(file_dentry(iocb->ki_filp), p, PATH_MAX); - if (IS_ERR(path)) { - kfree(p); - goto skip_read_trace; - } - - trace_f2fs_dataread_start(inode, pos, iov_iter_count(to), - current->pid, path, current->comm); - kfree(p); - } -skip_read_trace: if (f2fs_should_use_dio(inode, iocb, to)) { ret = f2fs_dio_read_iter(iocb, to); } else { @@ -4673,24 +4679,9 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (preallocated < 0) { ret = preallocated; } else { - if (trace_f2fs_datawrite_start_enabled()) { - char *p = f2fs_kmalloc(F2FS_I_SB(inode), - PATH_MAX, GFP_KERNEL); - char *path; - - if (!p) - goto skip_write_trace; - path = dentry_path_raw(file_dentry(iocb->ki_filp), - p, PATH_MAX); - if (IS_ERR(path)) { - kfree(p); - goto skip_write_trace; - } - trace_f2fs_datawrite_start(inode, orig_pos, orig_count, - current->pid, path, current->comm); - kfree(p); - } -skip_write_trace: + if (trace_f2fs_datawrite_start_enabled()) + f2fs_trace_rw_file_path(iocb, orig_count, WRITE); + /* Do the actual write. */ ret = dio ? f2fs_dio_write_iter(iocb, from, &may_need_sync) : -- cgit v1.2.3 From 933141e4eb49d8b48721e2377835063a1e8fb823 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Sat, 28 Jan 2023 18:32:26 +0800 Subject: f2fs: fix to handle F2FS_IOC_START_ATOMIC_REPLACE in f2fs_compat_ioctl() Otherwise, 32-bits binary call ioctl(F2FS_IOC_START_ATOMIC_REPLACE) will fail in 64-bits kernel. Fixes: 41e8f85a75fc ("f2fs: introduce F2FS_IOC_START_ATOMIC_REPLACE") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 65199574cd7d..f05148a9dc99 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -4814,6 +4814,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC32_MOVE_RANGE: return f2fs_compat_ioc_move_range(file, arg); case F2FS_IOC_START_ATOMIC_WRITE: + case F2FS_IOC_START_ATOMIC_REPLACE: case F2FS_IOC_COMMIT_ATOMIC_WRITE: case F2FS_IOC_START_VOLATILE_WRITE: case F2FS_IOC_RELEASE_VOLATILE_WRITE: -- cgit v1.2.3 From 8c0ed062ce27f6b7f0a568cb241e2b4dd2d9e6a6 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 31 Jan 2023 22:47:00 +0800 Subject: f2fs: fix to update age extent correctly during truncation nr_free may be less than len, we should update age extent cache w/ range [fofs, len] rather than [fofs, nr_free]. Fixes: 71644dff4811 ("f2fs: add block_age-based extent cache") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f05148a9dc99..a83117325b87 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -617,7 +617,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count) fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) + ofs; f2fs_update_read_extent_cache_range(dn, fofs, 0, len); - f2fs_update_age_extent_cache_range(dn, fofs, nr_free); + f2fs_update_age_extent_cache_range(dn, fofs, len); dec_valid_block_count(sbi, dn->inode, nr_free); } dn->ofs_in_node = ofs; -- cgit v1.2.3 From a84153f939808102dfa10904aa0f743e734a3e1d Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 31 Jan 2023 22:47:01 +0800 Subject: f2fs: fix to update age extent in f2fs_do_zero_range() We should update age extent in f2fs_do_zero_range() like we did in f2fs_truncate_data_blocks_range(). Fixes: 71644dff4811 ("f2fs: add block_age-based extent cache") Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index a83117325b87..a17aca50c18c 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1494,6 +1494,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start, } f2fs_update_read_extent_cache_range(dn, start, 0, index - start); + f2fs_update_age_extent_cache_range(dn, start, index - start); return ret; } -- cgit v1.2.3 From 146949defda868378992171b9e42318b06fcd482 Mon Sep 17 00:00:00 2001 From: Jinyoung CHOI Date: Mon, 6 Feb 2023 20:56:00 +0900 Subject: f2fs: fix typos in comments This patch is to fix typos in f2fs files. Signed-off-by: Jinyoung Choi Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/checkpoint.c | 4 ++-- fs/f2fs/compress.c | 2 +- fs/f2fs/data.c | 8 ++++---- fs/f2fs/extent_cache.c | 4 ++-- fs/f2fs/file.c | 6 +++--- fs/f2fs/namei.c | 2 +- fs/f2fs/segment.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 89ce08b0ff7c..1369ec892a2c 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -792,7 +792,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) */ head = &im->ino_list; - /* loop for each orphan inode entry and write them in Jornal block */ + /* loop for each orphan inode entry and write them in journal block */ list_for_each_entry(orphan, head, list) { if (!page) { page = f2fs_grab_meta_page(sbi, start_blk++); @@ -1122,7 +1122,7 @@ retry: } else { /* * We should submit bio, since it exists several - * wribacking dentry pages in the freeing inode. + * writebacking dentry pages in the freeing inode. */ f2fs_submit_merged_write(sbi, DATA); cond_resched(); diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index e4851f7a43d8..b40dec3d7f79 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1225,7 +1225,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, loff_t psize; int i, err; - /* we should bypass data pages to proceed the kworkder jobs */ + /* we should bypass data pages to proceed the kworker jobs */ if (unlikely(f2fs_cp_error(sbi))) { mapping_set_error(cc->rpages[0]->mapping, -EIO); goto out_free; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d04220cc2d26..28e09682b056 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2386,7 +2386,7 @@ static int f2fs_mpage_readpages(struct inode *inode, #ifdef CONFIG_F2FS_FS_COMPRESSION if (f2fs_compressed_file(inode)) { - /* there are remained comressed pages, submit them */ + /* there are remained compressed pages, submit them */ if (!f2fs_cluster_can_merge_page(&cc, page->index)) { ret = f2fs_read_multi_pages(&cc, &bio, max_nr_pages, @@ -2792,7 +2792,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, trace_f2fs_writepage(page, DATA); - /* we should bypass data pages to proceed the kworkder jobs */ + /* we should bypass data pages to proceed the kworker jobs */ if (unlikely(f2fs_cp_error(sbi))) { mapping_set_error(page->mapping, -EIO); /* @@ -2911,7 +2911,7 @@ out: redirty_out: redirty_page_for_writepage(wbc, page); /* - * pageout() in MM traslates EAGAIN, so calls handle_write_error() + * pageout() in MM translates EAGAIN, so calls handle_write_error() * -> mapping_set_error() -> set_bit(AS_EIO, ...). * file_write_and_wait_range() will see EIO error, which is critical * to return value of fsync() followed by atomic_write failure to user. @@ -2945,7 +2945,7 @@ out: } /* - * This function was copied from write_cche_pages from mm/page-writeback.c. + * This function was copied from write_cache_pages from mm/page-writeback.c. * The major change is making write step of cold data page separately from * warm/hot data page. */ diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index aef308e871ab..8d922c592dae 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -233,7 +233,7 @@ struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi, * @prev_ex: extent before ofs * @next_ex: extent after ofs * @insert_p: insert point for new extent at ofs - * in order to simpfy the insertion after. + * in order to simplify the insertion after. * tree must stay unchanged between lookup and insertion. */ struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root, @@ -718,7 +718,7 @@ static void __update_extent_tree_range(struct inode *inode, if (!en) en = next_en; - /* 2. invlidate all extent nodes in range [fofs, fofs + len - 1] */ + /* 2. invalidate all extent nodes in range [fofs, fofs + len - 1] */ while (en && en->ei.fofs < end) { unsigned int org_end; int parts = 0; /* # of parts current extent split into */ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index a17aca50c18c..300eae8b5415 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -303,7 +303,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, * for OPU case, during fsync(), node can be persisted before * data when lower device doesn't support write barrier, result * in data corruption after SPO. - * So for strict fsync mode, force to use atomic write sematics + * So for strict fsync mode, force to use atomic write semantics * to keep write order in between data/node and last node to * avoid potential data corruption. */ @@ -1806,7 +1806,7 @@ static long f2fs_fallocate(struct file *file, int mode, return -EOPNOTSUPP; /* - * Pinned file should not support partial trucation since the block + * Pinned file should not support partial truncation since the block * can be used by applications. */ if ((f2fs_compressed_file(inode) || f2fs_is_pinned_file(inode)) && @@ -1856,7 +1856,7 @@ out: static int f2fs_release_file(struct inode *inode, struct file *filp) { /* - * f2fs_relase_file is called at every close calls. So we should + * f2fs_release_file is called at every close calls. So we should * not drop any inmemory pages by close called by other process. */ if (!(filp->f_mode & FMODE_WRITE) || diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 82923273f4bb..f9aafb7ac44d 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -963,7 +963,7 @@ static int f2fs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, /* * If new_inode is null, the below renaming flow will - * add a link in old_dir which can conver inline_dir. + * add a link in old_dir which can convert inline_dir. * After then, if we failed to get the entry due to other * reasons like ENOMEM, we had to remove the new entry. * Instead of adding such the error handling routine, let's diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 69b01b5c0ce0..ead3f35f501d 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3616,7 +3616,7 @@ void f2fs_wait_on_page_writeback(struct page *page, /* submit cached LFS IO */ f2fs_submit_merged_write_cond(sbi, NULL, page, 0, type); - /* sbumit cached IPU IO */ + /* submit cached IPU IO */ f2fs_submit_merged_ipu_write(sbi, NULL, page); if (ordered) { wait_on_page_writeback(page); -- cgit v1.2.3 From a46bebd502fe1a3bd1d22f64cedd93e7e7702693 Mon Sep 17 00:00:00 2001 From: Daeho Jeong Date: Thu, 9 Feb 2023 10:18:19 -0800 Subject: f2fs: synchronize atomic write aborts To fix a race condition between atomic write aborts, I use the inode lock and make COW inode to be re-usable thoroughout the whole atomic file inode lifetime. Reported-by: syzbot+823000d23b3400619f7c@syzkaller.appspotmail.com Fixes: 3db1de0e582c ("f2fs: change the current atomic write way") Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 44 +++++++++++++++++++++++++++++--------------- fs/f2fs/inode.c | 11 +++++++++-- fs/f2fs/segment.c | 3 --- fs/f2fs/super.c | 2 -- 4 files changed, 38 insertions(+), 22 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 300eae8b5415..6436c52e7913 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1863,7 +1863,10 @@ static int f2fs_release_file(struct inode *inode, struct file *filp) atomic_read(&inode->i_writecount) != 1) return 0; + inode_lock(inode); f2fs_abort_atomic_write(inode, true); + inode_unlock(inode); + return 0; } @@ -1878,8 +1881,12 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) * before dropping file lock, it needs to do in ->flush. */ if (F2FS_I(inode)->atomic_write_task == current && - (current->flags & PF_EXITING)) + (current->flags & PF_EXITING)) { + inode_lock(inode); f2fs_abort_atomic_write(inode, true); + inode_unlock(inode); + } + return 0; } @@ -2085,19 +2092,28 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) goto out; } - /* Create a COW inode for atomic write */ - pinode = f2fs_iget(inode->i_sb, fi->i_pino); - if (IS_ERR(pinode)) { - f2fs_up_write(&fi->i_gc_rwsem[WRITE]); - ret = PTR_ERR(pinode); - goto out; - } + /* Check if the inode already has a COW inode */ + if (fi->cow_inode == NULL) { + /* Create a COW inode for atomic write */ + pinode = f2fs_iget(inode->i_sb, fi->i_pino); + if (IS_ERR(pinode)) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + ret = PTR_ERR(pinode); + goto out; + } - ret = f2fs_get_tmpfile(mnt_userns, pinode, &fi->cow_inode); - iput(pinode); - if (ret) { - f2fs_up_write(&fi->i_gc_rwsem[WRITE]); - goto out; + ret = f2fs_get_tmpfile(mnt_userns, pinode, &fi->cow_inode); + iput(pinode); + if (ret) { + f2fs_up_write(&fi->i_gc_rwsem[WRITE]); + goto out; + } + + set_inode_flag(fi->cow_inode, FI_COW_FILE); + clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); + } else { + /* Reuse the already created COW inode */ + f2fs_do_truncate_blocks(fi->cow_inode, 0, true); } f2fs_write_inode(inode, NULL); @@ -2105,8 +2121,6 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, bool truncate) stat_inc_atomic_inode(inode); set_inode_flag(inode, FI_ATOMIC_FILE); - set_inode_flag(fi->cow_inode, FI_COW_FILE); - clear_inode_flag(fi->cow_inode, FI_INLINE_DATA); isize = i_size_read(inode); fi->original_i_size = isize; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 2c250120d5da..7d2e2c0dba65 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -767,11 +767,18 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) void f2fs_evict_inode(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - nid_t xnid = F2FS_I(inode)->i_xattr_nid; + struct f2fs_inode_info *fi = F2FS_I(inode); + nid_t xnid = fi->i_xattr_nid; int err = 0; f2fs_abort_atomic_write(inode, true); + if (fi->cow_inode) { + clear_inode_flag(fi->cow_inode, FI_COW_FILE); + iput(fi->cow_inode); + fi->cow_inode = NULL; + } + trace_f2fs_evict_inode(inode); truncate_inode_pages_final(&inode->i_data); @@ -856,7 +863,7 @@ no_delete: stat_dec_inline_inode(inode); stat_dec_compr_inode(inode); stat_sub_compr_blocks(inode, - atomic_read(&F2FS_I(inode)->i_compr_blocks)); + atomic_read(&fi->i_compr_blocks)); if (likely(!f2fs_cp_error(sbi) && !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index ead3f35f501d..719329c1808c 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -192,9 +192,6 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) if (!f2fs_is_atomic_file(inode)) return; - clear_inode_flag(fi->cow_inode, FI_COW_FILE); - iput(fi->cow_inode); - fi->cow_inode = NULL; release_atomic_write_cnt(inode); clear_inode_flag(inode, FI_ATOMIC_COMMITTED); clear_inode_flag(inode, FI_ATOMIC_REPLACE); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index c11a161ba5be..aa55dc12aff2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1427,8 +1427,6 @@ static int f2fs_drop_inode(struct inode *inode) atomic_inc(&inode->i_count); spin_unlock(&inode->i_lock); - f2fs_abort_atomic_write(inode, true); - /* should remain fi->extent_tree for writepage */ f2fs_destroy_extent_node(inode); -- cgit v1.2.3 From ddf1eca4fc5a4038cb323306f51fbba34ce3f4d2 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 15 Feb 2023 14:17:01 +0800 Subject: f2fs: drop unnecessary arg for f2fs_ioc_*() They are not used, let's remove them. Signed-off-by: Yangtao Li Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 6436c52e7913..ca1720fc1187 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2539,7 +2539,7 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg) return __f2fs_ioc_gc_range(filp, &range); } -static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg) +static int f2fs_ioc_write_checkpoint(struct file *filp) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -3253,7 +3253,7 @@ int f2fs_precache_extents(struct inode *inode) return 0; } -static int f2fs_ioc_precache_extents(struct file *filp, unsigned long arg) +static int f2fs_ioc_precache_extents(struct file *filp) { return f2fs_precache_extents(file_inode(filp)); } @@ -4010,7 +4010,7 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len) return ret; } -static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) +static int f2fs_ioc_decompress_file(struct file *filp) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -4083,7 +4083,7 @@ out: return ret; } -static int f2fs_ioc_compress_file(struct file *filp, unsigned long arg) +static int f2fs_ioc_compress_file(struct file *filp) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); @@ -4199,7 +4199,7 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case F2FS_IOC_GARBAGE_COLLECT_RANGE: return f2fs_ioc_gc_range(filp, arg); case F2FS_IOC_WRITE_CHECKPOINT: - return f2fs_ioc_write_checkpoint(filp, arg); + return f2fs_ioc_write_checkpoint(filp); case F2FS_IOC_DEFRAGMENT: return f2fs_ioc_defragment(filp, arg); case F2FS_IOC_MOVE_RANGE: @@ -4213,7 +4213,7 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_PIN_FILE: return f2fs_ioc_set_pin_file(filp, arg); case F2FS_IOC_PRECACHE_EXTENTS: - return f2fs_ioc_precache_extents(filp, arg); + return f2fs_ioc_precache_extents(filp); case F2FS_IOC_RESIZE_FS: return f2fs_ioc_resize_fs(filp, arg); case FS_IOC_ENABLE_VERITY: @@ -4239,9 +4239,9 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case F2FS_IOC_SET_COMPRESS_OPTION: return f2fs_ioc_set_compress_option(filp, arg); case F2FS_IOC_DECOMPRESS_FILE: - return f2fs_ioc_decompress_file(filp, arg); + return f2fs_ioc_decompress_file(filp); case F2FS_IOC_COMPRESS_FILE: - return f2fs_ioc_compress_file(filp, arg); + return f2fs_ioc_compress_file(filp); default: return -ENOTTY; } -- cgit v1.2.3