mirror of
https://github.com/bobranten/Ext4Fsd.git
synced 2025-10-30 05:18:31 -05:00
suport for metadata checksums
This commit is contained in:
@@ -208,6 +208,7 @@
|
|||||||
<ClCompile Include="ext3\indirect.c" />
|
<ClCompile Include="ext3\indirect.c" />
|
||||||
<ClCompile Include="ext3\recover.c" />
|
<ClCompile Include="ext3\recover.c" />
|
||||||
<ClCompile Include="ext4\ext4_bh.c" />
|
<ClCompile Include="ext4\ext4_bh.c" />
|
||||||
|
<ClCompile Include="ext4\ext4_csum.c" />
|
||||||
<ClCompile Include="ext4\ext4_extents.c" />
|
<ClCompile Include="ext4\ext4_extents.c" />
|
||||||
<ClCompile Include="ext4\ext4_jbd2.c" />
|
<ClCompile Include="ext4\ext4_jbd2.c" />
|
||||||
<ClCompile Include="ext4\ext4_xattr.c" />
|
<ClCompile Include="ext4\ext4_xattr.c" />
|
||||||
|
|||||||
@@ -274,6 +274,9 @@
|
|||||||
<ClCompile Include="nls\nls_utf8.c">
|
<ClCompile Include="nls\nls_utf8.c">
|
||||||
<Filter>Source Files\nls</Filter>
|
<Filter>Source Files\nls</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ext4\ext4_csum.c">
|
||||||
|
<Filter>Source Files\ext4</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\ext2fs.h">
|
<ClInclude Include="include\ext2fs.h">
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Ext2LoadSuper(IN PEXT2_VCB Vcb,
|
|||||||
Ext2Sb = (PEXT2_SUPER_BLOCK)
|
Ext2Sb = (PEXT2_SUPER_BLOCK)
|
||||||
Ext2AllocatePool(
|
Ext2AllocatePool(
|
||||||
PagedPool,
|
PagedPool,
|
||||||
SUPER_BLOCK_SIZE,
|
sizeof(EXT2_SUPER_BLOCK),
|
||||||
EXT2_SB_MAGIC
|
EXT2_SB_MAGIC
|
||||||
);
|
);
|
||||||
if (!Ext2Sb) {
|
if (!Ext2Sb) {
|
||||||
@@ -43,7 +43,7 @@ Ext2LoadSuper(IN PEXT2_VCB Vcb,
|
|||||||
Status = Ext2ReadDisk(
|
Status = Ext2ReadDisk(
|
||||||
Vcb,
|
Vcb,
|
||||||
(ULONGLONG) SUPER_BLOCK_OFFSET,
|
(ULONGLONG) SUPER_BLOCK_OFFSET,
|
||||||
SUPER_BLOCK_SIZE,
|
sizeof(EXT2_SUPER_BLOCK),
|
||||||
(PVOID) Ext2Sb,
|
(PVOID) Ext2Sb,
|
||||||
bVerify );
|
bVerify );
|
||||||
|
|
||||||
@@ -68,11 +68,12 @@ Ext2SaveSuper(
|
|||||||
LONGLONG offset;
|
LONGLONG offset;
|
||||||
BOOLEAN rc;
|
BOOLEAN rc;
|
||||||
|
|
||||||
|
ext4_superblock_csum_set(&Vcb->sb);
|
||||||
offset = (LONGLONG) SUPER_BLOCK_OFFSET;
|
offset = (LONGLONG) SUPER_BLOCK_OFFSET;
|
||||||
rc = Ext2SaveBuffer( IrpContext,
|
rc = Ext2SaveBuffer( IrpContext,
|
||||||
Vcb,
|
Vcb,
|
||||||
offset,
|
offset,
|
||||||
SUPER_BLOCK_SIZE,
|
sizeof(EXT2_SUPER_BLOCK),
|
||||||
Vcb->SuperBlock
|
Vcb->SuperBlock
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ Ext2RefreshSuper (
|
|||||||
if (!CcCopyRead(
|
if (!CcCopyRead(
|
||||||
Vcb->Volume,
|
Vcb->Volume,
|
||||||
(PLARGE_INTEGER)&offset,
|
(PLARGE_INTEGER)&offset,
|
||||||
SUPER_BLOCK_SIZE,
|
sizeof(EXT2_SUPER_BLOCK),
|
||||||
TRUE,
|
TRUE,
|
||||||
(PVOID)Vcb->SuperBlock,
|
(PVOID)Vcb->SuperBlock,
|
||||||
&iosb )) {
|
&iosb )) {
|
||||||
@@ -127,7 +128,7 @@ Ext2RefreshSuper (
|
|||||||
VOID
|
VOID
|
||||||
Ext2DropGroupBH(IN PEXT2_VCB Vcb)
|
Ext2DropGroupBH(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
if (NULL == Vcb->sbi.s_gd) {
|
if (NULL == Vcb->sbi.s_gd) {
|
||||||
@@ -145,7 +146,7 @@ Ext2DropGroupBH(IN PEXT2_VCB Vcb)
|
|||||||
VOID
|
VOID
|
||||||
Ext2PutGroup(IN PEXT2_VCB Vcb)
|
Ext2PutGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
|
|
||||||
@@ -166,7 +167,7 @@ BOOLEAN
|
|||||||
Ext2LoadGroupBH(IN PEXT2_VCB Vcb)
|
Ext2LoadGroupBH(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
struct super_block *sb = &Vcb->sb;
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
BOOLEAN rc = FALSE;
|
BOOLEAN rc = FALSE;
|
||||||
|
|
||||||
@@ -203,7 +204,7 @@ BOOLEAN
|
|||||||
Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
struct super_block *sb = &Vcb->sb;
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
ext3_fsblk_t sb_block = 1;
|
ext3_fsblk_t sb_block = 1;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
BOOLEAN rc = FALSE;
|
BOOLEAN rc = FALSE;
|
||||||
@@ -261,7 +262,7 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
|||||||
VOID
|
VOID
|
||||||
Ext2DropBH(IN PEXT2_VCB Vcb)
|
Ext2DropBH(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
|
|
||||||
/* do nothing if Vcb is not initialized yet */
|
/* do nothing if Vcb is not initialized yet */
|
||||||
if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
|
if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
|
||||||
@@ -319,7 +320,7 @@ NTSTATUS
|
|||||||
Ext2FlushVcb(IN PEXT2_VCB Vcb)
|
Ext2FlushVcb(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER s = {0}, o;
|
LARGE_INTEGER s = {0}, o;
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext4_sb_info *sbi = &Vcb->sbi;
|
||||||
struct rb_node *node;
|
struct rb_node *node;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
|
||||||
@@ -393,7 +394,7 @@ Ext2SaveGroup(
|
|||||||
if (!gd)
|
if (!gd)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gd->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, gd);
|
ext4_group_desc_csum_set(&Vcb->sb, Group, gd);
|
||||||
mark_buffer_dirty(gb);
|
mark_buffer_dirty(gb);
|
||||||
fini_bh(&gb);
|
fini_bh(&gb);
|
||||||
|
|
||||||
@@ -445,7 +446,7 @@ Ext2GetInodeLba (
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src)
|
void Ext2DecodeInode(struct inode *dst, struct ext4_inode *src)
|
||||||
{
|
{
|
||||||
dst->i_mode = src->i_mode;
|
dst->i_mode = src->i_mode;
|
||||||
dst->i_flags = src->i_flags;
|
dst->i_flags = src->i_flags;
|
||||||
@@ -453,7 +454,7 @@ void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src)
|
|||||||
dst->i_gid = src->i_gid;
|
dst->i_gid = src->i_gid;
|
||||||
dst->i_nlink = src->i_links_count;
|
dst->i_nlink = src->i_links_count;
|
||||||
dst->i_generation = src->i_generation;
|
dst->i_generation = src->i_generation;
|
||||||
dst->i_size = src->i_size;
|
dst->i_size = src->i_size_lo;
|
||||||
if (S_ISREG(src->i_mode)) {
|
if (S_ISREG(src->i_mode)) {
|
||||||
dst->i_size |= (loff_t)src->i_size_high << 32;
|
dst->i_size |= (loff_t)src->i_size_high << 32;
|
||||||
}
|
}
|
||||||
@@ -465,14 +466,14 @@ void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src)
|
|||||||
dst->i_dtime = src->i_dtime;
|
dst->i_dtime = src->i_dtime;
|
||||||
dst->i_blocks = ext3_inode_blocks(src, dst);
|
dst->i_blocks = ext3_inode_blocks(src, dst);
|
||||||
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
||||||
if (EXT3_HAS_RO_COMPAT_FEATURE(dst->i_sb,
|
if (EXT4_HAS_RO_COMPAT_FEATURE(dst->i_sb,
|
||||||
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
|
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
|
||||||
dst->i_extra_isize = src->i_extra_isize;
|
dst->i_extra_isize = src->i_extra_isize;
|
||||||
else
|
else
|
||||||
dst->i_extra_isize = 0;
|
dst->i_extra_isize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2EncodeInode(struct ext3_inode *dst, struct inode *src)
|
void Ext2EncodeInode(struct ext4_inode *dst, struct inode *src)
|
||||||
{
|
{
|
||||||
dst->i_mode = src->i_mode;
|
dst->i_mode = src->i_mode;
|
||||||
dst->i_flags = src->i_flags;
|
dst->i_flags = src->i_flags;
|
||||||
@@ -480,7 +481,7 @@ void Ext2EncodeInode(struct ext3_inode *dst, struct inode *src)
|
|||||||
dst->i_gid = src->i_gid;
|
dst->i_gid = src->i_gid;
|
||||||
dst->i_links_count = src->i_nlink;
|
dst->i_links_count = src->i_nlink;
|
||||||
dst->i_generation = src->i_generation;
|
dst->i_generation = src->i_generation;
|
||||||
dst->i_size = (__u32)src->i_size;
|
dst->i_size_lo = (__u32)src->i_size;
|
||||||
if (S_ISREG(src->i_mode)) {
|
if (S_ISREG(src->i_mode)) {
|
||||||
dst->i_size_high = (__u32)(src->i_size >> 32);
|
dst->i_size_high = (__u32)(src->i_size >> 32);
|
||||||
}
|
}
|
||||||
@@ -494,7 +495,7 @@ void Ext2EncodeInode(struct ext3_inode *dst, struct inode *src)
|
|||||||
ASSERT(src->i_sb);
|
ASSERT(src->i_sb);
|
||||||
ext3_inode_blocks_set(dst, src);
|
ext3_inode_blocks_set(dst, src);
|
||||||
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
||||||
if (EXT3_HAS_RO_COMPAT_FEATURE(src->i_sb,
|
if (EXT4_HAS_RO_COMPAT_FEATURE(src->i_sb,
|
||||||
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
|
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE))
|
||||||
dst->i_extra_isize = src->i_extra_isize;
|
dst->i_extra_isize = src->i_extra_isize;
|
||||||
}
|
}
|
||||||
@@ -504,7 +505,8 @@ BOOLEAN
|
|||||||
Ext2LoadInode (IN PEXT2_VCB Vcb,
|
Ext2LoadInode (IN PEXT2_VCB Vcb,
|
||||||
IN struct inode *Inode)
|
IN struct inode *Inode)
|
||||||
{
|
{
|
||||||
struct ext3_inode ext3i = {0};
|
struct ext4_inode ext3i = {0};
|
||||||
|
struct ext4_inode_info ei = {0};
|
||||||
LONGLONG offset;
|
LONGLONG offset;
|
||||||
|
|
||||||
if (!Ext2GetInodeLba(Vcb, Inode->i_ino, &offset)) {
|
if (!Ext2GetInodeLba(Vcb, Inode->i_ino, &offset)) {
|
||||||
@@ -518,6 +520,10 @@ Ext2LoadInode (IN PEXT2_VCB Vcb,
|
|||||||
|
|
||||||
Ext2DecodeInode(Inode, &ext3i);
|
Ext2DecodeInode(Inode, &ext3i);
|
||||||
|
|
||||||
|
if (!ext4_inode_csum_verify(Inode, &ext3i, &ei)) {
|
||||||
|
//DbgPrint("inod %d checksum invalid\n", Inode->i_ino);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,10 +555,11 @@ Ext2SaveInode ( IN PEXT2_IRP_CONTEXT IrpContext,
|
|||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN struct inode *Inode)
|
IN struct inode *Inode)
|
||||||
{
|
{
|
||||||
struct ext3_inode ext3i = {0};
|
struct ext4_inode ext4i = {0};
|
||||||
|
struct ext4_inode_info ei = {0};
|
||||||
|
|
||||||
LONGLONG Offset = 0;
|
LONGLONG Offset = 0;
|
||||||
ULONG InodeSize = sizeof(ext3i);
|
ULONG InodeSize = sizeof(ext4i);
|
||||||
BOOLEAN rc = 0;
|
BOOLEAN rc = 0;
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
|
DEBUG(DL_INF, ( "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
|
||||||
@@ -563,16 +570,22 @@ Ext2SaveInode ( IN PEXT2_IRP_CONTEXT IrpContext,
|
|||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = Ext2LoadBuffer(NULL, Vcb, Offset, InodeSize, &ext3i);
|
rc = Ext2LoadBuffer(NULL, Vcb, Offset, InodeSize, &ext4i);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
DEBUG(DL_ERR, ( "Ext2SaveInode: failed reading inode %u.\n", Inode->i_ino));
|
DEBUG(DL_ERR, ( "Ext2SaveInode: failed reading inode %u.\n", Inode->i_ino));
|
||||||
goto errorout;;
|
goto errorout;;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2EncodeInode(&ext3i, Inode);
|
Ext2EncodeInode(&ext4i, Inode);
|
||||||
|
|
||||||
|
ext4_inode_csum_set(Inode, &ext4i, &ei);
|
||||||
|
|
||||||
if (InodeSize > Vcb->InodeSize)
|
if (InodeSize > Vcb->InodeSize)
|
||||||
|
{
|
||||||
|
DbgPrint("InodeSize > Vcb->InodeSize\n");
|
||||||
InodeSize = Vcb->InodeSize;
|
InodeSize = Vcb->InodeSize;
|
||||||
rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, InodeSize, &ext3i);
|
}
|
||||||
|
rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, InodeSize, &ext4i);
|
||||||
|
|
||||||
if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
|
if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
|
||||||
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
|
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
|
||||||
@@ -1004,7 +1017,7 @@ Again:
|
|||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
|
ext4_group_desc_csum_set(sb, Group, gd);
|
||||||
ext4_init_block_bitmap(sb, bh, Group, gd);
|
ext4_init_block_bitmap(sb, bh, Group, gd);
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
||||||
@@ -1099,6 +1112,7 @@ Again:
|
|||||||
|
|
||||||
/* update group description */
|
/* update group description */
|
||||||
ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
|
ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
|
||||||
|
ext4_block_bitmap_csum_set(sb, Group, gd, bh);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
|
|
||||||
/* update Vcb free blocks */
|
/* update Vcb free blocks */
|
||||||
@@ -1157,6 +1171,7 @@ Ext2FreeBlock(
|
|||||||
struct super_block *sb = &Vcb->sb;
|
struct super_block *sb = &Vcb->sb;
|
||||||
PEXT2_GROUP_DESC gd;
|
PEXT2_GROUP_DESC gd;
|
||||||
struct buffer_head *gb = NULL;
|
struct buffer_head *gb = NULL;
|
||||||
|
struct buffer_head bh;
|
||||||
ext4_fsblk_t bitmap_blk;
|
ext4_fsblk_t bitmap_blk;
|
||||||
|
|
||||||
RTL_BITMAP BlockBitmap;
|
RTL_BITMAP BlockBitmap;
|
||||||
@@ -1249,6 +1264,9 @@ Again:
|
|||||||
/* update group description table */
|
/* update group description table */
|
||||||
ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
|
ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
|
||||||
|
|
||||||
|
bh.b_data = BitmapCache;
|
||||||
|
ext4_block_bitmap_csum_set(sb, Group, gd, &bh);
|
||||||
|
|
||||||
/* indict the cache range is dirty */
|
/* indict the cache range is dirty */
|
||||||
CcSetDirtyPinnedData(BitmapBcb, NULL );
|
CcSetDirtyPinnedData(BitmapBcb, NULL );
|
||||||
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
|
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
|
||||||
@@ -1520,10 +1538,11 @@ repeat:
|
|||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
|
|
||||||
ext4_init_inode_bitmap(sb, bh, Group, gd);
|
ext4_init_inode_bitmap(sb, bh, Group, gd);
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
|
gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT);
|
||||||
|
ext4_inode_bitmap_csum_set(sb, Group, gd, bh, EXT4_INODES_PER_GROUP(sb) / 8);
|
||||||
|
ext4_group_desc_csum_set(sb, Group, gd);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
} else {
|
} else {
|
||||||
bh = sb_getblk(sb, bitmap_blk);
|
bh = sb_getblk(sb, bitmap_blk);
|
||||||
@@ -1584,7 +1603,7 @@ repeat:
|
|||||||
|
|
||||||
/* If we didn't allocate from within the initialized part of the inode
|
/* If we didn't allocate from within the initialized part of the inode
|
||||||
* table then we need to initialize up to this inode. */
|
* table then we need to initialize up to this inode. */
|
||||||
if (EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
|
if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
|
||||||
|
|
||||||
__u32 free;
|
__u32 free;
|
||||||
|
|
||||||
@@ -1621,7 +1640,9 @@ repeat:
|
|||||||
/* recheck and clear flag under lock if we still need to */
|
/* recheck and clear flag under lock if we still need to */
|
||||||
block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, gd));
|
block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, gd));
|
||||||
if (block_bitmap_bh) {
|
if (block_bitmap_bh) {
|
||||||
gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
|
ext4_block_bitmap_csum_set(sb, Group, gd,
|
||||||
|
block_bitmap_bh);
|
||||||
|
ext4_group_desc_csum_set(sb, Group, gd);
|
||||||
free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd);
|
free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd);
|
||||||
set_buffer_uptodate(block_bitmap_bh);
|
set_buffer_uptodate(block_bitmap_bh);
|
||||||
brelse(block_bitmap_bh);
|
brelse(block_bitmap_bh);
|
||||||
@@ -1638,6 +1659,8 @@ repeat:
|
|||||||
if (Type == EXT2_FT_DIR) {
|
if (Type == EXT2_FT_DIR) {
|
||||||
ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) + 1);
|
ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) + 1);
|
||||||
}
|
}
|
||||||
|
ext4_inode_bitmap_csum_set(sb, Group, gd, bh, EXT4_INODES_PER_GROUP(sb) / 8);
|
||||||
|
ext4_group_desc_csum_set(sb, Group, gd);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
Ext2UpdateVcbStat(IrpContext, Vcb);
|
Ext2UpdateVcbStat(IrpContext, Vcb);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
@@ -1789,6 +1812,8 @@ Ext2FreeInode(
|
|||||||
ext4_used_dirs_set(sb, gd,
|
ext4_used_dirs_set(sb, gd,
|
||||||
ext4_used_dirs_count(sb, gd) - 1);
|
ext4_used_dirs_count(sb, gd) - 1);
|
||||||
}
|
}
|
||||||
|
ext4_inode_bitmap_csum_set(sb, Group, gd, bh, EXT4_INODES_PER_GROUP(sb) / 8);
|
||||||
|
ext4_group_desc_csum_set(sb, Group, gd);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
Ext2UpdateVcbStat(IrpContext, Vcb);
|
Ext2UpdateVcbStat(IrpContext, Vcb);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
@@ -1896,7 +1921,7 @@ Ext2SetFileType (
|
|||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
BOOLEAN MainResourceAcquired = FALSE;
|
BOOLEAN MainResourceAcquired = FALSE;
|
||||||
|
|
||||||
if (!EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb, EXT3_FEATURE_INCOMPAT_FILETYPE)) {
|
if (!EXT4_HAS_INCOMPAT_FEATURE(dir->i_sb, EXT3_FEATURE_INCOMPAT_FILETYPE)) {
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2156,7 +2181,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
|
|||||||
else if ((char *) de + rlen > bh->b_data + dir->i_sb->s_blocksize)
|
else if ((char *) de + rlen > bh->b_data + dir->i_sb->s_blocksize)
|
||||||
error_msg = "directory entry across blocks";
|
error_msg = "directory entry across blocks";
|
||||||
else if (le32_to_cpu(de->inode) >
|
else if (le32_to_cpu(de->inode) >
|
||||||
le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
|
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))
|
||||||
error_msg = "inode out of bounds";
|
error_msg = "inode out of bounds";
|
||||||
|
|
||||||
if (error_msg != NULL) {
|
if (error_msg != NULL) {
|
||||||
@@ -2325,18 +2350,18 @@ loff_t ext3_max_bitmap_size(int bits, int has_huge_files)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode,
|
blkcnt_t ext3_inode_blocks(struct ext4_inode *raw_inode,
|
||||||
struct inode *inode)
|
struct inode *inode)
|
||||||
{
|
{
|
||||||
blkcnt_t i_blocks ;
|
blkcnt_t i_blocks ;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv;
|
PEXT2_VCB Vcb = (PEXT2_VCB)sb->s_priv;
|
||||||
|
|
||||||
if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
|
if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
|
||||||
EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
|
EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
|
||||||
/* we are using combined 48 bit field */
|
/* we are using combined 48 bit field */
|
||||||
i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
|
i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 |
|
||||||
le32_to_cpu(raw_inode->i_blocks);
|
le32_to_cpu(raw_inode->i_blocks_lo);
|
||||||
if (inode->i_flags & EXT4_HUGE_FILE_FL) {
|
if (inode->i_flags & EXT4_HUGE_FILE_FL) {
|
||||||
/* i_blocks represent file system block size */
|
/* i_blocks represent file system block size */
|
||||||
return i_blocks << (BLOCK_BITS - 9);
|
return i_blocks << (BLOCK_BITS - 9);
|
||||||
@@ -2344,11 +2369,11 @@ blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode,
|
|||||||
return i_blocks;
|
return i_blocks;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return le32_to_cpu(raw_inode->i_blocks);
|
return le32_to_cpu(raw_inode->i_blocks_lo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ext3_inode_blocks_set(struct ext3_inode *raw_inode,
|
int ext3_inode_blocks_set(struct ext4_inode *raw_inode,
|
||||||
struct inode * inode)
|
struct inode * inode)
|
||||||
{
|
{
|
||||||
u64 i_blocks = inode->i_blocks;
|
u64 i_blocks = inode->i_blocks;
|
||||||
@@ -2360,13 +2385,13 @@ int ext3_inode_blocks_set(struct ext3_inode *raw_inode,
|
|||||||
* i_blocks can be represnted in a 32 bit variable
|
* i_blocks can be represnted in a 32 bit variable
|
||||||
* as multiple of 512 bytes
|
* as multiple of 512 bytes
|
||||||
*/
|
*/
|
||||||
raw_inode->i_blocks = cpu_to_le32(i_blocks);
|
raw_inode->i_blocks_lo = cpu_to_le32(i_blocks);
|
||||||
raw_inode->i_blocks_high = 0;
|
raw_inode->i_blocks_high = 0;
|
||||||
inode->i_flags &= ~EXT4_HUGE_FILE_FL;
|
inode->i_flags &= ~EXT4_HUGE_FILE_FL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
|
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
|
||||||
EXT3_SET_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
|
EXT3_SET_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
|
||||||
Ext2SaveSuper(NULL, Vcb);
|
Ext2SaveSuper(NULL, Vcb);
|
||||||
}
|
}
|
||||||
@@ -2376,14 +2401,14 @@ int ext3_inode_blocks_set(struct ext3_inode *raw_inode,
|
|||||||
* i_blocks can be represented in a 48 bit variable
|
* i_blocks can be represented in a 48 bit variable
|
||||||
* as multiple of 512 bytes
|
* as multiple of 512 bytes
|
||||||
*/
|
*/
|
||||||
raw_inode->i_blocks = (__u32)cpu_to_le32(i_blocks);
|
raw_inode->i_blocks_lo = (__u32)cpu_to_le32(i_blocks);
|
||||||
raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
|
raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
|
||||||
inode->i_flags &= ~EXT4_HUGE_FILE_FL;
|
inode->i_flags &= ~EXT4_HUGE_FILE_FL;
|
||||||
} else {
|
} else {
|
||||||
inode->i_flags |= EXT4_HUGE_FILE_FL;
|
inode->i_flags |= EXT4_HUGE_FILE_FL;
|
||||||
/* i_block is stored in file system block size */
|
/* i_block is stored in file system block size */
|
||||||
i_blocks = i_blocks >> (BLOCK_BITS - 9);
|
i_blocks = i_blocks >> (BLOCK_BITS - 9);
|
||||||
raw_inode->i_blocks = (__u32)cpu_to_le32(i_blocks);
|
raw_inode->i_blocks_lo = (__u32)cpu_to_le32(i_blocks);
|
||||||
raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
|
raw_inode->i_blocks_high = (__u16)cpu_to_le16(i_blocks >> 32);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2392,7 +2417,7 @@ int ext3_inode_blocks_set(struct ext3_inode *raw_inode,
|
|||||||
ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
|
ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le32_to_cpu(bg->bg_block_bitmap) |
|
return le32_to_cpu(bg->bg_block_bitmap_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
|
(ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
|
||||||
}
|
}
|
||||||
@@ -2400,7 +2425,7 @@ ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
|
|||||||
ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
|
ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le32_to_cpu(bg->bg_inode_bitmap) |
|
return le32_to_cpu(bg->bg_inode_bitmap_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
|
(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
|
||||||
}
|
}
|
||||||
@@ -2408,7 +2433,7 @@ ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
|
|||||||
ext4_fsblk_t ext4_inode_table(struct super_block *sb,
|
ext4_fsblk_t ext4_inode_table(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le32_to_cpu(bg->bg_inode_table) |
|
return le32_to_cpu(bg->bg_inode_table_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
|
(ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
|
||||||
}
|
}
|
||||||
@@ -2416,7 +2441,7 @@ ext4_fsblk_t ext4_inode_table(struct super_block *sb,
|
|||||||
__u32 ext4_free_blks_count(struct super_block *sb,
|
__u32 ext4_free_blks_count(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le16_to_cpu(bg->bg_free_blocks_count) |
|
return le16_to_cpu(bg->bg_free_blocks_count_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
|
(__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
|
||||||
}
|
}
|
||||||
@@ -2424,7 +2449,7 @@ __u32 ext4_free_blks_count(struct super_block *sb,
|
|||||||
__u32 ext4_free_inodes_count(struct super_block *sb,
|
__u32 ext4_free_inodes_count(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le16_to_cpu(bg->bg_free_inodes_count) |
|
return le16_to_cpu(bg->bg_free_inodes_count_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
|
(__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
|
||||||
}
|
}
|
||||||
@@ -2432,7 +2457,7 @@ __u32 ext4_free_inodes_count(struct super_block *sb,
|
|||||||
__u32 ext4_used_dirs_count(struct super_block *sb,
|
__u32 ext4_used_dirs_count(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le16_to_cpu(bg->bg_used_dirs_count) |
|
return le16_to_cpu(bg->bg_used_dirs_count_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
|
(__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
|
||||||
}
|
}
|
||||||
@@ -2440,7 +2465,7 @@ __u32 ext4_used_dirs_count(struct super_block *sb,
|
|||||||
__u32 ext4_itable_unused_count(struct super_block *sb,
|
__u32 ext4_itable_unused_count(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg)
|
struct ext4_group_desc *bg)
|
||||||
{
|
{
|
||||||
return le16_to_cpu(bg->bg_itable_unused) |
|
return le16_to_cpu(bg->bg_itable_unused_lo) |
|
||||||
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
||||||
(__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
|
(__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
|
||||||
}
|
}
|
||||||
@@ -2448,7 +2473,7 @@ __u32 ext4_itable_unused_count(struct super_block *sb,
|
|||||||
void ext4_block_bitmap_set(struct super_block *sb,
|
void ext4_block_bitmap_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
||||||
{
|
{
|
||||||
bg->bg_block_bitmap = cpu_to_le32((u32)blk);
|
bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
|
bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
|
||||||
}
|
}
|
||||||
@@ -2456,7 +2481,7 @@ void ext4_block_bitmap_set(struct super_block *sb,
|
|||||||
void ext4_inode_bitmap_set(struct super_block *sb,
|
void ext4_inode_bitmap_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
||||||
{
|
{
|
||||||
bg->bg_inode_bitmap = cpu_to_le32((u32)blk);
|
bg->bg_inode_bitmap_lo = cpu_to_le32((u32)blk);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
|
bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
|
||||||
}
|
}
|
||||||
@@ -2464,7 +2489,7 @@ void ext4_inode_bitmap_set(struct super_block *sb,
|
|||||||
void ext4_inode_table_set(struct super_block *sb,
|
void ext4_inode_table_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
struct ext4_group_desc *bg, ext4_fsblk_t blk)
|
||||||
{
|
{
|
||||||
bg->bg_inode_table = cpu_to_le32((u32)blk);
|
bg->bg_inode_table_lo = cpu_to_le32((u32)blk);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
|
bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
|
||||||
}
|
}
|
||||||
@@ -2472,7 +2497,7 @@ void ext4_inode_table_set(struct super_block *sb,
|
|||||||
void ext4_free_blks_set(struct super_block *sb,
|
void ext4_free_blks_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, __u32 count)
|
struct ext4_group_desc *bg, __u32 count)
|
||||||
{
|
{
|
||||||
bg->bg_free_blocks_count = cpu_to_le16((__u16)count);
|
bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16);
|
bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16);
|
||||||
}
|
}
|
||||||
@@ -2480,7 +2505,7 @@ void ext4_free_blks_set(struct super_block *sb,
|
|||||||
void ext4_free_inodes_set(struct super_block *sb,
|
void ext4_free_inodes_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, __u32 count)
|
struct ext4_group_desc *bg, __u32 count)
|
||||||
{
|
{
|
||||||
bg->bg_free_inodes_count = cpu_to_le16((__u16)count);
|
bg->bg_free_inodes_count_lo = cpu_to_le16((__u16)count);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16);
|
bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16);
|
||||||
}
|
}
|
||||||
@@ -2488,7 +2513,7 @@ void ext4_free_inodes_set(struct super_block *sb,
|
|||||||
void ext4_used_dirs_set(struct super_block *sb,
|
void ext4_used_dirs_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, __u32 count)
|
struct ext4_group_desc *bg, __u32 count)
|
||||||
{
|
{
|
||||||
bg->bg_used_dirs_count = cpu_to_le16((__u16)count);
|
bg->bg_used_dirs_count_lo = cpu_to_le16((__u16)count);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16);
|
bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16);
|
||||||
}
|
}
|
||||||
@@ -2496,99 +2521,11 @@ void ext4_used_dirs_set(struct super_block *sb,
|
|||||||
void ext4_itable_unused_set(struct super_block *sb,
|
void ext4_itable_unused_set(struct super_block *sb,
|
||||||
struct ext4_group_desc *bg, __u32 count)
|
struct ext4_group_desc *bg, __u32 count)
|
||||||
{
|
{
|
||||||
bg->bg_itable_unused = cpu_to_le16((__u16)count);
|
bg->bg_itable_unused_lo = cpu_to_le16((__u16)count);
|
||||||
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
||||||
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
|
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
|
|
||||||
__u16 const crc16_table[256] = {
|
|
||||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
|
||||||
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
|
||||||
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
|
||||||
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
|
||||||
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
|
||||||
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
|
||||||
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
|
||||||
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
|
||||||
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
|
||||||
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
|
||||||
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
|
||||||
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
|
||||||
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
|
||||||
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
|
||||||
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
|
||||||
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
|
||||||
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
|
||||||
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
|
||||||
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
|
||||||
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
|
||||||
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
|
||||||
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
|
||||||
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
|
||||||
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
|
||||||
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
|
||||||
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
|
||||||
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
|
||||||
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
|
||||||
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
|
||||||
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
|
||||||
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
|
||||||
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline __u16 crc16_byte(__u16 crc, const __u8 data)
|
|
||||||
{
|
|
||||||
return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
|
|
||||||
}
|
|
||||||
|
|
||||||
__u16 crc16(__u16 crc, __u8 const *buffer, size_t len)
|
|
||||||
{
|
|
||||||
while (len--)
|
|
||||||
crc = crc16_byte(crc, *buffer++);
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
|
|
||||||
struct ext4_group_desc *gdp)
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
__u16 crc = 0;
|
|
||||||
__le32 le_group = cpu_to_le32(block_group);
|
|
||||||
|
|
||||||
/* old crc16 code */
|
|
||||||
if (!(sbi->s_es->s_feature_ro_compat &
|
|
||||||
cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
offset = offsetof(struct ext4_group_desc, bg_checksum);
|
|
||||||
|
|
||||||
crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
|
|
||||||
crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
|
|
||||||
crc = crc16(crc, (__u8 *)gdp, offset);
|
|
||||||
offset += sizeof(gdp->bg_checksum); /* skip checksum */
|
|
||||||
/* for checksum of struct ext4_group_desc do the rest...*/
|
|
||||||
if ((sbi->s_es->s_feature_incompat &
|
|
||||||
cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
|
|
||||||
offset < le16_to_cpu(sbi->s_es->s_desc_size))
|
|
||||||
crc = crc16(crc, (__u8 *)gdp + offset,
|
|
||||||
le16_to_cpu(sbi->s_es->s_desc_size) -
|
|
||||||
offset);
|
|
||||||
|
|
||||||
return cpu_to_le16(crc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
|
|
||||||
struct ext4_group_desc *gdp)
|
|
||||||
{
|
|
||||||
if ((sbi->s_es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) &&
|
|
||||||
(gdp->bg_checksum != ext4_group_desc_csum(sbi, block_group, gdp)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline int test_root(ext3_group_t a, ext3_group_t b)
|
static inline int test_root(ext3_group_t a, ext3_group_t b)
|
||||||
{
|
{
|
||||||
ext3_group_t num = b;
|
ext3_group_t num = b;
|
||||||
@@ -2618,7 +2555,7 @@ static int ext3_group_sparse(ext3_group_t group)
|
|||||||
*/
|
*/
|
||||||
int ext3_bg_has_super(struct super_block *sb, ext3_group_t group)
|
int ext3_bg_has_super(struct super_block *sb, ext3_group_t group)
|
||||||
{
|
{
|
||||||
if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
|
if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
|
||||||
EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
|
EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
|
||||||
!ext3_group_sparse(group))
|
!ext3_group_sparse(group))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2640,7 +2577,7 @@ static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb,
|
|||||||
static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
|
static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
|
||||||
ext4_group_t group)
|
ext4_group_t group)
|
||||||
{
|
{
|
||||||
return ext3_bg_has_super(sb, group) ? EXT3_SB(sb)->s_gdb_count : 0;
|
return ext3_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2655,10 +2592,10 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
|
|||||||
unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
|
unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
|
||||||
{
|
{
|
||||||
unsigned long first_meta_bg =
|
unsigned long first_meta_bg =
|
||||||
le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg);
|
le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
|
||||||
unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
|
unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
|
||||||
|
|
||||||
if (!EXT3_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
|
if (!EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
|
||||||
metagroup < first_meta_bg)
|
metagroup < first_meta_bg)
|
||||||
return ext4_bg_num_gdb_nometa(sb, group);
|
return ext4_bg_num_gdb_nometa(sb, group);
|
||||||
|
|
||||||
@@ -2669,13 +2606,13 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
|
|||||||
ext3_fsblk_t descriptor_loc(struct super_block *sb,
|
ext3_fsblk_t descriptor_loc(struct super_block *sb,
|
||||||
ext3_fsblk_t logical_sb_block, unsigned int nr)
|
ext3_fsblk_t logical_sb_block, unsigned int nr)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
ext3_group_t bg, first_meta_bg;
|
ext3_group_t bg, first_meta_bg;
|
||||||
int has_super = 0;
|
int has_super = 0;
|
||||||
|
|
||||||
first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
|
first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
|
||||||
|
|
||||||
if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
|
if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
|
||||||
nr < first_meta_bg)
|
nr < first_meta_bg)
|
||||||
return logical_sb_block + nr + 1;
|
return logical_sb_block + nr + 1;
|
||||||
bg = sbi->s_desc_per_block * nr;
|
bg = sbi->s_desc_per_block * nr;
|
||||||
@@ -2720,13 +2657,13 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
|
|||||||
ext4_group_t block_group,
|
ext4_group_t block_group,
|
||||||
struct ext4_group_desc *gdp)
|
struct ext4_group_desc *gdp)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
|
|
||||||
/* If checksum is bad mark all blocks and inodes use to prevent
|
/* If checksum is bad mark all blocks and inodes use to prevent
|
||||||
* allocation, essentially implementing a per-group read-only flag. */
|
* allocation, essentially implementing a per-group read-only flag. */
|
||||||
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
|
if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
|
||||||
ext4_error(sb, __FUNCTION__, "Checksum bad for group %u",
|
ext4_error(sb, __FUNCTION__, "Checksum bad for group %u",
|
||||||
block_group);
|
block_group);
|
||||||
ext4_free_blks_set(sb, gdp, 0);
|
ext4_free_blks_set(sb, gdp, 0);
|
||||||
@@ -2750,7 +2687,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
|
|||||||
void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
|
void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
|
||||||
ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
|
ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
|
||||||
{
|
{
|
||||||
struct ext3_super_block *es = EXT3_SB(sb)->s_es;
|
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
|
||||||
ext4_grpblk_t offset;
|
ext4_grpblk_t offset;
|
||||||
|
|
||||||
blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
|
blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
|
||||||
@@ -2776,11 +2713,11 @@ static int ext4_group_used_meta_blocks(struct super_block *sb,
|
|||||||
ext4_group_t block_group)
|
ext4_group_t block_group)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t tmp;
|
ext4_fsblk_t tmp;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
/* block bitmap, inode bitmap, and inode table blocks */
|
/* block bitmap, inode bitmap, and inode table blocks */
|
||||||
int used_blocks = sbi->s_itb_per_group + 2;
|
int used_blocks = sbi->s_itb_per_group + 2;
|
||||||
|
|
||||||
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
|
||||||
struct ext4_group_desc *gdp;
|
struct ext4_group_desc *gdp;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
|
|
||||||
@@ -2812,13 +2749,13 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
|
|||||||
{
|
{
|
||||||
int bit, bit_max;
|
int bit, bit_max;
|
||||||
unsigned free_blocks, group_blocks;
|
unsigned free_blocks, group_blocks;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
if (bh) {
|
if (bh) {
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
/* If checksum is bad mark all blocks used to prevent allocation
|
/* If checksum is bad mark all blocks used to prevent allocation
|
||||||
* essentially implementing a per-group read-only flag. */
|
* essentially implementing a per-group read-only flag. */
|
||||||
if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
|
if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
|
||||||
ext4_error(sb, __FUNCTION__,
|
ext4_error(sb, __FUNCTION__,
|
||||||
"Checksum bad for group %u", block_group);
|
"Checksum bad for group %u", block_group);
|
||||||
ext4_free_blks_set(sb, gdp, 0);
|
ext4_free_blks_set(sb, gdp, 0);
|
||||||
@@ -2833,7 +2770,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
|
|||||||
/* Check for superblock and gdt backups in this group */
|
/* Check for superblock and gdt backups in this group */
|
||||||
bit_max = ext3_bg_has_super(sb, block_group);
|
bit_max = ext3_bg_has_super(sb, block_group);
|
||||||
|
|
||||||
if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
|
if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
|
||||||
block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
|
block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
|
||||||
sbi->s_desc_per_block) {
|
sbi->s_desc_per_block) {
|
||||||
if (bit_max) {
|
if (bit_max) {
|
||||||
@@ -2869,7 +2806,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
|
|||||||
|
|
||||||
start = ext3_group_first_block_no(sb, block_group);
|
start = ext3_group_first_block_no(sb, block_group);
|
||||||
|
|
||||||
if (EXT3_HAS_INCOMPAT_FEATURE(sb,
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb,
|
||||||
EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
||||||
flex_bg = 1;
|
flex_bg = 1;
|
||||||
|
|
||||||
@@ -2910,7 +2847,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
|
|||||||
ext4_group_t block_group, struct buffer_head **bh)
|
ext4_group_t block_group, struct buffer_head **bh)
|
||||||
{
|
{
|
||||||
struct ext4_group_desc *desc = NULL;
|
struct ext4_group_desc *desc = NULL;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
PEXT2_VCB vcb = sb->s_priv;
|
PEXT2_VCB vcb = sb->s_priv;
|
||||||
ext4_group_t group;
|
ext4_group_t group;
|
||||||
ext4_group_t offset;
|
ext4_group_t offset;
|
||||||
@@ -2969,7 +2906,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
|
|||||||
struct ext4_group_desc *gdp;
|
struct ext4_group_desc *gdp;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count;
|
ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
|
||||||
|
|
||||||
desc_count = 0;
|
desc_count = 0;
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
@@ -2992,7 +2929,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
|
|||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
|
|
||||||
desc_count = 0;
|
desc_count = 0;
|
||||||
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
|
||||||
gdp = ext4_get_group_desc(sb, i, &bh);
|
gdp = ext4_get_group_desc(sb, i, &bh);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
continue;
|
continue;
|
||||||
@@ -3010,7 +2947,7 @@ unsigned long ext4_count_dirs(struct super_block * sb)
|
|||||||
unsigned long count = 0;
|
unsigned long count = 0;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
|
|
||||||
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
|
||||||
gdp = ext4_get_group_desc(sb, i, &bh);
|
gdp = ext4_get_group_desc(sb, i, &bh);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
continue;
|
continue;
|
||||||
@@ -3024,7 +2961,7 @@ unsigned long ext4_count_dirs(struct super_block * sb)
|
|||||||
int ext4_check_descriptors(struct super_block *sb)
|
int ext4_check_descriptors(struct super_block *sb)
|
||||||
{
|
{
|
||||||
PEXT2_VCB Vcb = sb->s_priv;
|
PEXT2_VCB Vcb = sb->s_priv;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
|
ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
|
||||||
ext4_fsblk_t last_block;
|
ext4_fsblk_t last_block;
|
||||||
ext4_fsblk_t block_bitmap;
|
ext4_fsblk_t block_bitmap;
|
||||||
@@ -3033,7 +2970,7 @@ int ext4_check_descriptors(struct super_block *sb)
|
|||||||
int flexbg_flag = 0;
|
int flexbg_flag = 0;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
|
|
||||||
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
|
||||||
flexbg_flag = 1;
|
flexbg_flag = 1;
|
||||||
|
|
||||||
DEBUG(DL_INF, ("Checking group descriptors"));
|
DEBUG(DL_INF, ("Checking group descriptors"));
|
||||||
@@ -3078,15 +3015,12 @@ int ext4_check_descriptors(struct super_block *sb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
|
if (!ext4_group_desc_csum_verify(sb, i, gdp)) {
|
||||||
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
||||||
"Checksum for group %u failed (%u!=%u)\n",
|
"Checksum for group %u failed.\n", i);
|
||||||
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
|
||||||
gdp)),
|
|
||||||
le16_to_cpu(gdp->bg_checksum));
|
|
||||||
if (!IsVcbReadOnly(Vcb)) {
|
if (!IsVcbReadOnly(Vcb)) {
|
||||||
__brelse(bh);
|
//__brelse(bh);
|
||||||
return 0;
|
//return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -758,7 +758,7 @@ static int call_filldir(struct file * filp, void * cookie,
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
struct fake_dirent
|
struct fake_dirent
|
||||||
{
|
{
|
||||||
__le32 inode;
|
__le32 inode;
|
||||||
@@ -823,7 +823,7 @@ struct dx_map_entry
|
|||||||
__u16 offs;
|
__u16 offs;
|
||||||
__u16 size;
|
__u16 size;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Future: use high four bits of block for coalesce-on-delete flags
|
* Future: use high four bits of block for coalesce-on-delete flags
|
||||||
* Mask them off for now.
|
* Mask them off for now.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <ext2fs.h>
|
#include <ext2fs.h>
|
||||||
#include <linux/jbd.h>
|
#include <linux/jbd.h>
|
||||||
#include <linux/ext3_fs.h>
|
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ DRIVERTYPE=FS
|
|||||||
INCLUDES=.;..;..\include;$(DRIVER_INC_PATH);
|
INCLUDES=.;..;..\include;$(DRIVER_INC_PATH);
|
||||||
|
|
||||||
# The source code:
|
# The source code:
|
||||||
SOURCES= ext4_bh.c ext4_extents.c ext4_jbd2.c extents.c \
|
SOURCES= ext4_bh.c ext4_csum.c ext4_extents.c ext4_jbd2.c ext4_xattr.c \
|
||||||
ext4_xattr.c
|
extents.c
|
||||||
|
|||||||
757
Ext4Fsd/ext4/ext4_csum.c
Normal file
757
Ext4Fsd/ext4/ext4_csum.c
Normal file
@@ -0,0 +1,757 @@
|
|||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
|
* PROJECT: Ext2-Ext4 File System Driver for WinXP-Win10
|
||||||
|
* FILE: ext4_csum.c
|
||||||
|
* PROGRAMMER: Bo Brant<6E>n <bosse@acc.umu.se>
|
||||||
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include "ext2fs.h"
|
||||||
|
#include "linux\ext4.h"
|
||||||
|
#include "linux\ext4_xattr.h"
|
||||||
|
|
||||||
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
|
||||||
|
__u16 const crc16_table[256] = {
|
||||||
|
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||||
|
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||||
|
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||||
|
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||||
|
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||||
|
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||||
|
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||||
|
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||||
|
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||||
|
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||||
|
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||||
|
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||||
|
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||||
|
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||||
|
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||||
|
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||||
|
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||||
|
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||||
|
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||||
|
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||||
|
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||||
|
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||||
|
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||||
|
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||||
|
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||||
|
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||||
|
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||||
|
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||||
|
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||||
|
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||||
|
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||||
|
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline __u16 crc16_byte(__u16 crc, const __u8 data)
|
||||||
|
{
|
||||||
|
return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
static __u16 crc16(__u16 crc, __u8 const *buffer, size_t len)
|
||||||
|
{
|
||||||
|
while (len--)
|
||||||
|
crc = crc16_byte(crc, *buffer++);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the CRC-32C table
|
||||||
|
* Generated with:
|
||||||
|
* width = 32 bits
|
||||||
|
* poly = 0x1EDC6F41
|
||||||
|
* reflect input bytes = true
|
||||||
|
* reflect output bytes = true
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const __u32 crc32c_table[256] = {
|
||||||
|
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
|
||||||
|
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
|
||||||
|
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
|
||||||
|
0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
|
||||||
|
0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
|
||||||
|
0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
|
||||||
|
0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
|
||||||
|
0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
|
||||||
|
0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
|
||||||
|
0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
|
||||||
|
0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
|
||||||
|
0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
|
||||||
|
0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
|
||||||
|
0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
|
||||||
|
0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
|
||||||
|
0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
|
||||||
|
0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
|
||||||
|
0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
|
||||||
|
0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
|
||||||
|
0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
|
||||||
|
0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
|
||||||
|
0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
|
||||||
|
0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
|
||||||
|
0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
|
||||||
|
0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
|
||||||
|
0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
|
||||||
|
0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
|
||||||
|
0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
|
||||||
|
0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
|
||||||
|
0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
|
||||||
|
0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
|
||||||
|
0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
|
||||||
|
0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
|
||||||
|
0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
|
||||||
|
0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
|
||||||
|
0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
|
||||||
|
0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
|
||||||
|
0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
|
||||||
|
0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
|
||||||
|
0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
|
||||||
|
0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
|
||||||
|
0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
|
||||||
|
0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
|
||||||
|
0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
|
||||||
|
0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
|
||||||
|
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
|
||||||
|
0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
|
||||||
|
0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
|
||||||
|
0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
|
||||||
|
0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
|
||||||
|
0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
|
||||||
|
0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
|
||||||
|
0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
|
||||||
|
0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
|
||||||
|
0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
|
||||||
|
0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
|
||||||
|
0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
|
||||||
|
0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
|
||||||
|
0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
|
||||||
|
0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
|
||||||
|
0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
|
||||||
|
0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
|
||||||
|
0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
|
||||||
|
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Steps through buffer one byte at at time, calculates reflected
|
||||||
|
* crc using table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __u32 crc32c(__u32 crc, const __u8 *data, unsigned int length)
|
||||||
|
{
|
||||||
|
while (length--)
|
||||||
|
crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
__u32 ext4_chksum(struct ext4_sb_info *sbi, __u32 crc,
|
||||||
|
const void *buffer, unsigned int length)
|
||||||
|
{
|
||||||
|
return crc32c(crc, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the superblock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le32 ext4_superblock_csum(struct super_block *sb,
|
||||||
|
struct ext4_super_block *es)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
int offset = offsetof(struct ext4_super_block, s_checksum);
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, ~0, (char *)es, offset);
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_superblock_csum_verify(struct super_block *sb,
|
||||||
|
struct ext4_super_block *es)
|
||||||
|
{
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return es->s_checksum == ext4_superblock_csum(sb, es);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_superblock_csum_set(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
es->s_checksum = ext4_superblock_csum(sb, es);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the group descriptors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
|
||||||
|
struct ext4_group_desc *gdp)
|
||||||
|
{
|
||||||
|
unsigned int offset = offsetof(struct ext4_group_desc, bg_checksum);
|
||||||
|
__u16 crc;
|
||||||
|
__le32 le_group = cpu_to_le32(block_group);
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (ext4_has_feature_metadata_csum(sb)) {
|
||||||
|
/* Use new metadata_csum algorithm */
|
||||||
|
__u32 csum32;
|
||||||
|
__u16 dummy_csum = 0;
|
||||||
|
|
||||||
|
csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
|
||||||
|
sizeof(le_group));
|
||||||
|
csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, offset);
|
||||||
|
csum32 = ext4_chksum(sbi, csum32, (__u8 *)&dummy_csum,
|
||||||
|
sizeof(dummy_csum));
|
||||||
|
offset += sizeof(dummy_csum);
|
||||||
|
if (offset < sbi->s_desc_size)
|
||||||
|
csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp + offset,
|
||||||
|
sbi->s_desc_size - offset);
|
||||||
|
|
||||||
|
crc = csum32 & 0xFFFF;
|
||||||
|
} else if (ext4_has_feature_gdt_csum(sb)) {
|
||||||
|
/* old crc16 code */
|
||||||
|
crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
|
||||||
|
crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
|
||||||
|
crc = crc16(crc, (__u8 *)gdp, offset);
|
||||||
|
offset += sizeof(gdp->bg_checksum); /* skip checksum */
|
||||||
|
/* for checksum of struct ext4_group_desc do the rest...*/
|
||||||
|
if (ext4_has_feature_64bit(sb) &&
|
||||||
|
offset < le16_to_cpu(sbi->s_es->s_desc_size))
|
||||||
|
crc = crc16(crc, (__u8 *)gdp + offset,
|
||||||
|
le16_to_cpu(sbi->s_es->s_desc_size) -
|
||||||
|
offset);
|
||||||
|
} else {
|
||||||
|
crc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu_to_le16(crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_group_desc_csum_verify(struct super_block *sb, __u32 block_group,
|
||||||
|
struct ext4_group_desc *gdp)
|
||||||
|
{
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return gdp->bg_checksum == ext4_group_desc_csum(sb, block_group, gdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
|
||||||
|
struct ext4_group_desc *gdp)
|
||||||
|
{
|
||||||
|
if (!ext4_has_group_desc_csum(sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdp->bg_checksum = ext4_group_desc_csum(sb, block_group, gdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the inode bitmap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
|
||||||
|
struct ext4_group_desc *gdp,
|
||||||
|
struct buffer_head *bh, int sz)
|
||||||
|
{
|
||||||
|
__u32 hi;
|
||||||
|
__u32 provided, calculated;
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo);
|
||||||
|
calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
|
||||||
|
if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) {
|
||||||
|
hi = le16_to_cpu(gdp->bg_inode_bitmap_csum_hi);
|
||||||
|
provided |= (hi << 16);
|
||||||
|
} else
|
||||||
|
calculated &= 0xFFFF;
|
||||||
|
|
||||||
|
return provided == calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
|
||||||
|
struct ext4_group_desc *gdp,
|
||||||
|
struct buffer_head *bh, int sz)
|
||||||
|
{
|
||||||
|
__u32 csum;
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
|
||||||
|
gdp->bg_inode_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
|
||||||
|
if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
|
||||||
|
gdp->bg_inode_bitmap_csum_hi = cpu_to_le16(csum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the block bitmap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
|
||||||
|
struct ext4_group_desc *gdp,
|
||||||
|
struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
__u32 hi;
|
||||||
|
__u32 provided, calculated;
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo);
|
||||||
|
calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
|
||||||
|
if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END) {
|
||||||
|
hi = le16_to_cpu(gdp->bg_block_bitmap_csum_hi);
|
||||||
|
provided |= (hi << 16);
|
||||||
|
} else
|
||||||
|
calculated &= 0xFFFF;
|
||||||
|
|
||||||
|
return provided == calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
|
||||||
|
struct ext4_group_desc *gdp,
|
||||||
|
struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
|
||||||
|
__u32 csum;
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
|
||||||
|
gdp->bg_block_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
|
||||||
|
if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END)
|
||||||
|
gdp->bg_block_bitmap_csum_hi = cpu_to_le16(csum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the inodes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le32 ext4_inode_csum_seed(struct inode *inode)
|
||||||
|
{
|
||||||
|
/* Precompute checksum seed for inode metadata */
|
||||||
|
if (ext4_has_feature_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;
|
||||||
|
csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum));
|
||||||
|
return ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw,
|
||||||
|
struct ext4_inode_info *ei)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
__u32 csum;
|
||||||
|
__u16 dummy_csum = 0;
|
||||||
|
int offset = offsetof(struct ext4_inode, i_checksum_lo);
|
||||||
|
unsigned int csum_size = sizeof(dummy_csum);
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, ext4_inode_csum_seed(inode), (__u8 *)raw, offset);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size);
|
||||||
|
offset += csum_size;
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
|
||||||
|
EXT4_GOOD_OLD_INODE_SIZE - offset);
|
||||||
|
|
||||||
|
if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
|
||||||
|
offset = offsetof(struct ext4_inode, i_checksum_hi);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)raw +
|
||||||
|
EXT4_GOOD_OLD_INODE_SIZE,
|
||||||
|
offset - EXT4_GOOD_OLD_INODE_SIZE);
|
||||||
|
if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum,
|
||||||
|
csum_size);
|
||||||
|
offset += csum_size;
|
||||||
|
}
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
|
||||||
|
EXT4_INODE_SIZE(inode->i_sb) - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return csum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw,
|
||||||
|
struct ext4_inode_info *ei)
|
||||||
|
{
|
||||||
|
__u32 provided, calculated, isz;
|
||||||
|
|
||||||
|
if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
|
||||||
|
cpu_to_le32(EXT4_OS_LINUX) ||
|
||||||
|
!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
provided = le16_to_cpu(raw->i_checksum_lo);
|
||||||
|
calculated = ext4_inode_csum(inode, raw, ei);
|
||||||
|
if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
|
||||||
|
EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))
|
||||||
|
{provided |= ((__u32)le16_to_cpu(raw->i_checksum_hi)) << 16;isz=EXT4_INODE_SIZE(inode->i_sb);}
|
||||||
|
else
|
||||||
|
{calculated &= 0xFFFF;isz=EXT4_GOOD_OLD_INODE_SIZE;}
|
||||||
|
|
||||||
|
if (provided != calculated) {
|
||||||
|
DbgPrint("inod %d checksum invalid: %lx!=%lx, isz=%u\n", inode->i_ino, provided, calculated, isz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return provided == calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,
|
||||||
|
struct ext4_inode_info *ei)
|
||||||
|
{
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
|
||||||
|
cpu_to_le32(EXT4_OS_LINUX) ||
|
||||||
|
!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
csum = ext4_inode_csum(inode, raw, ei);
|
||||||
|
raw->i_checksum_lo = cpu_to_le16(csum & 0xFFFF);
|
||||||
|
if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
|
||||||
|
EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))
|
||||||
|
raw->i_checksum_hi = cpu_to_le16(csum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the extent blocks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le32 ext4_extent_block_csum(struct inode *inode,
|
||||||
|
struct ext4_extent_header *eh)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, ext4_inode_csum_seed(inode), (__u8 *)eh, EXT4_EXTENT_TAIL_OFFSET(eh));
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_extent_block_csum_verify(struct inode *inode,
|
||||||
|
struct ext4_extent_header *eh)
|
||||||
|
{
|
||||||
|
struct ext4_extent_tail *et;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
et = find_ext4_extent_tail(eh);
|
||||||
|
return et->et_checksum == ext4_extent_block_csum(inode, eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_extent_block_csum_set(struct inode *inode,
|
||||||
|
struct ext4_extent_header *eh)
|
||||||
|
{
|
||||||
|
struct ext4_extent_tail *et;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
et = find_ext4_extent_tail(eh);
|
||||||
|
et->et_checksum = ext4_extent_block_csum(inode, eh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the directory entrys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void initialize_dirent_tail(struct ext4_dir_entry_tail *t,
|
||||||
|
unsigned int blocksize)
|
||||||
|
{
|
||||||
|
memset(t, 0, sizeof(struct ext4_dir_entry_tail));
|
||||||
|
t->det_rec_len = ext4_rec_len_to_disk(
|
||||||
|
sizeof(struct ext4_dir_entry_tail), blocksize);
|
||||||
|
t->det_reserved_ft = EXT4_FT_DIR_CSUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Walk through a dirent block to find a checksum "dirent" at the tail */
|
||||||
|
static struct ext4_dir_entry_tail *get_dirent_tail(struct inode *inode,
|
||||||
|
struct ext4_dir_entry *de)
|
||||||
|
{
|
||||||
|
struct ext4_dir_entry_tail *t;
|
||||||
|
|
||||||
|
#ifdef PARANOID
|
||||||
|
struct ext4_dir_entry *d, *top;
|
||||||
|
|
||||||
|
d = de;
|
||||||
|
top = (struct ext4_dir_entry *)(((void *)de) +
|
||||||
|
(EXT4_BLOCK_SIZE(inode->i_sb) -
|
||||||
|
sizeof(struct ext4_dir_entry_tail)));
|
||||||
|
while (d < top && d->rec_len)
|
||||||
|
d = (struct ext4_dir_entry *)(((void *)d) +
|
||||||
|
le16_to_cpu(d->rec_len));
|
||||||
|
|
||||||
|
if (d != top)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
t = (struct ext4_dir_entry_tail *)d;
|
||||||
|
#else
|
||||||
|
t = EXT4_DIRENT_TAIL(de, EXT4_BLOCK_SIZE(inode->i_sb));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (t->det_reserved_zero1 ||
|
||||||
|
le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) ||
|
||||||
|
t->det_reserved_zero2 ||
|
||||||
|
t->det_reserved_ft != EXT4_FT_DIR_CSUM)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __le32 ext4_dirent_csum(struct inode *inode,
|
||||||
|
struct ext4_dir_entry *dirent, int size)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, ext4_inode_csum_seed(inode), (__u8 *)dirent, size);
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
|
||||||
|
{
|
||||||
|
struct ext4_dir_entry_tail *t;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
t = get_dirent_tail(inode, dirent);
|
||||||
|
if (!t) {
|
||||||
|
DbgPrint("No space for directory leaf checksum. Please run e2fsck -D.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->det_checksum != ext4_dirent_csum(inode, dirent,
|
||||||
|
(unsigned int)((unsigned char *)t - (unsigned char *)dirent)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_dirent_csum_set(struct inode *inode,
|
||||||
|
struct ext4_dir_entry *dirent)
|
||||||
|
{
|
||||||
|
struct ext4_dir_entry_tail *t;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
t = get_dirent_tail(inode, dirent);
|
||||||
|
if (!t) {
|
||||||
|
DbgPrint("No space for directory leaf checksum. Please run e2fsck -D.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->det_checksum = ext4_dirent_csum(inode, dirent,
|
||||||
|
(unsigned int)((unsigned char *)t - (unsigned char *)dirent));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dx_countlimit *get_dx_countlimit(struct inode *inode,
|
||||||
|
struct ext4_dir_entry *dirent,
|
||||||
|
int *offset)
|
||||||
|
{
|
||||||
|
struct ext4_dir_entry *dp;
|
||||||
|
struct dx_root_info *root;
|
||||||
|
int count_offset;
|
||||||
|
|
||||||
|
if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb))
|
||||||
|
count_offset = 8;
|
||||||
|
else if (le16_to_cpu(dirent->rec_len) == 12) {
|
||||||
|
dp = (struct ext4_dir_entry *)(((unsigned char *)dirent) + 12);
|
||||||
|
if (le16_to_cpu(dp->rec_len) !=
|
||||||
|
EXT4_BLOCK_SIZE(inode->i_sb) - 12)
|
||||||
|
return NULL;
|
||||||
|
root = (struct dx_root_info *)(((unsigned char *)dp + 12));
|
||||||
|
if (root->reserved_zero ||
|
||||||
|
root->info_length != sizeof(struct dx_root_info))
|
||||||
|
return NULL;
|
||||||
|
count_offset = 32;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (offset)
|
||||||
|
*offset = count_offset;
|
||||||
|
return (struct dx_countlimit *)(((unsigned char *)dirent) + count_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __le32 ext4_dx_csum(struct inode *inode, struct ext4_dir_entry *dirent,
|
||||||
|
int count_offset, int count, struct dx_tail *t)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
__u32 csum;
|
||||||
|
int size;
|
||||||
|
__u32 dummy_csum = 0;
|
||||||
|
int offset = offsetof(struct dx_tail, dt_checksum);
|
||||||
|
|
||||||
|
size = count_offset + (count * sizeof(struct dx_entry));
|
||||||
|
csum = ext4_chksum(sbi, ext4_inode_csum_seed(inode), (__u8 *)dirent, size);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)t, offset);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_dx_csum_verify(struct inode *inode,
|
||||||
|
struct ext4_dir_entry *dirent)
|
||||||
|
{
|
||||||
|
struct dx_countlimit *c;
|
||||||
|
struct dx_tail *t;
|
||||||
|
int count_offset, limit, count;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
c = get_dx_countlimit(inode, dirent, &count_offset);
|
||||||
|
if (!c) {
|
||||||
|
DbgPrint("dir seems corrupt? Run e2fsck -D.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
limit = le16_to_cpu(c->limit);
|
||||||
|
count = le16_to_cpu(c->count);
|
||||||
|
if (count_offset + (limit * sizeof(struct dx_entry)) >
|
||||||
|
EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
|
||||||
|
DbgPrint("warn_no_space_for_csum in inode\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
t = (struct dx_tail *)(((struct dx_entry *)c) + limit);
|
||||||
|
|
||||||
|
return t->dt_checksum == ext4_dx_csum(inode, dirent, count_offset, count, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
|
||||||
|
{
|
||||||
|
struct dx_countlimit *c;
|
||||||
|
struct dx_tail *t;
|
||||||
|
int count_offset, limit, count;
|
||||||
|
|
||||||
|
if (!ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
c = get_dx_countlimit(inode, dirent, &count_offset);
|
||||||
|
if (!c) {
|
||||||
|
DbgPrint("dir seems corrupt? Run e2fsck -D.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
limit = le16_to_cpu(c->limit);
|
||||||
|
count = le16_to_cpu(c->count);
|
||||||
|
if (count_offset + (limit * sizeof(struct dx_entry)) >
|
||||||
|
EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) {
|
||||||
|
DbgPrint("warn_no_space_for_csum in inode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t = (struct dx_tail *)(((struct dx_entry *)c) + limit);
|
||||||
|
|
||||||
|
t->dt_checksum = ext4_dx_csum(inode, dirent, count_offset, count, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the multiple mount point structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
|
int offset = offsetof(struct mmp_struct, mmp_checksum);
|
||||||
|
__u32 csum;
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, sbi->s_csum_seed, (char *)mmp, offset);
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp)
|
||||||
|
{
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return mmp->mmp_checksum == ext4_mmp_csum(sb, mmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp)
|
||||||
|
{
|
||||||
|
if (!ext4_has_feature_metadata_csum(sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mmp->mmp_checksum = ext4_mmp_csum(sb, mmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata checksum functions for the extended attributes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __le32 ext4_xattr_block_csum(struct inode *inode,
|
||||||
|
sector_t block_nr,
|
||||||
|
struct ext4_xattr_header *hdr)
|
||||||
|
{
|
||||||
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
||||||
|
__u32 csum;
|
||||||
|
__le64 dsk_block_nr = cpu_to_le64(block_nr);
|
||||||
|
__u32 dummy_csum = 0;
|
||||||
|
int offset = offsetof(struct ext4_xattr_header, h_checksum);
|
||||||
|
|
||||||
|
csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr,
|
||||||
|
sizeof(dsk_block_nr));
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
|
||||||
|
offset += sizeof(dummy_csum);
|
||||||
|
csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset,
|
||||||
|
EXT4_BLOCK_SIZE(inode->i_sb) - offset);
|
||||||
|
|
||||||
|
return cpu_to_le32(csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext4_xattr_block_csum_verify(struct inode *inode,
|
||||||
|
struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
struct ext4_xattr_header *hdr = EXT4_XATTR_BHDR(bh);
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if (ext4_has_feature_metadata_csum(inode->i_sb)) {
|
||||||
|
lock_buffer(bh);
|
||||||
|
ret = (hdr->h_checksum == ext4_xattr_block_csum(inode,
|
||||||
|
bh->b_blocknr, hdr));
|
||||||
|
unlock_buffer(bh);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ext4_xattr_block_csum_set(struct inode *inode,
|
||||||
|
struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
if (ext4_has_feature_metadata_csum(inode->i_sb))
|
||||||
|
EXT4_XATTR_BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode,
|
||||||
|
bh->b_blocknr, EXT4_XATTR_BHDR(bh));
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
#include "linux\ext4.h"
|
#include "linux\ext4.h"
|
||||||
|
#include "linux\jbd.h"
|
||||||
|
|
||||||
static handle_t no_journal;
|
static handle_t no_journal;
|
||||||
|
|
||||||
|
|||||||
@@ -2224,6 +2224,10 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ext4_superblock_csum_verify(&Vcb->sb, Ext2Sb)) {
|
||||||
|
DbgPrint("Found ext4 filesystem with invalid superblock checksum. Run e2fsck?\n");
|
||||||
|
}
|
||||||
|
|
||||||
SetLongFlag(Vcb->Flags, VCB_MOUNTED);
|
SetLongFlag(Vcb->Flags, VCB_MOUNTED);
|
||||||
SetFlag(Vcb->Vpb->Flags, VPB_MOUNTED);
|
SetFlag(Vcb->Vpb->Flags, VPB_MOUNTED);
|
||||||
Ext2InsertVcb(Vcb);
|
Ext2InsertVcb(Vcb);
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <linux/ext2_fs.h>
|
|
||||||
#include <linux/ext3_fs.h>
|
|
||||||
#include <linux/ext3_fs_i.h>
|
|
||||||
#include <linux/ext4.h>
|
#include <linux/ext4.h>
|
||||||
|
|
||||||
/* DEBUG ****************************************************************/
|
/* DEBUG ****************************************************************/
|
||||||
@@ -2021,10 +2018,10 @@ loff_t ext3_max_size(int blkbits, int has_huge_files);
|
|||||||
loff_t ext3_max_bitmap_size(int bits, int has_huge_files);
|
loff_t ext3_max_bitmap_size(int bits, int has_huge_files);
|
||||||
|
|
||||||
|
|
||||||
__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
|
/*__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
|
||||||
struct ext4_group_desc *gdp);
|
struct ext4_group_desc *gdp);
|
||||||
int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
|
int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
|
||||||
struct ext4_group_desc *gdp);
|
struct ext4_group_desc *gdp);*/
|
||||||
|
|
||||||
ext3_fsblk_t descriptor_loc(struct super_block *sb,
|
ext3_fsblk_t descriptor_loc(struct super_block *sb,
|
||||||
ext3_fsblk_t logical_sb_block, unsigned int nr);
|
ext3_fsblk_t logical_sb_block, unsigned int nr);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/jbd.h>
|
#include <linux/jbd.h>
|
||||||
#include <linux/ext3_fs.h>
|
|
||||||
|
|
||||||
#define EXT3_JOURNAL(inode) (EXT3_SB((inode)->i_sb)->s_journal)
|
#define EXT3_JOURNAL(inode) (EXT3_SB((inode)->i_sb)->s_journal)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -86,7 +86,7 @@ struct ext4_xattr_entry {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE
|
//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE
|
||||||
|
|
||||||
#define EXT4_XATTR_PAD_BITS 2
|
#define EXT4_XATTR_PAD_BITS 2
|
||||||
#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
|
#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
|
||||||
|
|||||||
@@ -2547,6 +2547,9 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
|||||||
Vcb->sbi.s_blocks_per_group = sb->s_blocks_per_group;
|
Vcb->sbi.s_blocks_per_group = sb->s_blocks_per_group;
|
||||||
Vcb->sbi.s_first_ino = sb->s_first_ino;
|
Vcb->sbi.s_first_ino = sb->s_first_ino;
|
||||||
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_inode_size = sb->s_inode_size;
|
||||||
|
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 ||
|
||||||
@@ -2620,6 +2623,15 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mount ext4 with 64-bit block numbers read-only while testing.
|
||||||
|
*/
|
||||||
|
if (EXT3_HAS_INCOMPAT_FEATURE(&Vcb->sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
|
||||||
|
printk(KERN_ERR "EXT3-fs: %s: Mounting ext4 with 64-bit block numbers read-only.\n",
|
||||||
|
Vcb->sb.s_id);
|
||||||
|
SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
has_huge_files = EXT3_HAS_RO_COMPAT_FEATURE(&Vcb->sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
|
has_huge_files = EXT3_HAS_RO_COMPAT_FEATURE(&Vcb->sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
|
||||||
|
|
||||||
Vcb->sb.s_maxbytes = ext3_max_size(BLOCK_BITS, has_huge_files);
|
Vcb->sb.s_maxbytes = ext3_max_size(BLOCK_BITS, has_huge_files);
|
||||||
|
|||||||
Reference in New Issue
Block a user