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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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 ||
|
||||||
|
|||||||
Reference in New Issue
Block a user