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