python3 -c "
import struct

CHUNK = 128*512
LV_START = 5120000*512
BSIZE = 4096
GDT_ENTRY = 64
BPG = 32768

def raw_read(virt_offset, length):
    result = bytearray(length)
    pos = virt_offset
    remaining = length
    with open('/dev/md0','rb') as f:
        while remaining > 0:
            group     = pos // (5*CHUNK)
            in_group  = pos % (5*CHUNK)
            chunk_idx = in_group // CHUNK
            intra     = in_group % CHUNK
            seg_len   = min(CHUNK-intra, remaining)
            dst_off   = pos - virt_offset
            if chunk_idx != 4:
                phys = LV_START + group*4*CHUNK + chunk_idx*CHUNK + intra
                f.seek(phys)
                data = f.read(seg_len)
                result[dst_off:dst_off+len(data)] = data
            pos += seg_len
            remaining -= seg_len
    return bytes(result)

# Read primary GDT (at block 1 = byte 4096)
# and backup GDT (at block group 1 start + 1 block)
# Group 1 starts at block 32768, GDT backup at block 32769 = byte 32769*4096

# Read 1000 entries from primary GDT
primary_gdt = bytearray(raw_read(BSIZE, 1000 * GDT_ENTRY))

# Read 1000 entries from backup GDT at group 1
backup_start = (BPG + 1) * BSIZE  # block 32769
backup_gdt = raw_read(backup_start, 1000 * GDT_ENTRY)

print('Comparing primary vs backup GDT entries:')
mismatches = 0
zeros = 0
for i in range(1000):
    p = primary_gdt[i*GDT_ENTRY:(i+1)*GDT_ENTRY]
    b = backup_gdt[i*GDT_ENTRY:(i+1)*GDT_ENTRY]
    p_bb = struct.unpack_from('<I',p,0)[0]
    b_bb = struct.unpack_from('<I',b,0)[0]
    if p == bytes(GDT_ENTRY):
        zeros += 1
    elif p != b:
        mismatches += 1
        if mismatches <= 5:
            print(f'  Group {i}: primary bb={p_bb} vs backup bb={b_bb}')

print(f'Zero entries in primary: {zeros}/1000')
print(f'Mismatches: {mismatches}/1000')
print(f'Backup GDT group 0: bb={struct.unpack_from(\"<I\",backup_gdt,0)[0]}')
"
