From 96422adb362222c774d1aca345bb5b66bf022dd4 Mon Sep 17 00:00:00 2001 From: Tomas Mudrunka Date: Fri, 12 Jan 2024 16:00:02 +0100 Subject: [PATCH] MDRAID superblock generator --- c/mdraid-gen/mdraid.c | 119 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 c/mdraid-gen/mdraid.c diff --git a/c/mdraid-gen/mdraid.c b/c/mdraid-gen/mdraid.c new file mode 100644 index 0000000..7c946ca --- /dev/null +++ b/c/mdraid-gen/mdraid.c @@ -0,0 +1,119 @@ +/* MDRAID Superblock generator +This should create valid mdraid superblock for raid1 with 1 device. +It is still work in progress, but following seems to be recognized: + +make mdraid +./mdraid > test.img +mdadm --examine test.img + +*/ + +//#include +#include +#include +#include +#include +#include + +void random_uuid(__u8 *buf) +{ + __u32 r[4]; + for (int i = 0; i < 4; i++) + r[i] = random(); + memcpy(buf, r, 16); +} + +static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) +{ + unsigned int disk_csum, csum; + unsigned long long newcsum; + int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; + unsigned int *isuper = (unsigned int*)sb; + +/* make sure I can count... (needs include cstddef) */ +/* + if (offsetof(struct mdp_superblock_1,data_offset) != 128 || + offsetof(struct mdp_superblock_1, utime) != 192 || + sizeof(struct mdp_superblock_1) != 256) { + fprintf(stderr, "WARNING - superblock isn't sized correctly\n"); + } +*/ + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + newcsum = 0; + for (; size>=4; size -= 4 ) { + newcsum += __le32_to_cpu(*isuper); + isuper++; + } + + if (size == 2) + newcsum += __le16_to_cpu(*(unsigned short*) isuper); + + csum = (newcsum & 0xffffffff) + (newcsum >> 32); + sb->sb_csum = disk_csum; + return __cpu_to_le32(csum); +} + +int main() { + srand(time(NULL)); //FIXME: Seed UUID properly + + struct mdp_superblock_1 sb = {0}; + + /* constant array information - 128 bytes */ + sb.magic = 0xa92b4efc; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ + sb.major_version = 1; /* 1 */ + sb.feature_map = 0; /* bit 0 set if 'bitmap_offset' is meaningful */ + sb.pad0 = 0; /* always set to 0 when writing */ + + //TODO: set these + random_uuid(sb.set_uuid); /* user-space generated. U8[16]*/ + memcpy(sb.set_name, "localhost:777", 6); /* set and interpreted by user-space. CHAR[32] */ + sb.ctime=0; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ + + sb.level=1; /* -4 (multipath), -1 (linear), 0,1,4,5 */ + sb.layout=2; /* only for raid5 and raid10 currently */ + sb.size; /* used size of component devices, in 512byte sectors */ + + sb.chunksize=0; /* in 512byte sectors - not used in raid 1 */ + sb.raid_disks=1; + sb.bitmap_offset=0; /* sectors after start of superblock that bitmap starts + * NOTE: signed, so bitmap can be before superblock + * only meaningful of feature_map[0] is set. + */ + + /* constant this-device information - 64 bytes */ + sb.data_offset=4096+sizeof(sb); /* sector start of data, often 0 */ + sb.data_size; /* sectors in this device that can be used for data */ + sb.super_offset=8; /* sector start of this superblock */ + + sb.dev_number=0; /* permanent identifier of this device - not role in raid */ + sb.cnt_corrected_read=0; /* number of read errors that were corrected by re-writing */ + random_uuid(sb.device_uuid); /* user-space setable, ignored by kernel U8[16] */ + sb.devflags=0; /* per-device flags. Only two defined...*/ + //#define WriteMostly1 1 /* mask for writemostly flag in above */ + //#define FailFast1 2 /* Should avoid retries and fixups and just fail */ + + /* array state information - 64 bytes */ + sb.utime=0; /* 40 bits second, 24 bits microseconds */ + sb.events=0; /* incremented when superblock updated */ + sb.resync_offset=0; /* data before this offset (from data_offset) known to be in sync */ + sb.max_dev=1; /* size of devs[] array to consider */ + //__u8 pad3[64-32]; /* set to 0 when writing */ + + /* device state information. Indexed by dev_number. + * 2 bytes per device + * Note there are no per-device state flags. State information is rolled + * into the 'roles' value. If a device is spare or faulty, then it doesn't + * have a meaningful role. + */ + //__le16 dev_roles[]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ + + + sb.sb_csum=calc_sb_1_csum(&sb); + + //printf("Superblock\n"); + for(int i=0;i<4096;i++) putc(0, stdout); + fwrite(&sb, sizeof(sb), 1, stdout); + for(int i=0;i<40960;i++) putc(0, stdout); +} -- 2.30.2