Skip to content

Commit

Permalink
Formated code
Browse files Browse the repository at this point in the history
Signed-off-by: Tomas Mudrunka <[email protected]>
  • Loading branch information
Harvie committed Jan 10, 2025
1 parent f250915 commit 6cb934c
Showing 1 changed file with 105 additions and 97 deletions.
202 changes: 105 additions & 97 deletions image-mdraid.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ Some docs:

#include "genimage.h"

#define DATA_OFFSET_SECTORS (2048)
#define DATA_OFFSET_BYTES (DATA_OFFSET_SECTORS*512)
#define BITMAP_SECTORS_MAX 256
#define MDRAID_ALIGN_BYTES 8*512 //(should be divisible by 8 sectors to keep 4kB alignment)
#define DATA_OFFSET_SECTORS (2048)
#define DATA_OFFSET_BYTES (DATA_OFFSET_SECTORS * 512)
#define BITMAP_SECTORS_MAX 256
#define MDRAID_ALIGN_BYTES 8 * 512 //(should be divisible by 8 sectors to keep 4kB alignment)

static time_t mdraid_time = 0; //Array creation timestamp has to be identical across all the raid members, so we share it between invocations

Expand All @@ -58,28 +58,28 @@ static time_t mdraid_time = 0; //Array creation timestamp has to be identical ac

/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
BITMAP_STALE = 1, /* the bitmap file is out of date or had -EIO */
BITMAP_STALE = 1, /* the bitmap file is out of date or had -EIO */
BITMAP_WRITE_ERROR = 2, /* A write error has occurred */
BITMAP_HOSTENDIAN =15,
BITMAP_HOSTENDIAN = 15,
};

/* the superblock at the front of the bitmap file -- little endian */
typedef struct bitmap_super_s {
__le32 magic; /* 0 BITMAP_MAGIC */
__le32 version; /* 4 the bitmap major for now, could change... */
__u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */
__le64 events; /* 24 event counter for the bitmap (1)*/
__le64 events_cleared;/*32 event counter when last bit cleared (2) */
__le64 sync_size; /* 40 the size of the md device's sync range(3) */
__le32 state; /* 48 bitmap state information */
__le32 chunksize; /* 52 the bitmap chunk size in bytes */
__le32 daemon_sleep; /* 56 seconds between disk flushes */
__le32 write_behind; /* 60 number of outstanding write-behind writes */
__le32 magic; /* 0 BITMAP_MAGIC */
__le32 version; /* 4 the bitmap major for now, could change... */
__u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */
__le64 events; /* 24 event counter for the bitmap (1)*/
__le64 events_cleared; /*32 event counter when last bit cleared (2) */
__le64 sync_size; /* 40 the size of the md device's sync range(3) */
__le32 state; /* 48 bitmap state information */
__le32 chunksize; /* 52 the bitmap chunk size in bytes */
__le32 daemon_sleep; /* 56 seconds between disk flushes */
__le32 write_behind; /* 60 number of outstanding write-behind writes */
__le32 sectors_reserved; /* 64 number of 512-byte sectors that are
* reserved for the bitmap. */
__le32 nodes; /* 68 the maximum number of nodes in cluster. */
__u8 cluster_name[64]; /* 72 cluster name to which this md belongs */
__u8 pad[256 - 136]; /* set to zero */
__le32 nodes; /* 68 the maximum number of nodes in cluster. */
__u8 cluster_name[64]; /* 72 cluster name to which this md belongs */
__u8 pad[256 - 136]; /* set to zero */
} bitmap_super_t;

/* notes:
Expand All @@ -98,53 +98,54 @@ typedef struct bitmap_super_s {
#endif //BITMAP_MAGIC

//Superblock struct sanity check
ct_assert(offsetof(struct mdp_superblock_1,data_offset) == 128);
ct_assert(offsetof(struct mdp_superblock_1, data_offset) == 128);
ct_assert(offsetof(struct mdp_superblock_1, utime) == 192);
ct_assert(sizeof(struct mdp_superblock_1) == 256);

//This structure is used to store mdraid state data in handler_priv
typedef struct mdraid_img_s {
struct partition img_data_part; //Partition of data to be imported to raid
struct partition img_parent_part; //Partition of parent raid image (we can inherit config from it)
struct image *img_data; //Images for aforementioned partitions
struct image *img_parent; //Dtto
struct mdp_superblock_1 *sb; //Actual mdraid superblock that is gonna be stored on disk
bitmap_super_t bsb; //Actual bitmap superblock that is gonna be stored on disk
__le16 last_role; //This is counter used by slave devices to take roles
struct partition img_data_part; //Partition of data to be imported to raid
struct partition img_parent_part; //Partition of parent raid image (we can inherit config from it)
struct image *img_data; //Images for aforementioned partitions
struct image *img_parent; //Dtto
struct mdp_superblock_1 *sb; //Actual mdraid superblock that is gonna be stored on disk
bitmap_super_t bsb; //Actual bitmap superblock that is gonna be stored on disk
__le16 last_role; //This is counter used by slave devices to take roles
} mdraid_img_t;

static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
static unsigned int calc_sb_1_csum(struct mdp_superblock_1 *sb)
{
unsigned int disk_csum, csum;
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;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev) * 2;
unsigned int *isuper = (unsigned int *)sb;

//Temporarily set checksum in struct to 0 while remembering original value
disk_csum = sb->sb_csum;
disk_csum = sb->sb_csum;
sb->sb_csum = 0;
newcsum = 0;
for (; size>=4; size -= 4 ) {
newcsum = 0;
for (; size >= 4; size -= 4) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}

if (size == 2)
newcsum += __le16_to_cpu(*(unsigned short*) isuper);
newcsum += __le16_to_cpu(*(unsigned short *)isuper);

csum = (newcsum & 0xffffffff) + (newcsum >> 32);
csum = (newcsum & 0xffffffff) + (newcsum >> 32);
sb->sb_csum = disk_csum; //Set checksum in struct back to original value
return __cpu_to_le32(csum);
}

static int mdraid_generate(struct image *image) {
mdraid_img_t *md = image->handler_priv;
static int mdraid_generate(struct image *image)
{
mdraid_img_t *md = image->handler_priv;
mdraid_img_t *mdp = NULL; //Inheriting from this parent if not NULL
__le16 max_devices;
__le16 max_devices;

//Determine max_devices while considering possibility of inheritance from other image
if (md->img_parent) {
mdp = md->img_parent->handler_priv;
mdp = md->img_parent->handler_priv;
max_devices = mdp->sb->raid_disks;
} else {
max_devices = cfg_getint(image->imagesec, "devices");
Expand Down Expand Up @@ -172,81 +173,82 @@ static int mdraid_generate(struct image *image) {
}

//MD Superblock and Bitmap Superblock
size_t superblock_size = sizeof(struct mdp_superblock_1) + max_devices*2;
size_t superblock_size = sizeof(struct mdp_superblock_1) + max_devices * 2;
struct mdp_superblock_1 *sb = md->sb = xzalloc(superblock_size);
bitmap_super_t *bsb = &md->bsb;
bitmap_super_t *bsb = &md->bsb;

if (mdp) {
//We are inheriting the superblock in this case
memcpy(md->sb, mdp->sb, superblock_size);
memcpy(md->sb, mdp->sb, superblock_size);
//memcpy(&md->bsb, &mdp->bsb, sizeof(bitmap_super_t));
} else {
//We are not inheriting superblock, therefore we need to fully initialize the array

char *name = cfg_getstr(image->imagesec, "label");

/* constant array information - 128 bytes */
sb->magic = MD_SB_MAGIC; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
sb->major_version = 1; /* Always 1 for 1.xx metadata version :-) */
sb->feature_map = MD_FEATURE_BITMAP_OFFSET; /* bit 0 set if 'bitmap_offset' is meaningful */
sb->pad0 = 0; /* always set to 0 when writing */
sb->magic = MD_SB_MAGIC; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
sb->major_version = 1; /* Always 1 for 1.xx metadata version :-) */
sb->feature_map = MD_FEATURE_BITMAP_OFFSET; /* bit 0 set if 'bitmap_offset' is meaningful */
sb->pad0 = 0; /* always set to 0 when writing */

char *raid_uuid = cfg_getstr(image->imagesec, "raid-uuid");
if (!raid_uuid) raid_uuid = uuid_random();
uuid_parse(raid_uuid, sb->set_uuid); /* user-space generated. U8[16]*/
if (!raid_uuid)
raid_uuid = uuid_random();
uuid_parse(raid_uuid, sb->set_uuid); /* user-space generated. U8[16]*/

strncpy(sb->set_name, name, 32); sb->set_name[31] = 0; /* set and interpreted by user-space. CHAR[32] */
strncpy(sb->set_name, name, 32);
sb->set_name[31] = 0; /* set and interpreted by user-space. CHAR[32] */

long int timestamp = cfg_getint(image->imagesec, "timestamp");
if (timestamp >= 0) {
sb->ctime = timestamp & 0xffffffffff;
} else {
sb->ctime = mdraid_time & 0xffffffffff; /* lo 40 bits are seconds, top 24 are microseconds or 0*/
sb->ctime = mdraid_time & 0xffffffffff; /* lo 40 bits are seconds, top 24 are microseconds or 0*/
}

sb->level = 1; /* -4 (multipath), -1 (linear), 0,1,4,5 */
sb->level = 1; /* -4 (multipath), -1 (linear), 0,1,4,5 */
//sb->layout; /* only for raid5 and raid10 currently */
sb->size = (image->size - DATA_OFFSET_BYTES)/512; /* used size of component devices, in 512byte sectors */
sb->size = (image->size - DATA_OFFSET_BYTES) / 512; /* used size of component devices, in 512byte sectors */

sb->chunksize = 0; /* in 512byte sectors - not used in raid 1 */
sb->chunksize = 0; /* in 512byte sectors - not used in raid 1 */
sb->raid_disks = max_devices;
}


sb->bitmap_offset = 8; /* sectors after start of superblock that bitmap starts
sb->bitmap_offset = 8; /* 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 = DATA_OFFSET_SECTORS; /* sector start of data, often 0 */
sb->data_size = sb->size; /* sectors in this device that can be used for data */
sb->super_offset = 8; /* sector start of this superblock */
sb->data_offset = DATA_OFFSET_SECTORS; /* sector start of data, often 0 */
sb->data_size = sb->size; /* sectors in this device that can be used for data */
sb->super_offset = 8; /* sector start of this superblock */

sb->dev_number = role; /* permanent identifier of this device - not role in raid (They can be equal tho). */
sb->cnt_corrected_read = 0; /* number of read errors that were corrected by re-writing */
sb->dev_number = role; /* permanent identifier of this device - not role in raid (They can be equal tho). */
sb->cnt_corrected_read = 0; /* number of read errors that were corrected by re-writing */

char *disk_uuid = cfg_getstr(image->imagesec, "disk-uuid");
if (!disk_uuid) disk_uuid = uuid_random();
uuid_parse(disk_uuid, sb->device_uuid); /* user-space setable, ignored by kernel U8[16] */
if (!disk_uuid)
disk_uuid = uuid_random();
uuid_parse(disk_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 */
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 */

/* Bad block log. If there are any bad blocks the feature flag is set.
* If offset and size are non-zero, that space is reserved and available
*/
sb->bblog_shift = 9; /* shift from sectors to badblock size, typicaly 9-12 (shift by 9 is equal to 512 sectors per badblock) */
sb->bblog_size = 8; /* number of sectors reserved for list */
sb->bblog_offset = sb->bitmap_offset+BITMAP_SECTORS_MAX+8; /* sector offset from superblock to bblog, signed - not unsigned */
sb->bblog_shift = 9; /* shift from sectors to badblock size, typicaly 9-12 (shift by 9 is equal to 512 sectors per badblock) */
sb->bblog_size = 8; /* number of sectors reserved for list */
sb->bblog_offset = sb->bitmap_offset + BITMAP_SECTORS_MAX + 8; /* sector offset from superblock to bblog, signed - not unsigned */

/* array state information - 64 bytes */
sb->utime = sb->ctime; /* 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 = max_devices; /* size of devs[] array to consider */
sb->utime = sb->ctime; /* 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 = max_devices; /* size of devs[] array to consider */
//__u8 pad3[64-32]; /* set to 0 when writing */

/* device state information. Indexed by dev_number.
Expand All @@ -255,60 +257,65 @@ static int mdraid_generate(struct image *image) {
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
__le16 *dev_roles = (__le16 *) ((char *) sb + sizeof(struct mdp_superblock_1)); /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
__le16 *dev_roles = (__le16 *)((char *)sb + sizeof(struct mdp_superblock_1)); /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
//memset(dev_roles, 0xFF, max_devices*2); //All devices in array are set as inactive initialy
for(int i = 0; i<max_devices; i++) { //All devices are assigned roles equal to their dev_number initialy
dev_roles[i] = i; //Assign active role to all devices
for (int i = 0; i < max_devices; i++) { //All devices are assigned roles equal to their dev_number initialy
dev_roles[i] = i; //Assign active role to all devices
}

//Calculate superblock checksum
sb->sb_csum = calc_sb_1_csum(sb);

//Prepare bitmap superblock (bitmaps don't have checksums for performance reasons)
bsb->magic = BITMAP_MAGIC; /* 0 BITMAP_MAGIC - This is actualy just char string saying "bitm" :-) */
bsb->version = 4; /* v4 is compatible with mdraid v1.2, 4 the bitmap major for now, could change... */
memcpy(bsb->uuid, sb->set_uuid, sizeof(bsb->uuid)); /* 8 128 bit uuid - must match md device uuid */
bsb->magic = BITMAP_MAGIC; /* 0 BITMAP_MAGIC - This is actualy just char string saying "bitm" :-) */
bsb->version = 4; /* v4 is compatible with mdraid v1.2, 4 the bitmap major for now, could change... */
memcpy(bsb->uuid, sb->set_uuid, sizeof(bsb->uuid)); /* 8 128 bit uuid - must match md device uuid */
//bsb->events = 0; /* 24 event counter for the bitmap (1)*/
//bsb->events_cleared = 0;/*32 event counter when last bit cleared (2) */
bsb->sync_size = sb->data_size; /* 40 the size of the md device's sync range(3) */
bsb->sync_size = sb->data_size; /* 40 the size of the md device's sync range(3) */
//bsb->state = 0; /* 48 bitmap state information */
bsb->chunksize = 64*1024*1024; /* 52 the bitmap chunk size in bytes, 64MB is default on linux */
bsb->daemon_sleep = 5; /* 5 is considered safe default. 56 seconds between disk flushes */
bsb->chunksize = 64 * 1024 * 1024; /* 52 the bitmap chunk size in bytes, 64MB is default on linux */
bsb->daemon_sleep = 5; /* 5 is considered safe default. 56 seconds between disk flushes */
//bsb->write_behind = 0; /* 60 number of outstanding write-behind writes */
bsb->sectors_reserved = roundup(bsb->sync_size / bsb->chunksize, 8); /* 64 number of 512-byte sectors that are reserved for the bitmap. */
//bsb->nodes; /* 68 the maximum number of nodes in cluster. */
//bsb->cluster_name[64]; /* 72 cluster name to which this md belongs */
//__u8 pad[256 - 136]; /* set to zero */

//Increase bitmap chunk size till we fit in sectors max
while(bsb->sectors_reserved > BITMAP_SECTORS_MAX) {
while (bsb->sectors_reserved > BITMAP_SECTORS_MAX) {
bsb->chunksize *= 2;
bsb->sectors_reserved = roundup(bsb->sync_size / bsb->chunksize, 8);
}

//Construct image file
int ret;
ret = prepare_image(image, image->size);
if (ret) return ret;
if (ret)
return ret;
//Write superblock
ret = insert_data(image, sb, imageoutfile(image), superblock_size, sb->super_offset * 512);
if (ret) return ret;
if (ret)
return ret;
//Write bitmap
if ( sb->feature_map & MD_FEATURE_BITMAP_OFFSET ) {
if (sb->feature_map & MD_FEATURE_BITMAP_OFFSET) {
ret = insert_data(image, bsb, imageoutfile(image), sizeof(*bsb), (sb->super_offset + sb->bitmap_offset) * 512);
if (ret) return ret;
if (ret)
return ret;
}
//Write data
if (md->img_data) {
ret = insert_image(image, md->img_data, md->img_data->size, DATA_OFFSET_BYTES, 0);
if (ret) return ret;
if (ret)
return ret;
}

return 0;
}

static int mdraid_parse(struct image *image, cfg_t *cfg) {
mdraid_img_t *md = xzalloc(sizeof(mdraid_img_t));
static int mdraid_parse(struct image *image, cfg_t *cfg)
{
mdraid_img_t *md = xzalloc(sizeof(mdraid_img_t));
image->handler_priv = md;

//Common MDRAID subsystem init
Expand Down Expand Up @@ -355,7 +362,8 @@ static int mdraid_parse(struct image *image, cfg_t *cfg) {
return 0;
}

static int mdraid_setup(struct image *image, cfg_t *cfg) {
static int mdraid_setup(struct image *image, cfg_t *cfg)
{
mdraid_img_t *md = image->handler_priv;

//Find data image and its metadata if data partition exists
Expand Down Expand Up @@ -399,10 +407,10 @@ static cfg_opt_t mdraid_opts[] = {
};

struct image_handler mdraid_handler = {
.type = "mdraid",
.type = "mdraid",
.no_rootpath = cfg_true,
.parse = mdraid_parse,
.setup = mdraid_setup,
.generate = mdraid_generate,
.opts = mdraid_opts,
.parse = mdraid_parse,
.setup = mdraid_setup,
.generate = mdraid_generate,
.opts = mdraid_opts,
};

0 comments on commit 6cb934c

Please sign in to comment.