Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 May 2018 19:29:35 +0000 (UTC)
From:      Fedor Uporov <fsu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r333585 - head/sys/fs/ext2fs
Message-ID:  <201805131929.w4DJTZtZ072481@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: fsu
Date: Sun May 13 19:29:35 2018
New Revision: 333585
URL: https://svnweb.freebsd.org/changeset/base/333585

Log:
  Fix on-disk inode checksum calculation logic.
  
  Reviewed by:    pfg
  MFC after:      3 months
  
  Differential Revision:    https://reviews.freebsd.org/D15395

Modified:
  head/sys/fs/ext2fs/ext2_csum.c
  head/sys/fs/ext2fs/ext2_inode_cnv.c

Modified: head/sys/fs/ext2fs/ext2_csum.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_csum.c	Sun May 13 19:19:10 2018	(r333584)
+++ head/sys/fs/ext2fs/ext2_csum.c	Sun May 13 19:29:35 2018	(r333585)
@@ -535,29 +535,42 @@ static uint32_t
 ext2_ei_csum(struct inode *ip, struct ext2fs_dinode *ei)
 {
 	struct m_ext2fs *fs;
-	uint16_t old_hi;
-	uint32_t inum, gen, crc;
+	uint32_t inode_csum_seed, inum, gen, crc;
+	uint16_t dummy_csum = 0;
+	unsigned int offset, csum_size;
 
 	fs = ip->i_e2fs;
-
-	ei->e2di_chksum_lo = 0;
-	if ((EXT2_INODE_SIZE(ip->i_e2fs) > E2FS_REV0_INODE_SIZE &&
-	    ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) {
-		old_hi = ei->e2di_chksum_hi;
-		ei->e2di_chksum_hi = 0;
-	}
-
+	offset = offsetof(struct ext2fs_dinode, e2di_chksum_lo);
+	csum_size = sizeof(dummy_csum);
 	inum = ip->i_number;
 	gen = ip->i_gen;
+	crc = calculate_crc32c(fs->e2fs_csum_seed,
+	    (uint8_t *)&inum, sizeof(inum));
+	inode_csum_seed = calculate_crc32c(crc,
+	    (uint8_t *)&gen, sizeof(gen));
 
-	crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&inum, sizeof(inum));
-	crc = calculate_crc32c(crc, (uint8_t *)&gen, sizeof(gen));
-	crc = calculate_crc32c(crc, (uint8_t *)ei, fs->e2fs->e2fs_inode_size);
+	crc = calculate_crc32c(inode_csum_seed, (uint8_t *)ei, offset);
+	crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum, csum_size);
+	offset += csum_size;
+	crc = calculate_crc32c(crc, (uint8_t *)ei + offset,
+	    E2FS_REV0_INODE_SIZE - offset);
 
-	if ((EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE &&
-	    ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END))
-		ei->e2di_chksum_hi = old_hi;
+	if (EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE) {
+		offset = offsetof(struct ext2fs_dinode, e2di_chksum_hi);
+		crc = calculate_crc32c(crc, (uint8_t *)ei +
+		    E2FS_REV0_INODE_SIZE, offset - E2FS_REV0_INODE_SIZE);
 
+		if ((EXT2_INODE_SIZE(ip->i_e2fs) > E2FS_REV0_INODE_SIZE &&
+		    ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) {
+			crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum,
+			    csum_size);
+			offset += csum_size;
+		}
+
+		crc = calculate_crc32c(crc, (uint8_t *)ei + offset,
+		    EXT2_INODE_SIZE(fs) - offset);
+	}
+
 	return (crc);
 }
 
@@ -573,10 +586,6 @@ ext2_ei_csum_verify(struct inode *ip, struct ext2fs_di
 	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
 		return (0);
 
-	/* Check case, when dinode was not initialized */
-	if (!memcmp(ei, &ei_zero, sizeof(struct ext2fs_dinode)))
-		return (0);
-
 	provided = ei->e2di_chksum_lo;
 	calculated = ext2_ei_csum(ip, ei);
 
@@ -587,8 +596,17 @@ ext2_ei_csum_verify(struct inode *ip, struct ext2fs_di
 	} else
 		calculated &= 0xFFFF;
 
-	if (provided != calculated)
+	if (provided != calculated) {
+		/*
+		 * If it is first time used dinode,
+		 * it is expected that it will be zeroed
+		 * and we will not return checksum error in this case.
+		 */
+		if (!memcmp(ei, &ei_zero, sizeof(struct ext2fs_dinode)))
+			return (0);
+
 		return (EIO);
+	}
 
 	return (0);
 }

Modified: head/sys/fs/ext2fs/ext2_inode_cnv.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_inode_cnv.c	Sun May 13 19:19:10 2018	(r333584)
+++ head/sys/fs/ext2fs/ext2_inode_cnv.c	Sun May 13 19:29:35 2018	(r333585)
@@ -92,10 +92,7 @@ ext2_print_inode(struct inode *in)
 int
 ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
 {
-	struct m_ext2fs *fs;
-	const static struct ext2fs_dinode ei_zero;
 
-	fs = ip->i_e2fs;
 	ip->i_nlink = ei->e2di_nlink;
 	/*
 	 * Godmar thinks - if the link count is zero, then the inode is
@@ -139,11 +136,7 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
 
 	memcpy(ip->i_data, ei->e2di_blocks, sizeof(ei->e2di_blocks));
 
-	if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM) &&
-	    memcmp(ei, &ei_zero, EXT2_INODE_SIZE(fs)))
-		return (ext2_ei_csum_verify(ip, ei));
-
-	return (0);
+	return (ext2_ei_csum_verify(ip, ei));
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805131929.w4DJTZtZ072481>