public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] btrfs: fix the uninitialized btrfs_bio::iter
@ 2022-03-17  0:23 Qu Wenruo
  2022-03-17  2:54 ` kernel test robot
  2022-03-18 16:35 ` David Sterba
  0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2022-03-17  0:23 UTC (permalink / raw)
  To: linux-btrfs

[BUG]
There are reports about compression crash with error injection, mostly
triggering the following ASSERT()s in dec_and_test_compressed_bio():

	ASSERT(btrfs_bio(bio)->iter.bi_size);

The call trace triggered by generic/475 (needs compress mount option)
looks like this:

  assertion failed: btrfs_bio(bio)->iter.bi_size, in fs/btrfs/compression.c:213
  ------------[ cut here ]------------
  kernel BUG at fs/btrfs/ctree.h:3551!
  invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
  CPU: 5 PID: 6548 Comm: fsstress Tainted: G           OE     5.17.0-rc7-custom+ #10
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  RIP: 0010:assertfail.constprop.0+0x18/0x1a [btrfs]
  Call Trace:
   <TASK>
   dec_and_test_compressed_bio.cold+0x16/0x2c [btrfs]
   end_compressed_bio_read+0x37/0x170 [btrfs]
   btrfs_submit_compressed_read+0x803/0x820 [btrfs]
   submit_one_bio+0xc7/0x100 [btrfs]
   btrfs_readpage+0xec/0x130 [btrfs]
   filemap_read_folio+0x53/0xf0
   filemap_get_pages+0x6f3/0xa10
   filemap_read+0x1d6/0x520
   new_sync_read+0x24e/0x360
   vfs_read+0x1a1/0x2a0
   ksys_read+0xc9/0x160
   do_syscall_64+0x3b/0x90
   entry_SYSCALL_64_after_hwframe+0x44/0xae

[CAUSE]
Unlike regular IO path, we will initialize btrfs_bio::iter in
btrfs_map_bio(), for error path, we have to manually initialize
btrfs_bio::iter before calling the endio function.

In above case, due to injected errors, we go to finish_cb: tag directly
without submitting with btrfs_map_bio() call.

This leaves btrfs_bio::iter for the compressed bio uninitialized and
caught by the ASSERT().

[FIX]
Fix it by calling btrfs_bio_save_iter() before we call endio for the
compressed bio.

Please fold this fix into commit "btrfs: make
dec_and_test_compressed_bio() to be split bio compatible".

If needed, I can update the series and resend, but if this is the only
problem, it may be better not to flood the list with 17 patches.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/compression.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 0bf694038c61..2df034f6194c 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -582,6 +582,7 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
 finish_cb:
 	if (bio) {
 		bio->bi_status = ret;
+		btrfs_bio_save_iter(btrfs_bio(bio));
 		bio_endio(bio);
 	}
 	/* Last byte of @cb is submitted, endio will free @cb */
@@ -924,6 +925,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 finish_cb:
 	if (comp_bio) {
 		comp_bio->bi_status = ret;
+		btrfs_bio_save_iter(btrfs_bio(comp_bio));
 		bio_endio(comp_bio);
 	}
 	/* All bytes of @cb is submitted, endio will free @cb */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] btrfs: fix the uninitialized btrfs_bio::iter
  2022-03-17  0:23 [PATCH] btrfs: fix the uninitialized btrfs_bio::iter Qu Wenruo
@ 2022-03-17  2:54 ` kernel test robot
  2022-03-18 16:35 ` David Sterba
  1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2022-03-17  2:54 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs; +Cc: kbuild-all

Hi Qu,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on kdave/for-next]
[also build test ERROR on v5.17-rc8 next-20220316]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Qu-Wenruo/btrfs-fix-the-uninitialized-btrfs_bio-iter/20220317-082643
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
config: arm-randconfig-c002-20220314 (https://download.01.org/0day-ci/archive/20220317/202203171007.1LuEGp3u-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8712b95c5f74e4842f3b19b36417be829b2281b2
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Qu-Wenruo/btrfs-fix-the-uninitialized-btrfs_bio-iter/20220317-082643
        git checkout 8712b95c5f74e4842f3b19b36417be829b2281b2
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash fs/btrfs/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   fs/btrfs/compression.c: In function 'btrfs_submit_compressed_write':
>> fs/btrfs/compression.c:617:17: error: implicit declaration of function 'btrfs_bio_save_iter'; did you mean 'btrfs_do_write_iter'? [-Werror=implicit-function-declaration]
     617 |                 btrfs_bio_save_iter(btrfs_bio(bio));
         |                 ^~~~~~~~~~~~~~~~~~~
         |                 btrfs_do_write_iter
   cc1: some warnings being treated as errors


vim +617 fs/btrfs/compression.c

   494	
   495	/*
   496	 * worker function to build and submit bios for previously compressed pages.
   497	 * The corresponding pages in the inode should be marked for writeback
   498	 * and the compressed pages should have a reference on them for dropping
   499	 * when the IO is complete.
   500	 *
   501	 * This also checksums the file bytes and gets things ready for
   502	 * the end io hooks.
   503	 */
   504	blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
   505					 unsigned int len, u64 disk_start,
   506					 unsigned int compressed_len,
   507					 struct page **compressed_pages,
   508					 unsigned int nr_pages,
   509					 unsigned int write_flags,
   510					 struct cgroup_subsys_state *blkcg_css,
   511					 bool writeback)
   512	{
   513		struct btrfs_fs_info *fs_info = inode->root->fs_info;
   514		struct bio *bio = NULL;
   515		struct compressed_bio *cb;
   516		u64 cur_disk_bytenr = disk_start;
   517		u64 next_stripe_start;
   518		blk_status_t ret;
   519		int skip_sum = inode->flags & BTRFS_INODE_NODATASUM;
   520		const bool use_append = btrfs_use_zone_append(inode, disk_start);
   521		const unsigned int bio_op = use_append ? REQ_OP_ZONE_APPEND : REQ_OP_WRITE;
   522	
   523		ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
   524		       IS_ALIGNED(len, fs_info->sectorsize));
   525		cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
   526		if (!cb)
   527			return BLK_STS_RESOURCE;
   528		refcount_set(&cb->pending_sectors, compressed_len >> fs_info->sectorsize_bits);
   529		cb->status = BLK_STS_OK;
   530		cb->inode = &inode->vfs_inode;
   531		cb->start = start;
   532		cb->len = len;
   533		cb->mirror_num = 0;
   534		cb->compressed_pages = compressed_pages;
   535		cb->compressed_len = compressed_len;
   536		cb->writeback = writeback;
   537		cb->orig_bio = NULL;
   538		cb->nr_pages = nr_pages;
   539	
   540		while (cur_disk_bytenr < disk_start + compressed_len) {
   541			u64 offset = cur_disk_bytenr - disk_start;
   542			unsigned int index = offset >> PAGE_SHIFT;
   543			unsigned int real_size;
   544			unsigned int added;
   545			struct page *page = compressed_pages[index];
   546			bool submit = false;
   547	
   548			/* Allocate new bio if submitted or not yet allocated */
   549			if (!bio) {
   550				bio = alloc_compressed_bio(cb, cur_disk_bytenr,
   551					bio_op | write_flags, end_compressed_bio_write,
   552					&next_stripe_start);
   553				if (IS_ERR(bio)) {
   554					ret = errno_to_blk_status(PTR_ERR(bio));
   555					bio = NULL;
   556					goto finish_cb;
   557				}
   558			}
   559			/*
   560			 * We should never reach next_stripe_start start as we will
   561			 * submit comp_bio when reach the boundary immediately.
   562			 */
   563			ASSERT(cur_disk_bytenr != next_stripe_start);
   564	
   565			/*
   566			 * We have various limits on the real read size:
   567			 * - stripe boundary
   568			 * - page boundary
   569			 * - compressed length boundary
   570			 */
   571			real_size = min_t(u64, U32_MAX, next_stripe_start - cur_disk_bytenr);
   572			real_size = min_t(u64, real_size, PAGE_SIZE - offset_in_page(offset));
   573			real_size = min_t(u64, real_size, compressed_len - offset);
   574			ASSERT(IS_ALIGNED(real_size, fs_info->sectorsize));
   575	
   576			if (use_append)
   577				added = bio_add_zone_append_page(bio, page, real_size,
   578						offset_in_page(offset));
   579			else
   580				added = bio_add_page(bio, page, real_size,
   581						offset_in_page(offset));
   582			/* Reached zoned boundary */
   583			if (added == 0)
   584				submit = true;
   585	
   586			cur_disk_bytenr += added;
   587			/* Reached stripe boundary */
   588			if (cur_disk_bytenr == next_stripe_start)
   589				submit = true;
   590	
   591			/* Finished the range */
   592			if (cur_disk_bytenr == disk_start + compressed_len)
   593				submit = true;
   594	
   595			if (submit) {
   596				if (!skip_sum) {
   597					ret = btrfs_csum_one_bio(inode, bio, start, true);
   598					if (ret)
   599						goto finish_cb;
   600				}
   601	
   602				ret = submit_compressed_bio(fs_info, cb, bio, 0);
   603				if (ret)
   604					goto finish_cb;
   605				bio = NULL;
   606			}
   607			cond_resched();
   608		}
   609		if (blkcg_css)
   610			kthread_associate_blkcg(NULL);
   611	
   612		return 0;
   613	
   614	finish_cb:
   615		if (bio) {
   616			bio->bi_status = ret;
 > 617			btrfs_bio_save_iter(btrfs_bio(bio));
   618			bio_endio(bio);
   619		}
   620		/* Last byte of @cb is submitted, endio will free @cb */
   621		if (cur_disk_bytenr == disk_start + compressed_len)
   622			return ret;
   623	
   624		wait_var_event(cb, refcount_read(&cb->pending_sectors) ==
   625				   (disk_start + compressed_len - cur_disk_bytenr) >>
   626				   fs_info->sectorsize_bits);
   627		/*
   628		 * Even with previous bio ended, we should still have io not yet
   629		 * submitted, thus need to finish manually.
   630		 */
   631		ASSERT(refcount_read(&cb->pending_sectors));
   632		/* Now we are the only one referring @cb, can finish it safely. */
   633		finish_compressed_bio_write(cb);
   634		return ret;
   635	}
   636	

---
0-DAY CI Kernel Test Service
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] btrfs: fix the uninitialized btrfs_bio::iter
  2022-03-17  0:23 [PATCH] btrfs: fix the uninitialized btrfs_bio::iter Qu Wenruo
  2022-03-17  2:54 ` kernel test robot
@ 2022-03-18 16:35 ` David Sterba
  1 sibling, 0 replies; 3+ messages in thread
From: David Sterba @ 2022-03-18 16:35 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs

On Thu, Mar 17, 2022 at 08:23:12AM +0800, Qu Wenruo wrote:
> [BUG]
> There are reports about compression crash with error injection, mostly
> triggering the following ASSERT()s in dec_and_test_compressed_bio():
> 
> 	ASSERT(btrfs_bio(bio)->iter.bi_size);
> 
> The call trace triggered by generic/475 (needs compress mount option)
> looks like this:
> 
>   assertion failed: btrfs_bio(bio)->iter.bi_size, in fs/btrfs/compression.c:213
>   ------------[ cut here ]------------
>   kernel BUG at fs/btrfs/ctree.h:3551!
>   invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
>   CPU: 5 PID: 6548 Comm: fsstress Tainted: G           OE     5.17.0-rc7-custom+ #10
>   Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
>   RIP: 0010:assertfail.constprop.0+0x18/0x1a [btrfs]
>   Call Trace:
>    <TASK>
>    dec_and_test_compressed_bio.cold+0x16/0x2c [btrfs]
>    end_compressed_bio_read+0x37/0x170 [btrfs]
>    btrfs_submit_compressed_read+0x803/0x820 [btrfs]
>    submit_one_bio+0xc7/0x100 [btrfs]
>    btrfs_readpage+0xec/0x130 [btrfs]
>    filemap_read_folio+0x53/0xf0
>    filemap_get_pages+0x6f3/0xa10
>    filemap_read+0x1d6/0x520
>    new_sync_read+0x24e/0x360
>    vfs_read+0x1a1/0x2a0
>    ksys_read+0xc9/0x160
>    do_syscall_64+0x3b/0x90
>    entry_SYSCALL_64_after_hwframe+0x44/0xae
> 
> [CAUSE]
> Unlike regular IO path, we will initialize btrfs_bio::iter in
> btrfs_map_bio(), for error path, we have to manually initialize
> btrfs_bio::iter before calling the endio function.
> 
> In above case, due to injected errors, we go to finish_cb: tag directly
> without submitting with btrfs_map_bio() call.
> 
> This leaves btrfs_bio::iter for the compressed bio uninitialized and
> caught by the ASSERT().
> 
> [FIX]
> Fix it by calling btrfs_bio_save_iter() before we call endio for the
> compressed bio.
> 
> Please fold this fix into commit "btrfs: make
> dec_and_test_compressed_bio() to be split bio compatible".
> 
> If needed, I can update the series and resend, but if this is the only
> problem, it may be better not to flood the list with 17 patches.

No need to resend, fixup folded to the patch and the series will be in
for-next again, thanks.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-03-18 16:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-17  0:23 [PATCH] btrfs: fix the uninitialized btrfs_bio::iter Qu Wenruo
2022-03-17  2:54 ` kernel test robot
2022-03-18 16:35 ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox