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 | ||
96422adb TM |
12 | */ |
13 | ||
14 | //#include <cstddef> | |
15 | #include <string.h> | |
16 | #include <time.h> | |
17 | #include <stdlib.h> | |
18 | #include <stdio.h> | |
19 | #include <linux/raid/md_p.h> | |
20 | ||
21 | void random_uuid(__u8 *buf) | |
22 | { | |
23 | __u32 r[4]; | |
24 | for (int i = 0; i < 4; i++) | |
25 | r[i] = random(); | |
26 | memcpy(buf, r, 16); | |
27 | } | |
28 | ||
29 | static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) | |
30 | { | |
31 | unsigned int disk_csum, csum; | |
32 | unsigned long long newcsum; | |
33 | int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2; | |
34 | unsigned int *isuper = (unsigned int*)sb; | |
35 | ||
36 | /* make sure I can count... (needs include cstddef) */ | |
37 | /* | |
38 | if (offsetof(struct mdp_superblock_1,data_offset) != 128 || | |
39 | offsetof(struct mdp_superblock_1, utime) != 192 || | |
40 | sizeof(struct mdp_superblock_1) != 256) { | |
41 | fprintf(stderr, "WARNING - superblock isn't sized correctly\n"); | |
42 | } | |
43 | */ | |
44 | ||
45 | disk_csum = sb->sb_csum; | |
46 | sb->sb_csum = 0; | |
47 | newcsum = 0; | |
48 | for (; size>=4; size -= 4 ) { | |
49 | newcsum += __le32_to_cpu(*isuper); | |
50 | isuper++; | |
51 | } | |
52 | ||
53 | if (size == 2) | |
54 | newcsum += __le16_to_cpu(*(unsigned short*) isuper); | |
55 | ||
56 | csum = (newcsum & 0xffffffff) + (newcsum >> 32); | |
57 | sb->sb_csum = disk_csum; | |
58 | return __cpu_to_le32(csum); | |
59 | } | |
60 | ||
61 | int main() { | |
30d358cd TM |
62 | size_t data_size = 10000; //512B sectors |
63 | ||
96422adb TM |
64 | srand(time(NULL)); //FIXME: Seed UUID properly |
65 | ||
66 | struct mdp_superblock_1 sb = {0}; | |
67 | ||
68 | /* constant array information - 128 bytes */ | |
69 | sb.magic = 0xa92b4efc; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ | |
70 | sb.major_version = 1; /* 1 */ | |
71 | sb.feature_map = 0; /* bit 0 set if 'bitmap_offset' is meaningful */ | |
72 | sb.pad0 = 0; /* always set to 0 when writing */ | |
73 | ||
74 | //TODO: set these | |
75 | random_uuid(sb.set_uuid); /* user-space generated. U8[16]*/ | |
30d358cd | 76 | memcpy(sb.set_name, "localhost:7", 12); /* set and interpreted by user-space. CHAR[32] */ |
96422adb TM |
77 | sb.ctime=0; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ |
78 | ||
79 | sb.level=1; /* -4 (multipath), -1 (linear), 0,1,4,5 */ | |
30d358cd TM |
80 | //sb.layout=2; /* only for raid5 and raid10 currently */ |
81 | sb.size=data_size+128; /* used size of component devices, in 512byte sectors */ | |
96422adb TM |
82 | |
83 | sb.chunksize=0; /* in 512byte sectors - not used in raid 1 */ | |
84 | sb.raid_disks=1; | |
30d358cd | 85 | sb.bitmap_offset=8; /* sectors after start of superblock that bitmap starts |
96422adb TM |
86 | * NOTE: signed, so bitmap can be before superblock |
87 | * only meaningful of feature_map[0] is set. | |
88 | */ | |
89 | ||
90 | /* constant this-device information - 64 bytes */ | |
30d358cd TM |
91 | sb.data_offset=128; /* sector start of data, often 0 */ |
92 | sb.data_size=data_size; /* sectors in this device that can be used for data */ | |
96422adb TM |
93 | sb.super_offset=8; /* sector start of this superblock */ |
94 | ||
95 | sb.dev_number=0; /* permanent identifier of this device - not role in raid */ | |
96 | sb.cnt_corrected_read=0; /* number of read errors that were corrected by re-writing */ | |
97 | random_uuid(sb.device_uuid); /* user-space setable, ignored by kernel U8[16] */ | |
98 | sb.devflags=0; /* per-device flags. Only two defined...*/ | |
99 | //#define WriteMostly1 1 /* mask for writemostly flag in above */ | |
100 | //#define FailFast1 2 /* Should avoid retries and fixups and just fail */ | |
101 | ||
102 | /* array state information - 64 bytes */ | |
103 | sb.utime=0; /* 40 bits second, 24 bits microseconds */ | |
104 | sb.events=0; /* incremented when superblock updated */ | |
105 | sb.resync_offset=0; /* data before this offset (from data_offset) known to be in sync */ | |
106 | sb.max_dev=1; /* size of devs[] array to consider */ | |
107 | //__u8 pad3[64-32]; /* set to 0 when writing */ | |
108 | ||
109 | /* device state information. Indexed by dev_number. | |
110 | * 2 bytes per device | |
111 | * Note there are no per-device state flags. State information is rolled | |
112 | * into the 'roles' value. If a device is spare or faulty, then it doesn't | |
113 | * have a meaningful role. | |
114 | */ | |
115 | //__le16 dev_roles[]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ | |
116 | ||
117 | ||
118 | sb.sb_csum=calc_sb_1_csum(&sb); | |
119 | ||
120 | //printf("Superblock\n"); | |
30d358cd | 121 | for(int i=0;i<(8*512);i++) putc(0, stdout); |
96422adb | 122 | fwrite(&sb, sizeof(sb), 1, stdout); |
30d358cd TM |
123 | for(int i=0;i<((120*512)-sizeof(sb));i++) putc(0, stdout); |
124 | ||
125 | for(int i=0;i<(data_size*512);i++) putc(0, stdout); | |
96422adb | 126 | } |