mirror of
				https://github.com/bobranten/Ext4Fsd.git
				synced 2025-10-29 21:18:30 -05:00 
			
		
		
		
	metadata checksums on directories
This commit is contained in:
		| @@ -394,11 +394,15 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, | ||||
|     unsigned short	reclen; | ||||
|     int		nlen, rlen, err; | ||||
|     char		*top; | ||||
|     int		csum_size = 0; | ||||
|  | ||||
|     if (ext4_has_metadata_csum(inode->i_sb)) | ||||
|         csum_size = sizeof(struct ext4_dir_entry_tail); | ||||
|  | ||||
|     reclen = EXT3_DIR_REC_LEN(namelen); | ||||
|     if (!de) { | ||||
|         de = (struct ext3_dir_entry_2 *)bh->b_data; | ||||
|         top = bh->b_data + dir->i_sb->s_blocksize - reclen; | ||||
|         top = bh->b_data + dir->i_sb->s_blocksize - reclen - csum_size; | ||||
|         while ((char *) de <= top) { | ||||
|             if (!ext3_check_dir_entry("ext3_add_entry", dir, de, | ||||
|                                       bh, offset)) { | ||||
| @@ -453,6 +457,7 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, | ||||
|     ext3_update_dx_flag(dir); | ||||
|     dir->i_version++; | ||||
|     ext3_mark_inode_dirty(icb, dir); | ||||
|     ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh->b_data); | ||||
|     set_buffer_dirty(bh); | ||||
|     __brelse(bh); | ||||
|     return 0; | ||||
| @@ -1667,6 +1672,8 @@ int ext3_dx_add_entry(struct ext2_icb *icb, struct dentry *dentry, | ||||
|             dxtrace(dx_show_index ("node", frames[1].entries)); | ||||
|             dxtrace(dx_show_index ("node", | ||||
|                                    ((struct dx_node *) bh2->b_data)->entries)); | ||||
|             ext4_dx_csum_set(dir, (struct ext4_dir_entry *)frame->bh->b_data); | ||||
|             ext4_dx_csum_set(dir, (struct ext4_dir_entry *)bh2->b_data); | ||||
|             set_buffer_dirty(bh2); | ||||
|             brelse (bh2); | ||||
|         } else { | ||||
| @@ -1770,8 +1777,13 @@ struct ext3_dir_entry_2 * | ||||
|     char *data1 = (*bh)->b_data, *data2; | ||||
|     unsigned split, move, size; | ||||
|     struct ext3_dir_entry_2 *de = NULL, *de2; | ||||
|     struct ext4_dir_entry_tail *t; | ||||
|     int	csum_size = 0; | ||||
|     int	err, i; | ||||
|  | ||||
|     if (ext4_has_metadata_csum(dir->i_sb)) | ||||
|         csum_size = sizeof(struct ext4_dir_entry_tail); | ||||
|  | ||||
|     bh2 = ext3_append (icb, dir, &newblock, error); | ||||
|     if (!(bh2)) { | ||||
|         brelse(*bh); | ||||
| @@ -1807,8 +1819,15 @@ struct ext3_dir_entry_2 * | ||||
|     /* Fancy dance to stay within two buffers */ | ||||
|     de2 = dx_move_dirents(data1, data2, map + split, count - split); | ||||
|     de = dx_pack_dirents(data1,blocksize); | ||||
|     de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | ||||
|     de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); | ||||
|     de->rec_len = cpu_to_le16(data1 + (blocksize - csum_size) - (char *) de); | ||||
|     de2->rec_len = cpu_to_le16(data2 + (blocksize - csum_size) - (char *) de2); | ||||
|     if (csum_size) { | ||||
|         t = EXT4_DIRENT_TAIL(data1, blocksize); | ||||
|         initialize_dirent_tail(t, blocksize); | ||||
|  | ||||
|         t = EXT4_DIRENT_TAIL(data2, blocksize); | ||||
|         initialize_dirent_tail(t, blocksize); | ||||
|     } | ||||
|     dxtrace(dx_show_leaf (icb, hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); | ||||
|     dxtrace(dx_show_leaf (icb, hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); | ||||
|  | ||||
| @@ -1819,6 +1838,8 @@ struct ext3_dir_entry_2 * | ||||
|         de = de2; | ||||
|     } | ||||
|     dx_insert_block (frame, hash2 + continued, newblock); | ||||
|     ext4_dx_csum_set(dir, (struct ext4_dir_entry *)frame->bh->b_data); | ||||
|     ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh2->b_data); | ||||
|     set_buffer_dirty(bh2); | ||||
|     set_buffer_dirty(frame->bh); | ||||
|  | ||||
| @@ -1850,6 +1871,11 @@ int make_indexed_dir(struct ext2_icb *icb, struct dentry *dentry, | ||||
|     struct dx_hash_info hinfo; | ||||
|     ext3_lblk_t  block; | ||||
|     struct fake_dirent *fde; | ||||
|     struct ext4_dir_entry_tail *t; | ||||
|     int csum_size = 0; | ||||
|  | ||||
|     if (ext4_has_metadata_csum(inode->i_sb)) | ||||
|         csum_size = sizeof(struct ext4_dir_entry_tail); | ||||
|  | ||||
|     blocksize =  dir->i_sb->s_blocksize; | ||||
|     dxtrace(printk("Creating index: inode %lu\n", dir->i_ino)); | ||||
| @@ -1866,7 +1892,7 @@ int make_indexed_dir(struct ext2_icb *icb, struct dentry *dentry, | ||||
|         brelse(bh); | ||||
|         return -EIO; | ||||
|     } | ||||
|     len = (unsigned int)((char *) root + blocksize - (char *) de); | ||||
|     len = (unsigned int)((char *) root + (blocksize - csum_size) - (char *) de); | ||||
|  | ||||
|     /* Allocate new block for the 0th block's dirents */ | ||||
|     bh2 = ext3_append(icb, dir, &block, &retval); | ||||
| @@ -1882,7 +1908,13 @@ int make_indexed_dir(struct ext2_icb *icb, struct dentry *dentry, | ||||
|     top = data1 + len; | ||||
|     while ((char *)(de2 = ext3_next_entry(de)) < top) | ||||
|         de = de2; | ||||
|     de->rec_len = ext3_rec_len_to_disk(blocksize + (__u32)(data1 - (char *)de)); | ||||
|     de->rec_len = ext3_rec_len_to_disk((blocksize - csum_size) + (__u32)(data1 - (char *)de)); | ||||
|  | ||||
|     if (csum_size) { | ||||
|         t = EXT4_DIRENT_TAIL(data1, blocksize); | ||||
|         initialize_dirent_tail(t, blocksize); | ||||
|     } | ||||
|  | ||||
|     /* Initialize the root; the dot dirents already exist */ | ||||
|     de = (struct ext3_dir_entry_2 *) (&root->dotdot); | ||||
|     de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2)); | ||||
| @@ -1902,6 +1934,8 @@ int make_indexed_dir(struct ext2_icb *icb, struct dentry *dentry, | ||||
|     frame->entries = entries; | ||||
|     frame->at = entries; | ||||
|     frame->bh = bh; | ||||
|     ext4_dx_csum_set(dir, (struct ext4_dir_entry *)bh->b_data); | ||||
|     ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh2->b_data); | ||||
|     bh = bh2; | ||||
|     /* bh and bh2 are to be marked as dirty in do_split */ | ||||
|     de = do_split(icb, dir, &bh, frame, &hinfo, &retval); | ||||
| @@ -1943,6 +1977,11 @@ int ext3_add_entry(struct ext2_icb *icb, struct dentry *dentry, struct inode *in | ||||
| #endif | ||||
|     unsigned blocksize; | ||||
|     ext3_lblk_t block, blocks; | ||||
|     struct ext4_dir_entry_tail *t; | ||||
|     int	csum_size = 0; | ||||
|  | ||||
|     if (ext4_has_metadata_csum(inode->i_sb)) | ||||
|         csum_size = sizeof(struct ext4_dir_entry_tail); | ||||
|  | ||||
|     sb = dir->i_sb; | ||||
|     blocksize = sb->s_blocksize; | ||||
| @@ -1982,7 +2021,13 @@ int ext3_add_entry(struct ext2_icb *icb, struct dentry *dentry, struct inode *in | ||||
|         return retval; | ||||
|     de = (struct ext3_dir_entry_2 *) bh->b_data; | ||||
|     de->inode = 0; | ||||
|     de->rec_len = ext3_rec_len_to_disk(blocksize); | ||||
|     de->rec_len = ext3_rec_len_to_disk(blocksize - csum_size); | ||||
|  | ||||
|     if (csum_size) { | ||||
|         t = EXT4_DIRENT_TAIL(bh->b_data, blocksize); | ||||
|         initialize_dirent_tail(t, blocksize); | ||||
|     } | ||||
|  | ||||
|     return add_dirent_to_buf(icb, dentry, inode, de, bh); | ||||
| } | ||||
|  | ||||
| @@ -1996,9 +2041,13 @@ int ext3_delete_entry(struct ext2_icb *icb, struct inode *dir, | ||||
| { | ||||
|     struct ext3_dir_entry_2 *de, *pde = NULL; | ||||
|     size_t i = 0; | ||||
|     int	csum_size = 0; | ||||
|  | ||||
|     if (ext4_has_metadata_csum(dir->i_sb)) | ||||
|         csum_size = sizeof(struct ext4_dir_entry_tail); | ||||
|  | ||||
|     de = (struct ext3_dir_entry_2 *) bh->b_data; | ||||
|     while (i < bh->b_size) { | ||||
|     while (i < bh->b_size - csum_size) { | ||||
|         if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i)) | ||||
|             return -EIO; | ||||
|         if (de == de_del)  { | ||||
| @@ -2010,6 +2059,7 @@ int ext3_delete_entry(struct ext2_icb *icb, struct inode *dir, | ||||
|                 de->inode = 0; | ||||
|             dir->i_version++; | ||||
|             /* ext3_journal_dirty_metadata(handle, bh); */ | ||||
|             ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh->b_data); | ||||
|             set_buffer_dirty(bh); | ||||
|             return 0; | ||||
|         } | ||||
| @@ -2257,4 +2307,4 @@ cleanup_and_exit: | ||||
|     for (; ra_ptr < ra_max; ra_ptr++) | ||||
|         brelse(bh_use[ra_ptr]); | ||||
|     return ret; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -358,16 +358,15 @@ void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, | ||||
| static __le32 ext4_inode_csum_seed(struct inode *inode) | ||||
| { | ||||
| 	/* Precompute checksum seed for inode metadata */ | ||||
| 	if (ext4_has_feature_metadata_csum(inode->i_sb)) { | ||||
| 	if (ext4_has_metadata_csum(inode->i_sb)) { | ||||
| 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||||
| 		__u32 csum; | ||||
| 		__le32 inum = cpu_to_le32(inode->i_ino); | ||||
| 		__le32 gen = inode->i_generation; | ||||
| 		__le32 gen = cpu_to_le32(inode->i_generation); | ||||
| 		csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum)); | ||||
| 		return ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen)); | ||||
| 	} | ||||
|  | ||||
|     return 0; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, | ||||
| @@ -487,7 +486,7 @@ void ext4_extent_block_csum_set(struct inode *inode, | ||||
|  * Metadata checksum functions for the directory entrys. | ||||
|  */ | ||||
|  | ||||
| static void initialize_dirent_tail(struct ext4_dir_entry_tail *t, | ||||
| void initialize_dirent_tail(struct ext4_dir_entry_tail *t, | ||||
| 			    unsigned int blocksize) | ||||
| { | ||||
| 	memset(t, 0, sizeof(struct ext4_dir_entry_tail)); | ||||
|   | ||||
| @@ -2549,7 +2549,12 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext, | ||||
|         Vcb->sbi.s_desc_size = sb->s_desc_size; | ||||
|         Vcb->sbi.s_clusters_per_group = sb->s_clusters_per_group; | ||||
|         Vcb->sbi.s_inode_size = sb->s_inode_size; | ||||
|         Vcb->sbi.s_csum_seed = ext4_chksum(&Vcb->sbi, ~0, sb->s_uuid, sizeof(sb->s_uuid)); | ||||
|  | ||||
|         /* Precompute checksum seed for all metadata */ | ||||
|         if (ext4_has_feature_csum_seed(&Vcb->sb)) | ||||
|             Vcb->sbi.s_csum_seed = sb->s_checksum_seed; | ||||
|         else if (ext4_has_metadata_csum(&Vcb->sb) || ext4_has_feature_ea_inode(&Vcb->sb)) | ||||
|             Vcb->sbi.s_csum_seed = ext4_chksum(&Vcb->sbi, ~0, sb->s_uuid, sizeof(sb->s_uuid)); | ||||
|  | ||||
|         if (EXT3_HAS_INCOMPAT_FEATURE(&Vcb->sb, EXT4_FEATURE_INCOMPAT_64BIT)) { | ||||
|             if (Vcb->sbi.s_desc_size < EXT4_MIN_DESC_SIZE_64BIT || | ||||
|   | ||||
		Reference in New Issue
	
	Block a user