shithub: lwext4

Download patch

ref: daf0d53c33e9427c3eb66b6e572798017249011b
parent: 72e4738cc40a0a1c2b1e944353badcd5a169c8f4
author: ngkaho1234 <[email protected]>
date: Mon Oct 26 06:30:03 EDT 2015

FIX: directory checksum entry not initialized.

--- a/lwext4/ext4_dir.c
+++ b/lwext4/ext4_dir.c
@@ -105,6 +105,14 @@
 	return 1;
 }
 
+/* checksumming functions */
+void initialize_dir_tail(struct ext4_directory_entry_tail *t)
+{
+	memset(t, 0, sizeof(struct ext4_directory_entry_tail));
+	t->rec_len = to_le16(sizeof(struct ext4_directory_entry_tail));
+	t->reserved_ft = EXT4_DIRENTRY_DIR_CSUM;
+}
+
 void ext4_dir_set_checksum(struct ext4_inode_ref *inode_ref,
 			   struct ext4_directory_entry_ll *dirent)
 {
@@ -396,6 +404,11 @@
 			     name_len);
 
 	/* Save new block */
+	if (ext4_sb_has_feature_read_only(&fs->sb,
+					  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		initialize_dir_tail(EXT4_DIRENT_TAIL(new_block.data,
+					ext4_sb_get_block_size(&fs->sb)));
+
 	ext4_dir_set_checksum(parent,
 			(struct ext4_directory_entry_ll *)new_block.data);
 	new_block.dirty = true;
--- a/lwext4/ext4_dir.h
+++ b/lwext4/ext4_dir.h
@@ -266,6 +266,9 @@
 void ext4_dir_set_checksum(struct ext4_inode_ref *inode_ref,
 			   struct ext4_directory_entry_ll *dirent);
 
+/* checksumming functions */
+void initialize_dir_tail(struct ext4_directory_entry_tail *t);
+
 #endif /* EXT4_DIR_H_ */
 
 /**
--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -371,8 +371,12 @@
 	uint32_t entry_space = block_size -
 			       2 * sizeof(struct ext4_directory_dx_dot_entry) -
 			       sizeof(struct ext4_directory_dx_root_info);
+	if (ext4_sb_has_feature_read_only(sb,
+					  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		entry_space -= sizeof(struct ext4_directory_dx_tail);
 	uint16_t root_limit =
 	    entry_space / sizeof(struct ext4_directory_dx_entry);
+
 	ext4_dir_dx_countlimit_set_limit(countlimit, root_limit);
 
 	/* Append new block, where will be new entries inserted in the future */
@@ -397,6 +401,7 @@
 	if (ext4_sb_has_feature_read_only(sb,
 					  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
 		ext4_dir_entry_ll_set_entry_length(block_entry,
+				block_size -
 				sizeof(struct ext4_directory_entry_tail));
 		ext4_dir_entry_ll_set_name_length(sb,
 						  block_entry,
@@ -404,6 +409,11 @@
 		ext4_dir_entry_ll_set_inode_type(sb,
 						 block_entry,
 						 EXT4_DIRENTRY_DIR_CSUM);
+		if (ext4_sb_has_feature_read_only(sb,
+						  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+			initialize_dir_tail(EXT4_DIRENT_TAIL(block_entry,
+						ext4_sb_get_block_size(sb)));
+
 		ext4_dir_set_checksum(dir,
 				(struct ext4_directory_entry_ll *)new_block.data);
 	} else {
@@ -1032,9 +1042,14 @@
 	}
 
 	/* Do some steps to finish operation */
-	ext4_dir_set_dx_checksum(inode_ref,
+	ext4_dir_set_checksum(inode_ref,
 			(struct ext4_directory_entry_ll *)old_data_block->data);
-	ext4_dir_set_dx_checksum(inode_ref,
+	if (ext4_sb_has_feature_read_only(&inode_ref->fs->sb,
+					  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+		initialize_dir_tail(EXT4_DIRENT_TAIL(new_data_block_tmp.data,
+					ext4_sb_get_block_size(&inode_ref->fs->sb)));
+
+	ext4_dir_set_checksum(inode_ref,
 			(struct ext4_directory_entry_ll *)new_data_block_tmp.data);
 	old_data_block->dirty = true;
 	new_data_block_tmp.dirty = true;
@@ -1063,6 +1078,7 @@
 			struct ext4_directory_dx_block *dx_block,
 			struct ext4_directory_dx_block **new_dx_block)
 {
+	struct ext4_sblock *sb = &inode_ref->fs->sb;
 	struct ext4_directory_dx_entry *entries;
 
 	if (dx_block == dx_blocks)
@@ -1153,9 +1169,13 @@
 			uint32_t entry_space =
 			    block_size -
 			    sizeof(struct ext4_fake_directory_entry);
+			if (ext4_sb_has_feature_read_only(sb,
+							  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+				entry_space -= sizeof(struct ext4_directory_dx_tail);
 			uint32_t node_limit =
 			    entry_space /
 			    sizeof(struct ext4_directory_dx_entry);
+
 			ext4_dir_dx_countlimit_set_limit(right_countlimit,
 							 node_limit);
 
@@ -1212,6 +1232,9 @@
 			uint32_t entry_space =
 			    block_size -
 			    sizeof(struct ext4_fake_directory_entry);
+			if (ext4_sb_has_feature_read_only(sb,
+							  EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+				entry_space -= sizeof(struct ext4_directory_dx_tail);
 			uint32_t node_limit =
 			    entry_space /
 			    sizeof(struct ext4_directory_dx_entry);