1
0
mirror of https://github.com/bobranten/Ext4Fsd.git synced 2025-10-30 05:18:31 -05:00

metadata checksums on directories

This commit is contained in:
Bo Brantén
2020-02-01 23:53:40 +01:00
parent 87e787e8c6
commit 4db087019f
3 changed files with 68 additions and 14 deletions

View File

@@ -394,11 +394,15 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry,
unsigned short reclen; unsigned short reclen;
int nlen, rlen, err; int nlen, rlen, err;
char *top; 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); reclen = EXT3_DIR_REC_LEN(namelen);
if (!de) { if (!de) {
de = (struct ext3_dir_entry_2 *)bh->b_data; 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) { while ((char *) de <= top) {
if (!ext3_check_dir_entry("ext3_add_entry", dir, de, if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
bh, offset)) { bh, offset)) {
@@ -453,6 +457,7 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry,
ext3_update_dx_flag(dir); ext3_update_dx_flag(dir);
dir->i_version++; dir->i_version++;
ext3_mark_inode_dirty(icb, dir); ext3_mark_inode_dirty(icb, dir);
ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh->b_data);
set_buffer_dirty(bh); set_buffer_dirty(bh);
__brelse(bh); __brelse(bh);
return 0; 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", frames[1].entries));
dxtrace(dx_show_index ("node", dxtrace(dx_show_index ("node",
((struct dx_node *) bh2->b_data)->entries)); ((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); set_buffer_dirty(bh2);
brelse (bh2); brelse (bh2);
} else { } else {
@@ -1770,8 +1777,13 @@ struct ext3_dir_entry_2 *
char *data1 = (*bh)->b_data, *data2; char *data1 = (*bh)->b_data, *data2;
unsigned split, move, size; unsigned split, move, size;
struct ext3_dir_entry_2 *de = NULL, *de2; struct ext3_dir_entry_2 *de = NULL, *de2;
struct ext4_dir_entry_tail *t;
int csum_size = 0;
int err, i; 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); bh2 = ext3_append (icb, dir, &newblock, error);
if (!(bh2)) { if (!(bh2)) {
brelse(*bh); brelse(*bh);
@@ -1807,8 +1819,15 @@ struct ext3_dir_entry_2 *
/* Fancy dance to stay within two buffers */ /* Fancy dance to stay within two buffers */
de2 = dx_move_dirents(data1, data2, map + split, count - split); de2 = dx_move_dirents(data1, data2, map + split, count - split);
de = dx_pack_dirents(data1,blocksize); de = dx_pack_dirents(data1,blocksize);
de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); de->rec_len = cpu_to_le16(data1 + (blocksize - csum_size) - (char *) de);
de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); 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 *) data1, blocksize, 1));
dxtrace(dx_show_leaf (icb, hinfo, (struct ext3_dir_entry_2 *) data2, 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; de = de2;
} }
dx_insert_block (frame, hash2 + continued, newblock); 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(bh2);
set_buffer_dirty(frame->bh); 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; struct dx_hash_info hinfo;
ext3_lblk_t block; ext3_lblk_t block;
struct fake_dirent *fde; 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; blocksize = dir->i_sb->s_blocksize;
dxtrace(printk("Creating index: inode %lu\n", dir->i_ino)); 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); brelse(bh);
return -EIO; 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 */ /* Allocate new block for the 0th block's dirents */
bh2 = ext3_append(icb, dir, &block, &retval); 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; top = data1 + len;
while ((char *)(de2 = ext3_next_entry(de)) < top) while ((char *)(de2 = ext3_next_entry(de)) < top)
de = de2; 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 */ /* Initialize the root; the dot dirents already exist */
de = (struct ext3_dir_entry_2 *) (&root->dotdot); de = (struct ext3_dir_entry_2 *) (&root->dotdot);
de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2)); 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->entries = entries;
frame->at = entries; frame->at = entries;
frame->bh = bh; 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 = bh2;
/* bh and bh2 are to be marked as dirty in do_split */ /* bh and bh2 are to be marked as dirty in do_split */
de = do_split(icb, dir, &bh, frame, &hinfo, &retval); 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 #endif
unsigned blocksize; unsigned blocksize;
ext3_lblk_t block, blocks; 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; sb = dir->i_sb;
blocksize = sb->s_blocksize; blocksize = sb->s_blocksize;
@@ -1982,7 +2021,13 @@ int ext3_add_entry(struct ext2_icb *icb, struct dentry *dentry, struct inode *in
return retval; return retval;
de = (struct ext3_dir_entry_2 *) bh->b_data; de = (struct ext3_dir_entry_2 *) bh->b_data;
de->inode = 0; 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); 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; struct ext3_dir_entry_2 *de, *pde = NULL;
size_t i = 0; 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; 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)) if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i))
return -EIO; return -EIO;
if (de == de_del) { if (de == de_del) {
@@ -2010,6 +2059,7 @@ int ext3_delete_entry(struct ext2_icb *icb, struct inode *dir,
de->inode = 0; de->inode = 0;
dir->i_version++; dir->i_version++;
/* ext3_journal_dirty_metadata(handle, bh); */ /* ext3_journal_dirty_metadata(handle, bh); */
ext4_dirent_csum_set(dir, (struct ext4_dir_entry *)bh->b_data);
set_buffer_dirty(bh); set_buffer_dirty(bh);
return 0; return 0;
} }
@@ -2257,4 +2307,4 @@ cleanup_and_exit:
for (; ra_ptr < ra_max; ra_ptr++) for (; ra_ptr < ra_max; ra_ptr++)
brelse(bh_use[ra_ptr]); brelse(bh_use[ra_ptr]);
return ret; return ret;
} }

View File

@@ -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) static __le32 ext4_inode_csum_seed(struct inode *inode)
{ {
/* Precompute checksum seed for inode metadata */ /* 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); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
__u32 csum; __u32 csum;
__le32 inum = cpu_to_le32(inode->i_ino); __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)); csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum));
return ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen)); 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, 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. * 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) unsigned int blocksize)
{ {
memset(t, 0, sizeof(struct ext4_dir_entry_tail)); memset(t, 0, sizeof(struct ext4_dir_entry_tail));

View File

@@ -2549,7 +2549,12 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
Vcb->sbi.s_desc_size = sb->s_desc_size; Vcb->sbi.s_desc_size = sb->s_desc_size;
Vcb->sbi.s_clusters_per_group = sb->s_clusters_per_group; Vcb->sbi.s_clusters_per_group = sb->s_clusters_per_group;
Vcb->sbi.s_inode_size = sb->s_inode_size; 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 (EXT3_HAS_INCOMPAT_FEATURE(&Vcb->sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
if (Vcb->sbi.s_desc_size < EXT4_MIN_DESC_SIZE_64BIT || if (Vcb->sbi.s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||