shithub: riscv

Download patch

ref: a9513b7532d1e2fb59159386dd6e4ea28e24bc87
parent: 220dfb87f561f73ec1d154e08511332a660d1119
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Feb 16 13:37:48 EST 2024

ext4srv: dir/index: disable htree csum checks for now (lwext4 broken); fix a few bugs

--- a/sys/src/cmd/ext4srv/ext4_dir_idx.c
+++ b/sys/src/cmd/ext4srv/ext4_dir_idx.c
@@ -182,8 +182,6 @@
 		ino_gen = to_le32(ext4_inode_get_generation(inode_ref->inode));
 
 		sz = count_offset + (count * sizeof(struct ext4_dir_idx_tail));
-		orig_cum = t->checksum;
-		t->checksum = 0;
 		/* First calculate crc32 checksum against fs uuid */
 		csum = inode_ref->fs->uuid_crc32c;
 		/* Then calculate crc32 checksum against inode number
@@ -193,6 +191,8 @@
 		/* After that calculate crc32 checksum against all the dx_entry */
 		csum = ext4_crc32c(csum, de, sz);
 		/* Finally calculate crc32 checksum for dx_tail */
+		orig_cum = t->checksum;
+		t->checksum = 0;
 		csum = ext4_crc32c(csum, t, sizeof(struct ext4_dir_idx_tail));
 		t->checksum = orig_cum;
 	}
@@ -260,10 +260,9 @@
 		}
 		t = (void *)(((struct ext4_dir_idx_entry *)climit) + limit);
 
-		u32int c;
-		c = to_le32(ext4_dir_dx_checksum(inode_ref, de, coff, cnt, t));
+		u32int c = to_le32(ext4_dir_dx_checksum(inode_ref, de, coff, cnt, t));
 		if (t->checksum != c)
-			return false;
+			return true; // FIXME lwext4 does not set correct checksums sometimes
 	}
 	return true;
 }
@@ -331,7 +330,7 @@
 	struct ext4_dir_idx_root *root = (void *)block.data;
 	struct ext4_dir_idx_rinfo *info = &(root->info);
 
-	memset(root, 0, sizeof(struct ext4_dir_idx_root));
+	memset(root, 0, sizeof(*root));
 	struct ext4_dir_en *de;
 
 	/* Initialize dot entries */
@@ -339,7 +338,7 @@
 	ext4_dir_write_entry(sb, de, 12, dir, ".", strlen("."));
 
 	de = (struct ext4_dir_en *)(root->dots + 1);
-	u16int elen = block_size - 12;
+	int elen = block_size - 12;
 	ext4_dir_write_entry(sb, de, elen, parent, "..", strlen(".."));
 
 	/* Initialize root info structure */
@@ -388,7 +387,7 @@
 	struct ext4_dir_en *be = (void *)new_block.data;
 
 	if (ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) {
-		u16int len = block_size - sizeof(struct ext4_dir_entry_tail);
+		int len = block_size - sizeof(struct ext4_dir_entry_tail);
 		ext4_dir_en_set_entry_len(be, len);
 		ext4_dir_en_set_name_len(sb, be, 0);
 		ext4_dir_en_set_inode_type(sb, be, EXT4_DE_UNKNOWN);
@@ -547,7 +546,7 @@
 		}
 
 		/* Goto child node */
-		u32int n_blk = ext4_dir_dx_entry_get_block(at);
+		ext4_lblk_t n_blk = ext4_dir_dx_entry_get_block(at);
 
 		ind_level--;
 
@@ -613,8 +612,11 @@
 		if (p->position < p->entries + cnt)
 			break;
 
-		if (p == dx_blocks)
-			return 0;
+		if (p == dx_blocks) {
+notfound:
+			werrstr(Enotfound);
+			return EXT4_ERR_NOT_FOUND;
+		}
 
 		num_handles++;
 		p--;
@@ -625,12 +627,12 @@
 	u32int current_hash = ext4_dir_dx_entry_get_hash(p->position);
 	if ((hash & 1) == 0) {
 		if ((current_hash & ~1) != hash)
-			return 0;
+			goto notfound;
 	}
 
 	/* Fill new path */
 	while (num_handles--) {
-		u32int blk = ext4_dir_dx_entry_get_block(p->position);
+		ext4_lblk_t blk = ext4_dir_dx_entry_get_block(p->position);
 		r = ext4_fs_get_inode_dblk_idx(inode_ref, blk, &blk_adr, false);
 		if (r != 0)
 			return r;
@@ -661,8 +663,7 @@
 		p->position = p->entries;
 	}
 
-	werrstr(Enotfound);
-	return EXT4_ERR_NOT_FOUND;
+	return 0;
 }
 
 int ext4_dir_dx_find_entry(struct ext4_dir_search_result *result,
@@ -673,7 +674,7 @@
 	ext4_fsblk_t root_block_addr;
 	int rc2;
 	int rc;
-	rc = ext4_fs_get_inode_dblk_idx(inode_ref,  0, &root_block_addr, false);
+	rc = ext4_fs_get_inode_dblk_idx(inode_ref, 0, &root_block_addr, false);
 	if (rc != 0)
 		return rc;
 
@@ -691,6 +692,8 @@
 			 "Block: %ud\n",
 			 inode_ref->index,
 			 (u32int)0);
+		werrstr("htree root checksum mismatch");
+		return -1;
 	}
 
 	/* Initialize hash info (compute hash value) */
@@ -709,8 +712,7 @@
 	struct ext4_dir_idx_block *dx_block;
 	struct ext4_dir_idx_block *tmp;
 
-	rc = ext4_dir_dx_get_leaf(&hinfo, inode_ref, &root_block, &dx_block,
-				  dx_blocks);
+	rc = ext4_dir_dx_get_leaf(&hinfo, inode_ref, &root_block, &dx_block, dx_blocks);
 	if (rc != 0) {
 		ext4_block_set(fs->bdev, &root_block);
 		return EXT4_ERR_BAD_DX_DIR;
@@ -718,21 +720,18 @@
 
 	for (;;) {
 		/* Load leaf block */
-		u32int leaf_blk_idx;
+		ext4_lblk_t leaf_blk_idx = ext4_dir_dx_entry_get_block(dx_block->position);
 		ext4_fsblk_t leaf_block_addr;
-		struct ext4_block b;
-
-		leaf_blk_idx = ext4_dir_dx_entry_get_block(dx_block->position);
-		rc = ext4_fs_get_inode_dblk_idx(inode_ref, leaf_blk_idx,
-						&leaf_block_addr, false);
+		rc = ext4_fs_get_inode_dblk_idx(inode_ref, leaf_blk_idx, &leaf_block_addr, false);
 		if (rc != 0)
 			break;
 
+		struct ext4_block b;
 		rc = ext4_trans_block_get(fs->bdev, &b, leaf_block_addr);
 		if (rc != 0)
 			break;
 
-		if (!ext4_dir_csum_verify(inode_ref, (void *)b.data)) {
+		if (!ext4_dir_dx_csum_verify(inode_ref, (void *)b.data)) {
 			ext4_dbg(DEBUG_DIR_IDX,
 				 DBG_WARN "HTree leaf block checksum failed."
 				 "Inode: %ud, "
@@ -739,6 +738,9 @@
 				 "Block: %ud\n",
 				 inode_ref->index,
 				 leaf_blk_idx);
+			rc = -1;
+			werrstr("htree leaf block checksum mismatch");
+			break;
 		}
 
 		/* Linear search inside block */
@@ -762,16 +764,12 @@
 
 		/* check if the next block could be checked */
 		rc = ext4_dir_dx_next_block(inode_ref, hinfo.hash, dx_block, &dx_blocks[0]);
-		if (rc != 0) {
-			if (rc == EXT4_ERR_NOT_FOUND)
-				continue;
+		if (rc != 0)
 			break;
-		}
 	}
 
 	/* The whole path must be released (preventing memory leak) */
 	tmp = dx_blocks;
-
 	while (tmp <= dx_block) {
 		rc2 = ext4_block_set(fs->bdev, &tmp->b);
 		if (rc == 0 && rc2 != 0)
@@ -1192,6 +1190,7 @@
 {
 	int rc2 = 0;
 	int r;
+
 	/* Get direct block 0 (index root) */
 	ext4_fsblk_t rblock_addr;
 	r =  ext4_fs_get_inode_dblk_idx(parent, 0, &rblock_addr, false);
@@ -1237,7 +1236,7 @@
 	}
 
 	/* Try to insert to existing data block */
-	u32int leaf_block_idx = ext4_dir_dx_entry_get_block(dx_blk->position);
+	ext4_lblk_t leaf_block_idx = ext4_dir_dx_entry_get_block(dx_blk->position);
 	ext4_fsblk_t leaf_block_addr;
 	r = ext4_fs_get_inode_dblk_idx(parent, leaf_block_idx,
 						&leaf_block_addr, false);
@@ -1257,7 +1256,7 @@
 	if (r != 0)
 		goto release_index;
 
-	if (!ext4_dir_csum_verify(parent,(void *)target_block.data)) {
+	if (!ext4_dir_dx_csum_verify(parent, (void *)target_block.data)) {
 		ext4_dbg(DEBUG_DIR_IDX,
 				DBG_WARN "HTree leaf block checksum failed."
 				"Inode: %ud, "