81 lines
3.2 KiB
Python
81 lines
3.2 KiB
Python
CHUNK = 128*512
|
|
LV_START = 5120000*512
|
|
BSIZE = 4096
|
|
|
|
# The directory data block is at virtual block 5251104
|
|
# virt_byte = 5251104 * 4096 = 21508521984
|
|
virt_byte = 5251104 * BSIZE
|
|
|
|
group = virt_byte // (5*CHUNK)
|
|
in_group = virt_byte % (5*CHUNK)
|
|
chunk_idx = in_group // CHUNK
|
|
intra = in_group % CHUNK
|
|
|
|
print(f'Virtual byte: {virt_byte}')
|
|
print(f'Chunk group: {group}')
|
|
print(f'Chunk index: {chunk_idx}')
|
|
print(f'Intra: {intra}')
|
|
print()
|
|
|
|
# This is chunk_idx=4 - a PERC metadata chunk
|
|
# The PERC stored filesystem data here
|
|
# Physical location:
|
|
# In our translation, we skip chunk_idx=4
|
|
# But if the PERC stored data there, it's at:
|
|
# phys = LV_START + group*5*CHUNK + chunk_idx*CHUNK + intra
|
|
# (5 chunks per group including metadata chunk)
|
|
phys_with_meta = LV_START + group*5*CHUNK + chunk_idx*CHUNK + intra
|
|
print(f'Physical byte if 5-chunk groups: {phys_with_meta}')
|
|
print(f'Physical sector: {phys_with_meta//512}')
|
|
|
|
# Also try: physical = LV_START + group*4*CHUNK + ... but for chunk 4
|
|
# In our current scheme chunk 4 has no mapping
|
|
# But the data must be somewhere on disk
|
|
|
|
# The PERC presents 5 virtual chunks = 5*64KB = 320KB per group
|
|
# Of these, 4 are data and 1 is PERC metadata
|
|
# But what if it's the OPPOSITE?
|
|
# What if 4 are PERC metadata and only 1 is data? No - we verified 4/5 ratio
|
|
|
|
# What if the metadata chunk IS stored on disk but at a different offset?
|
|
# The PERC stores its own metadata in those chunk positions
|
|
# For reading filesystem data that falls there, it must use the metadata chunk
|
|
# storage differently
|
|
|
|
# Let's read what's physically at that location
|
|
# The virtual block 5251104 is in chunk group 'group' at chunk position 4
|
|
# In the physical layout (5 chunks per group):
|
|
# group X physical layout: [data0][data1][data2][data3][meta4]
|
|
# Our translation: physical chunk = group*4 + chunk_idx (skipping meta)
|
|
# So physical chunk for data chunks 0-3 = group*4 + 0,1,2,3
|
|
# And physical chunk for meta = stored AFTER the 4 data chunks = group*4+4?
|
|
# But that would mean physical layout is: data0,data1,data2,data3,meta4
|
|
# which IS 5 consecutive chunks on disk
|
|
|
|
# So the physical byte for chunk_idx=4 would be:
|
|
phys_consecutive = LV_START + group*5*CHUNK + 4*CHUNK + intra
|
|
print(f'Physical byte (consecutive 5-chunk): {phys_consecutive}')
|
|
|
|
# Read it
|
|
with open('/dev/md0','rb') as f:
|
|
f.seek(phys_consecutive)
|
|
data = f.read(512)
|
|
nonzero = sum(1 for b in data if b != 0)
|
|
print(f'Nonzero bytes: {nonzero}/512')
|
|
print(f'First 32: {data[:32].hex()}')
|
|
|
|
# Also check: maybe the metadata chunk is interleaved differently
|
|
# What if physical layout per group is: [meta0][data1][data2][data3][data4]?
|
|
# i.e. metadata chunk is FIRST, not last?
|
|
for meta_pos in range(5):
|
|
# If metadata is at position meta_pos within each group of 5 physical chunks
|
|
# Then for virtual chunk_idx=4 (the one we skip):
|
|
# virtual chunks 0,1,2,3 map to physical chunks skipping meta_pos
|
|
# virtual chunk 4 IS the metadata chunk
|
|
phys_test = LV_START + group*5*CHUNK + meta_pos*CHUNK + intra
|
|
with open('/dev/md0','rb') as f:
|
|
f.seek(phys_test)
|
|
data = f.read(64)
|
|
nonzero = sum(1 for b in data if b != 0)
|
|
print(f'meta_pos={meta_pos}: phys={phys_test} nonzero={nonzero} first8={data[:8].hex()}')
|