Commit | Line | Data |
---|---|---|
96422adb TM |
1 | /* MDRAID Superblock generator |
2 | This should create valid mdraid superblock for raid1 with 1 device. | |
3 | It is still work in progress, but following seems to be recognized: | |
4 | ||
5 | make mdraid | |
6 | ./mdraid > test.img | |
7 | mdadm --examine test.img | |
8 | ||
30d358cd TM |
9 | losetup /dev/loop1 test.img |
10 | mdadm --assemble md /dev/loop1 | |
11 | ||
ddf3a797 TM |
12 | Some docs: |
13 | https://raid.wiki.kernel.org/index.php/RAID_superblock_formats#Sub-versions_of_the_version-1_superblock | |
14 | https://docs.huihoo.com/doxygen/linux/kernel/3.7/md__p_8h_source.html | |
15 | ||
96422adb TM |
16 | */ |
17 | ||
18 | //#include <cstddef> | |
19 | #include <string.h> | |
20 | #include <time.h> | |
21 | #include <stdlib.h> | |
22 | #include <stdio.h> | |
23 | #include <linux/raid/md_p.h> | |
24 | ||
25 | void random_uuid(__u8 *buf) | |
26 | { | |
27 | __u32 r[4]; | |
28 | for (int i = 0; i < 4; i++) | |
29 | r[i] = random(); | |
30 | memcpy(buf, r, 16); | |
31 | } | |
32 | ||
33 | static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) | |
34 | { | |
35 | unsigned int disk_csum, csum; | |
36 | unsigned long long newcsum; | |
37 | int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; | |
38 | unsigned int *isuper = (unsigned int*)sb; | |
39 | ||
40 | /* make sure I can count... (needs include cstddef) */ | |
41 | /* | |
42 | if (offsetof(struct mdp_superblock_1,data_offset) != 128 || | |
43 | offsetof(struct mdp_superblock_1, utime) != 192 || | |
44 | sizeof(struct mdp_superblock_1) != 256) { | |
45 | fprintf(stderr, "WARNING - superblock isn't sized correctly\n"); | |
46 | } | |
47 | */ | |
48 | ||
49 | disk_csum = sb->sb_csum; | |
50 | sb->sb_csum = 0; | |
51 | newcsum = 0; | |
52 | for (; size>=4; size -= 4 ) { | |
53 | newcsum += __le32_to_cpu(*isuper); | |
54 | isuper++; | |
55 | } | |
56 | ||
57 | if (size == 2) | |
58 | newcsum += __le16_to_cpu(*(unsigned short*) isuper); | |
59 | ||
60 | csum = (newcsum & 0xffffffff) + (newcsum >> 32); | |
61 | sb->sb_csum = disk_csum; | |
62 | return __cpu_to_le32(csum); | |
63 | } | |
64 | ||
65 | int main() { | |
f636a245 TM |
66 | //printf("Superblock\n"); |
67 | ||
e7456ece | 68 | size_t data_size = 8192; //512B sectors (should be divisible by 8 sectors to keep 4kB alignment) |
30d358cd | 69 | |
96422adb TM |
70 | srand(time(NULL)); //FIXME: Seed UUID properly |
71 | ||
72 | struct mdp_superblock_1 sb = {0}; | |
73 | ||
74 | /* constant array information - 128 bytes */ | |
75 | sb.magic = 0xa92b4efc; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ | |
76 | sb.major_version = 1; /* 1 */ | |
f636a245 | 77 | sb.feature_map = 0; //MD_FEATURE_BITMAP_OFFSET; /* bit 0 set if 'bitmap_offset' is meaningful */ //FIXME: internal bitmap bit is not seen by mdadm???? |
96422adb TM |
78 | sb.pad0 = 0; /* always set to 0 when writing */ |
79 | ||
80 | //TODO: set these | |
81 | random_uuid(sb.set_uuid); /* user-space generated. U8[16]*/ | |
30d358cd | 82 | memcpy(sb.set_name, "localhost:7", 12); /* set and interpreted by user-space. CHAR[32] */ |
96422adb TM |
83 | sb.ctime=0; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ |
84 | ||
85 | sb.level=1; /* -4 (multipath), -1 (linear), 0,1,4,5 */ | |
30d358cd | 86 | //sb.layout=2; /* only for raid5 and raid10 currently */ |
e7456ece | 87 | sb.size=data_size; /* used size of component devices, in 512byte sectors */ |
96422adb TM |
88 | |
89 | sb.chunksize=0; /* in 512byte sectors - not used in raid 1 */ | |
90 | sb.raid_disks=1; | |
30d358cd | 91 | sb.bitmap_offset=8; /* sectors after start of superblock that bitmap starts |
96422adb TM |
92 | * NOTE: signed, so bitmap can be before superblock |
93 | * only meaningful of feature_map[0] is set. | |
94 | */ | |
95 | ||
96 | /* constant this-device information - 64 bytes */ | |
e7456ece | 97 | sb.data_offset=2048; /* sector start of data, often 0 */ |
30d358cd | 98 | sb.data_size=data_size; /* sectors in this device that can be used for data */ |
96422adb TM |
99 | sb.super_offset=8; /* sector start of this superblock */ |
100 | ||
101 | sb.dev_number=0; /* permanent identifier of this device - not role in raid */ | |
102 | sb.cnt_corrected_read=0; /* number of read errors that were corrected by re-writing */ | |
103 | random_uuid(sb.device_uuid); /* user-space setable, ignored by kernel U8[16] */ | |
104 | sb.devflags=0; /* per-device flags. Only two defined...*/ | |
105 | //#define WriteMostly1 1 /* mask for writemostly flag in above */ | |
106 | //#define FailFast1 2 /* Should avoid retries and fixups and just fail */ | |
107 | ||
f636a245 TM |
108 | /* Bad block log. If there are any bad blocks the feature flag is set. |
109 | * If offset and size are non-zero, that space is reserved and available | |
110 | */ | |
111 | sb.bblog_shift=9; /* shift from sectors to block size */ //FIXME: not sure with this! | |
112 | sb.bblog_size=8; /* number of sectors reserved for list */ | |
113 | sb.bblog_offset=16; /* sector offset from superblock to bblog, | |
114 | * signed - not unsigned */ | |
115 | ||
96422adb TM |
116 | /* array state information - 64 bytes */ |
117 | sb.utime=0; /* 40 bits second, 24 bits microseconds */ | |
118 | sb.events=0; /* incremented when superblock updated */ | |
119 | sb.resync_offset=0; /* data before this offset (from data_offset) known to be in sync */ | |
e7456ece | 120 | sb.max_dev=sb.raid_disks; /* size of devs[] array to consider */ |
96422adb TM |
121 | //__u8 pad3[64-32]; /* set to 0 when writing */ |
122 | ||
123 | /* device state information. Indexed by dev_number. | |
124 | * 2 bytes per device | |
125 | * Note there are no per-device state flags. State information is rolled | |
126 | * into the 'roles' value. If a device is spare or faulty, then it doesn't | |
127 | * have a meaningful role. | |
128 | */ | |
129 | //__le16 dev_roles[]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ | |
130 | ||
131 | ||
f636a245 | 132 | //Calculate checksum |
96422adb TM |
133 | sb.sb_csum=calc_sb_1_csum(&sb); |
134 | ||
e7456ece TM |
135 | //Empty space before metadata (sector 0 - 7) |
136 | for(int i=0;i<(sb.super_offset*512);i++) putc(0, stdout); | |
137 | ||
138 | //Superblock and padding (sector 8 - 2048) | |
96422adb | 139 | fwrite(&sb, sizeof(sb), 1, stdout); |
e7456ece | 140 | for(int i=0;i<(((sb.data_offset-sb.super_offset)*512)-sizeof(sb));i++) putc(0, stdout); |
30d358cd | 141 | |
e7456ece | 142 | //Data (N sectors) |
30d358cd | 143 | for(int i=0;i<(data_size*512);i++) putc(0, stdout); |
96422adb | 144 | } |