ext2: Introduce State.Block_Size
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index ccc8b31..5f28c83 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -25,11 +25,10 @@
--------------------------------------------------------------------------
SUPERBLOCK_SIZE : constant := 1024;
- SUPERBLOCK_BLOCKS : constant := SUPERBLOCK_SIZE / BLOCK_SIZE;
-
SUPERBLOCK_MAGIC : constant := 16#ef53#;
OLD_REV : constant := 0;
DYNAMIC_REV : constant := 1;
+
FEATURE_INCOMPAT_EXTENTS : constant := 16#0040#;
FEATURE_INCOMPAT_64BIT : constant := 16#0080#;
@@ -65,6 +64,7 @@
begin
if S_Log_Block_Size <= Unsigned_32 (Log_Block_Size'Last - 10) then
State.Block_Size_Bits := Log_Block_Size (S_Log_Block_Size + 10);
+ State.Block_Size := 2 ** Log_Block_Size (S_Log_Block_Size + 10);
else
Success := False;
return;
@@ -112,9 +112,9 @@
declare
S_Desc_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 63 * 4 + 2);
begin
- if Is_Power_Of_2 (S_Desc_Size) and then
- S_Desc_Size in Unsigned_16 (Desc_Size'First) ..
- Unsigned_16 (Positive'Min (Desc_Size'Last, 2 ** State.Block_Size_Bits))
+ if Natural (S_Desc_Size) in Desc_Size and
+ Natural (S_Desc_Size) <= State.Block_Size and
+ Is_Power_Of_2 (S_Desc_Size)
then
State.Desc_Size := Desc_Size (S_Desc_Size);
else
@@ -132,24 +132,22 @@
end Mount;
procedure Read_FSBlock
- (State : in T;
- Buf : out Buffer_Type;
+ (Buf : in out Buffer_Type;
FSBlock : in FSBlock_Offset;
+ Part_Len : in Partition_Length;
Success : out Boolean)
with
- Pre =>
- Is_Mounted (State) and
- Buf'Length = 2 ** State.Block_Size_Bits
+ Pre => Buf'Length in Block_Size
is
- Block_Size : constant Blockdev_Length := 2 ** State.Block_Size_Bits;
- Max_Block_Offset : constant FSBlock_Offset :=
- FSBlock_Offset (State.Part_Len / Block_Size - 1);
+ FSBlock_64 : constant Integer_64 := Integer_64 (FSBlock);
+ Block_Size : constant Integer_64 := Integer_64 (Buf'Length);
+ Max_Block_Offset : constant Integer_64 := Integer_64 (Part_Len) / Block_Size - 1;
begin
- if FSBlock > Max_Block_Offset then
+ if FSBlock_64 > Max_Block_Offset then
Success := False;
return;
end if;
- Blockdev.Read (Buf, Blockdev_Length (FSBlock) * Block_Size, Success);
+ Blockdev.Read (Buf, Blockdev_Length (FSBlock_64 * Block_Size), Success);
end Read_FSBlock;
procedure Cache_FSBlock
@@ -162,26 +160,23 @@
Cache_End : out Max_Block_Index;
Success : out Boolean)
with
- Post => Cache_End = Cache_Start + 2 ** State.Block_Size_Bits
+ Post => Cache_End = Cache_Start + State.Block_Size - 1
is
- Block_Size : constant Natural := 2 ** State.Block_Size_Bits;
-- Limit cache usage depending on block size:
- Max_Level : constant Block_Cache_Index :=
- 2 ** (Log_Block_Size'Last - State.Block_Size_Bits) - 1;
- Cache_Level : constant Block_Cache_Index :=
- Block_Cache_Index'Min (Level, Max_Level);
+ Max_Level : constant Block_Cache_Index := Block_Size'Last / State.Block_Size - 1;
+ Cache_Level : constant Block_Cache_Index := Block_Cache_Index'Min (Level, Max_Level);
begin
- Cache_Start := Cache_Level * Block_Size;
- Cache_End := Cache_Start + Block_Size - 1;
+ Cache_Start := Cache_Level * State.Block_Size;
+ Cache_End := Cache_Start + State.Block_Size - 1;
if State.Block_Cache_Logical (Cache_Level) = Logical and
State.Block_Cache_Label (Cache_Level) = Label
then
Success := True;
else
Read_FSBlock
- (State => State,
- Buf => State.Block_Cache (Cache_Start .. Cache_End),
+ (Buf => State.Block_Cache (Cache_Start .. Cache_End),
FSBlock => Phys,
+ Part_Len => State.Part_Len,
Success => Success);
State.Block_Cache_Logical (Cache_Level) := Logical;
State.Block_Cache_Label (Cache_Level) := Label;
@@ -196,7 +191,7 @@
Cache_End : out Max_Block_Index;
Success : out Boolean)
with
- Post => Cache_End = Cache_Start + 2 ** State.Block_Size_Bits
+ Post => Cache_End = Cache_Start + State.Block_Size - 1
is
begin
Cache_FSBlock (State, Phys, Level, Cache_Label (Phys),
@@ -232,9 +227,8 @@
function I_Blocks is new Ada.Unchecked_Conversion (Inode_Extents, Inode_Blocks);
function I_Blocks (State : T) return Inode_Blocks is (I_Blocks (State.Inode.Inline));
- Block_Size : constant Natural := 2 ** State.Block_Size_Bits;
- Addr_Per_Block : constant FSBlock_Logical := FSBlock_Logical (Block_Size / 4);
- Max_Addr_Per_Block : constant FSBlock_Logical := FSBlock_Logical (2 ** Log_Block_Size'Last / 4);
+ Addr_Per_Block : constant FSBlock_Logical := FSBlock_Logical (State.Block_Size / 4);
+ Max_Addr_Per_Block : constant FSBlock_Logical := FSBlock_Logical (Block_Size'Last / 4);
type Addr_In_Block_Range is range 0 .. Max_Addr_Per_Block - 1;
procedure Indirect_Block_Lookup
@@ -379,6 +373,7 @@
Extent_Header_Magic : constant := 16#f03a#;
subtype Extent_Off is Natural range 0 .. Extent_Header_Size;
subtype Extent_Idx is Natural range 1 .. (Max_Block_Index'Last + 1) / Extent_Header_Size - 1;
+ Dynamic_Max_Index : constant Extent_Idx := State.Block_Size / Extent_Header_Size - 1;
function Extent_Byte_Offset (Idx : Extent_Idx; Off : Extent_Off) return Natural
is
@@ -469,10 +464,9 @@
with
Pre => Logical_Off <= Logical,
Post => (if Success then
+ Cache_End = Cache_Start + State.Block_Size - 1 and then
Extent_Logical (State.Block_Cache (Cache_Start .. Cache_End), Next) <= Logical)
is
- Block_Size : constant Natural := 2 ** State.Block_Size_Bits;
- Dynamic_Max_Index : constant Natural := Block_Size / Extent_Header_Size - 1;
begin
Cache_FSBlock
(State => State,
@@ -583,10 +577,8 @@
subtype Desc_In_Block_Index is Group_Index
range 0 .. Group_Index (2 ** Log_Block_Size'Last / Desc_Size'First - 1);
- Block_Size : constant Natural := 2 ** State.Block_Size_Bits;
-
- Inodes_Per_Block : constant Inode_Index := Inode_Index (Block_Size / State.Inode_Size);
- Desc_Per_Block : constant Group_Index := Group_Index (Block_Size / State.Desc_Size);
+ Inodes_Per_Block : constant Inode_Index := Inode_Index (State.Block_Size / State.Inode_Size);
+ Desc_Per_Block : constant Group_Index := Group_Index (State.Block_Size / State.Desc_Size);
------------------------
-- Group deserialization
@@ -880,10 +872,9 @@
Pos := Buf'First;
while Pos <= Buf'Last and Inode_Length (File_Pos) < State.Inode.Size loop
declare
- Block_Size : constant File_Length := 2 ** State.Block_Size_Bits;
- In_Block : constant Max_Block_Index := Natural (File_Pos mod Block_Size);
- Logical : constant FSBlock_Logical := FSBlock_Logical (File_Pos / Block_Size);
- In_Block_Space : constant Natural := Natural (Block_Size) - In_Block;
+ In_Block : constant Max_Block_Index := Natural (File_Pos) mod State.Block_Size;
+ Logical : constant FSBlock_Logical := FSBlock_Logical (File_Pos / File_Offset (State.Block_Size));
+ In_Block_Space : constant Natural := Natural (State.Block_Size) - In_Block;
In_File_Space : constant Inode_Length := State.Inode.Size - Inode_Length (File_Pos);
In_Buf_Space : constant Natural := Buf'Last - Pos + 1;
Len_Here : Natural;
diff --git a/src/filo-fs-ext2.ads b/src/filo-fs-ext2.ads
index 32b1940..ba47aef 100644
--- a/src/filo-fs-ext2.ads
+++ b/src/filo-fs-ext2.ads
@@ -45,6 +45,7 @@
-- maximum block size is 64KiB (2^16):
subtype Log_Block_Size is Positive range 10 .. 16;
+ subtype Block_Size is Natural range 2 ** Log_Block_Size'First .. 2 ** Log_Block_Size'Last;
subtype Max_Block_Index is Index_Type range 0 .. 2 ** Log_Block_Size'Last - 1;
-- Minimum ext2 block size is 1KiB (two 512B blocks)
@@ -85,7 +86,8 @@
S : State;
Part_Len : Partition_Length := 0;
First_Data_Block : FSBlock_Offset := 0;
- Block_Size_Bits : Log_Block_Size := 10;
+ Block_Size_Bits : Log_Block_Size := Log_Block_Size'First;
+ Block_Size : Ext2.Block_Size := Ext2.Block_Size'First;
Inodes_Per_Group : Inode_Index := Inode_Index'First;
Inode_Size : Ext2.Inode_Size := Ext2.Inode_Size'First;
Desc_Size : Ext2.Desc_Size := Ext2.Desc_Size'First;