[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <202602041239.JFyNwVcg-lkp@intel.com>
Date: Wed, 4 Feb 2026 12:21:41 +0800
From: kernel test robot <lkp@...el.com>
To: Zhang Yi <yi.zhang@...wei.com>, linux-ext4@...r.kernel.org
Cc: oe-kbuild-all@...ts.linux.dev, linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org, tytso@....edu,
adilger.kernel@...ger.ca, jack@...e.cz, ojaswin@...ux.ibm.com,
ritesh.list@...il.com, hch@...radead.org, djwong@...nel.org,
yi.zhang@...wei.com, yi.zhang@...weicloud.com, yizhang089@...il.com,
libaokun1@...wei.com, yangerkun@...wei.com, yukuai@...as.com
Subject: Re: [PATCH -next v2 03/22] ext4: only order data when partially
block truncating down
Hi Zhang,
kernel test robot noticed the following build warnings:
[auto build test WARNING on next-20260202]
url: https://github.com/intel-lab-lkp/linux/commits/Zhang-Yi/ext4-make-ext4_block_zero_page_range-pass-out-did_zero/20260203-144244
base: next-20260202
patch link: https://lore.kernel.org/r/20260203062523.3869120-4-yi.zhang%40huawei.com
patch subject: [PATCH -next v2 03/22] ext4: only order data when partially block truncating down
config: riscv-randconfig-r071-20260204 (https://download.01.org/0day-ci/archive/20260204/202602041239.JFyNwVcg-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 9b8addffa70cee5b2acc5454712d9cf78ce45710)
smatch version: v0.5.0-8994-gd50c5a4c
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@...el.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602041239.JFyNwVcg-lkp@intel.com/
New smatch warnings:
fs/ext4/inode.c:4577 ext4_truncate() warn: unsigned 'zero_len' is never less than zero.
Old smatch warnings:
fs/ext4/inode.c:2651 mpage_prepare_extent_to_map() warn: missing error code 'err'
fs/ext4/inode.c:5129 check_igot_inode() warn: missing unwind goto?
vim +/zero_len +4577 fs/ext4/inode.c
4494
4495 /*
4496 * ext4_truncate()
4497 *
4498 * We block out ext4_get_block() block instantiations across the entire
4499 * transaction, and VFS/VM ensures that ext4_truncate() cannot run
4500 * simultaneously on behalf of the same inode.
4501 *
4502 * As we work through the truncate and commit bits of it to the journal there
4503 * is one core, guiding principle: the file's tree must always be consistent on
4504 * disk. We must be able to restart the truncate after a crash.
4505 *
4506 * The file's tree may be transiently inconsistent in memory (although it
4507 * probably isn't), but whenever we close off and commit a journal transaction,
4508 * the contents of (the filesystem + the journal) must be consistent and
4509 * restartable. It's pretty simple, really: bottom up, right to left (although
4510 * left-to-right works OK too).
4511 *
4512 * Note that at recovery time, journal replay occurs *before* the restart of
4513 * truncate against the orphan inode list.
4514 *
4515 * The committed inode has the new, desired i_size (which is the same as
4516 * i_disksize in this case). After a crash, ext4_orphan_cleanup() will see
4517 * that this inode's truncate did not complete and it will again call
4518 * ext4_truncate() to have another go. So there will be instantiated blocks
4519 * to the right of the truncation point in a crashed ext4 filesystem. But
4520 * that's fine - as long as they are linked from the inode, the post-crash
4521 * ext4_truncate() run will find them and release them.
4522 */
4523 int ext4_truncate(struct inode *inode)
4524 {
4525 struct ext4_inode_info *ei = EXT4_I(inode);
4526 unsigned int credits;
4527 int err = 0, err2;
4528 handle_t *handle;
4529 struct address_space *mapping = inode->i_mapping;
4530
4531 /*
4532 * There is a possibility that we're either freeing the inode
4533 * or it's a completely new inode. In those cases we might not
4534 * have i_rwsem locked because it's not necessary.
4535 */
4536 if (!(inode_state_read_once(inode) & (I_NEW | I_FREEING)))
4537 WARN_ON(!inode_is_locked(inode));
4538 trace_ext4_truncate_enter(inode);
4539
4540 if (!ext4_can_truncate(inode))
4541 goto out_trace;
4542
4543 if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
4544 ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
4545
4546 if (ext4_has_inline_data(inode)) {
4547 int has_inline = 1;
4548
4549 err = ext4_inline_data_truncate(inode, &has_inline);
4550 if (err || has_inline)
4551 goto out_trace;
4552 }
4553
4554 /* If we zero-out tail of the page, we have to create jinode for jbd2 */
4555 if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
4556 err = ext4_inode_attach_jinode(inode);
4557 if (err)
4558 goto out_trace;
4559 }
4560
4561 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
4562 credits = ext4_chunk_trans_extent(inode, 1);
4563 else
4564 credits = ext4_blocks_for_truncate(inode);
4565
4566 handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
4567 if (IS_ERR(handle)) {
4568 err = PTR_ERR(handle);
4569 goto out_trace;
4570 }
4571
4572 if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
4573 unsigned int zero_len;
4574
4575 zero_len = ext4_block_truncate_page(handle, mapping,
4576 inode->i_size);
> 4577 if (zero_len < 0) {
4578 err = zero_len;
4579 goto out_stop;
4580 }
4581 if (zero_len && !IS_DAX(inode) &&
4582 ext4_should_order_data(inode)) {
4583 err = ext4_jbd2_inode_add_write(handle, inode,
4584 inode->i_size, zero_len);
4585 if (err)
4586 goto out_stop;
4587 }
4588 }
4589
4590 /*
4591 * We add the inode to the orphan list, so that if this
4592 * truncate spans multiple transactions, and we crash, we will
4593 * resume the truncate when the filesystem recovers. It also
4594 * marks the inode dirty, to catch the new size.
4595 *
4596 * Implication: the file must always be in a sane, consistent
4597 * truncatable state while each transaction commits.
4598 */
4599 err = ext4_orphan_add(handle, inode);
4600 if (err)
4601 goto out_stop;
4602
4603 ext4_fc_track_inode(handle, inode);
4604 ext4_check_map_extents_env(inode);
4605
4606 down_write(&EXT4_I(inode)->i_data_sem);
4607 ext4_discard_preallocations(inode);
4608
4609 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
4610 err = ext4_ext_truncate(handle, inode);
4611 else
4612 ext4_ind_truncate(handle, inode);
4613
4614 up_write(&ei->i_data_sem);
4615 if (err)
4616 goto out_stop;
4617
4618 if (IS_SYNC(inode))
4619 ext4_handle_sync(handle);
4620
4621 out_stop:
4622 /*
4623 * If this was a simple ftruncate() and the file will remain alive,
4624 * then we need to clear up the orphan record which we created above.
4625 * However, if this was a real unlink then we were called by
4626 * ext4_evict_inode(), and we allow that function to clean up the
4627 * orphan info for us.
4628 */
4629 if (inode->i_nlink)
4630 ext4_orphan_del(handle, inode);
4631
4632 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
4633 err2 = ext4_mark_inode_dirty(handle, inode);
4634 if (unlikely(err2 && !err))
4635 err = err2;
4636 ext4_journal_stop(handle);
4637
4638 out_trace:
4639 trace_ext4_truncate_exit(inode);
4640 return err;
4641 }
4642
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Powered by blists - more mailing lists