Commit 50a472bb authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

f2fs: do not return EFSCORRUPTED, but try to run online repair



If we return the error, there's no way to recover the status as of now, since
fsck does not fix the xattr boundary issue.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent a5e80e18
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2750,7 +2750,9 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page)
	f2fs_update_inode_page(inode);

	/* 3: update and set xattr node page dirty */
	memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE);
	if (page)
		memcpy(F2FS_NODE(xpage), F2FS_NODE(page),
				VALID_XATTR_BLOCK_SIZE);

	set_page_dirty(xpage);
	f2fs_put_page(xpage, 1);
+13 −7
Original line number Diff line number Diff line
@@ -364,10 +364,10 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,

	*xe = __find_xattr(cur_addr, last_txattr_addr, NULL, index, len, name);
	if (!*xe) {
		f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
		f2fs_err(F2FS_I_SB(inode), "lookup inode (%lu) has corrupted xattr",
								inode->i_ino);
		set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
		err = -EFSCORRUPTED;
		err = -ENODATA;
		f2fs_handle_error(F2FS_I_SB(inode),
					ERROR_CORRUPTED_XATTR);
		goto out;
@@ -584,13 +584,12 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)

		if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
			(void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
			f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
			f2fs_err(F2FS_I_SB(inode), "list inode (%lu) has corrupted xattr",
						inode->i_ino);
			set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
			error = -EFSCORRUPTED;
			f2fs_handle_error(F2FS_I_SB(inode),
						ERROR_CORRUPTED_XATTR);
			goto cleanup;
			break;
		}

		if (!prefix)
@@ -650,7 +649,7 @@ static int __f2fs_setxattr(struct inode *inode, int index,

	if (size > MAX_VALUE_LEN(inode))
		return -E2BIG;

retry:
	error = read_all_xattrs(inode, ipage, &base_addr);
	if (error)
		return error;
@@ -660,7 +659,14 @@ static int __f2fs_setxattr(struct inode *inode, int index,
	/* find entry with wanted name. */
	here = __find_xattr(base_addr, last_base_addr, NULL, index, len, name);
	if (!here) {
		f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
		if (!F2FS_I(inode)->i_xattr_nid) {
			f2fs_notice(F2FS_I_SB(inode),
				"recover xattr in inode (%lu)", inode->i_ino);
			f2fs_recover_xattr_data(inode, NULL);
			kfree(base_addr);
			goto retry;
		}
		f2fs_err(F2FS_I_SB(inode), "set inode (%lu) has corrupted xattr",
								inode->i_ino);
		set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
		error = -EFSCORRUPTED;