docs
[mirrors/Programs.git] / c / mdraid-gen / mdraid.c
CommitLineData
96422adb
TM
1/* MDRAID Superblock generator
2This should create valid mdraid superblock for raid1 with 1 device.
3It is still work in progress, but following seems to be recognized:
4
5make mdraid
6./mdraid > test.img
7mdadm --examine test.img
8
30d358cd
TM
9losetup /dev/loop1 test.img
10mdadm --assemble md /dev/loop1
11
ddf3a797
TM
12Some docs:
13https://raid.wiki.kernel.org/index.php/RAID_superblock_formats#Sub-versions_of_the_version-1_superblock
14https://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
25void 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
33static 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
65int 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}
This page took 0.316366 seconds and 4 git commands to generate.