Commit 6638d682 authored by Ryusuke Konishi's avatar Ryusuke Konishi Committed by sanglipeng1
Browse files

nilfs2: replace WARN_ONs for invalid DAT metadata block requests

stable inclusion
from stable-v5.10.210
commit c90746c03b3c41707f7e8518c723f0b69948a264
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAE52H

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c90746c03b3c41707f7e8518c723f0b69948a264

--------------------------------

commit 5124a0a5 upstream.

If DAT metadata file block access fails due to corruption of the DAT file
or abnormal virtual block numbers held by b-trees or inodes, a kernel
warning is generated.

This replaces the WARN_ONs by error output, so that a kernel, booted with
panic_on_warn, does not panic.  This patch also replaces the detected
return code -ENOENT with another internal code -EINVAL to notify the bmap
layer of metadata corruption.  When the bmap layer sees -EINVAL, it
handles the abnormal situation with nilfs_bmap_convert_error() and finally
returns code -EIO as it should.

Link: https://lkml.kernel.org/r/0000000000005cc3d205ea23ddcf@google.com
Link: https://lkml.kernel.org/r/20230126164114.6911-1-konishi.ryusuke@gmail.com


Signed-off-by: default avatarRyusuke Konishi <konishi.ryusuke@gmail.com>
Reported-by: default avatar <syzbot+5d5d25f90f195a3cfcb4@syzkaller.appspotmail.com>
Tested-by: default avatarRyusuke Konishi <konishi.ryusuke@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng1 <sanglipeng1@jd.com>
parent 81b047fa
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -40,8 +40,21 @@ static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
static int nilfs_dat_prepare_entry(struct inode *dat,
				   struct nilfs_palloc_req *req, int create)
{
	return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
	int ret;

	ret = nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
					   create, &req->pr_entry_bh);
	if (unlikely(ret == -ENOENT)) {
		nilfs_err(dat->i_sb,
			  "DAT doesn't have a block to manage vblocknr = %llu",
			  (unsigned long long)req->pr_entry_nr);
		/*
		 * Return internal code -EINVAL to notify bmap layer of
		 * metadata corruption.
		 */
		ret = -EINVAL;
	}
	return ret;
}

static void nilfs_dat_commit_entry(struct inode *dat,
@@ -123,11 +136,7 @@ static void nilfs_dat_commit_free(struct inode *dat,

int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
{
	int ret;

	ret = nilfs_dat_prepare_entry(dat, req, 0);
	WARN_ON(ret == -ENOENT);
	return ret;
	return nilfs_dat_prepare_entry(dat, req, 0);
}

void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
@@ -154,10 +163,8 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
	int ret;

	ret = nilfs_dat_prepare_entry(dat, req, 0);
	if (ret < 0) {
		WARN_ON(ret == -ENOENT);
	if (ret < 0)
		return ret;
	}

	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,