diff --git a/image-mdraid.c b/image-mdraid.c index fda06b1..47df60d 100644 --- a/image-mdraid.c +++ b/image-mdraid.c @@ -48,7 +48,6 @@ Some docs: static time_t mdraid_time = 0; //Array creation timestamp has to be identical across all the raid members, so we share it between invocations - /* * bitmap structures: * Taken from Linux kernel drivers/md/md-bitmap.h @@ -97,6 +96,13 @@ typedef struct bitmap_super_s { * devices. For raid10 it is the size of the array. */ +typedef struct mdraid_img_s { + struct image *img_data; + struct image *img_inherit; + struct mdp_superblock_1 *sb; + bitmap_super_t bsb; +} mdraid_img_t; + static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) { @@ -131,7 +137,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) } static int mdraid_generate(struct image *image) { - struct image *img_in = image->handler_priv; + mdraid_img_t *md = image->handler_priv; char *name = cfg_getstr(image->imagesec, "label"); __le16 max_devices = cfg_getint(image->imagesec, "devices"); @@ -148,8 +154,8 @@ static int mdraid_generate(struct image *image) { } size_t superblock_size = sizeof(struct mdp_superblock_1) + max_devices*2; - struct mdp_superblock_1 *sb = xzalloc(superblock_size); - bitmap_super_t bsb = {0}; + struct mdp_superblock_1 *sb = md->sb = xzalloc(superblock_size); + bitmap_super_t *bsb = &md->bsb; /* constant array information - 128 bytes */ sb->magic = MD_SB_MAGIC; /* MD_SB_MAGIC: 0xa92b4efc - little endian. This is actualy just char string saying "bitm" :-) */ @@ -227,25 +233,25 @@ static int mdraid_generate(struct image *image) { 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 */ - 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.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.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 */ + bsb->magic = BITMAP_MAGIC; /* 0 BITMAP_MAGIC */ + 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->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->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) { - bsb.chunksize *= 2; - bsb.sectors_reserved = roundup(bsb.sync_size / bsb.chunksize, 8); + while(bsb->sectors_reserved > BITMAP_SECTORS_MAX) { + bsb->chunksize *= 2; + bsb->sectors_reserved = roundup(bsb->sync_size / bsb->chunksize, 8); } //Construct image file @@ -257,21 +263,22 @@ static int mdraid_generate(struct image *image) { if (ret) return ret; //Write bitmap if ( sb->feature_map & MD_FEATURE_BITMAP_OFFSET ) { - ret = insert_data(image, &bsb, imageoutfile(image), sizeof(bsb), (sb->super_offset + sb->bitmap_offset) * 512); + ret = insert_data(image, bsb, imageoutfile(image), sizeof(*bsb), (sb->super_offset + sb->bitmap_offset) * 512); if (ret) return ret; } //Write data - if (img_in) { - ret = insert_image(image, img_in, img_in->size, DATA_OFFSET_BYTES, 0); + if (md->img_data) { + ret = insert_image(image, md->img_data, md->img_data->size, DATA_OFFSET_BYTES, 0); if (ret) return ret; } - free(sb); - return 0; } static int mdraid_setup(struct image *image, cfg_t *cfg) { + mdraid_img_t *md = xzalloc(sizeof(mdraid_img_t)); + image->handler_priv = md; + if (!mdraid_time) { mdraid_time = time(NULL); srandom(mdraid_time); //For UUID generation @@ -285,9 +292,10 @@ static int mdraid_setup(struct image *image, cfg_t *cfg) { } //Find data image to be put inside the array - struct image *img_in = NULL; + md->img_data = NULL; char *src = cfg_getstr(image->imagesec, "image"); if (src) { + //Add data image as dependency (so it's built first) struct partition *part; part = xzalloc(sizeof *part); part->image = src; @@ -295,14 +303,14 @@ static int mdraid_setup(struct image *image, cfg_t *cfg) { if (part->image) { image_info(image, "MDRAID using data from: %s\n", part->image); - img_in = image_get(part->image); //TODO: will this work for pre-existing images not generated by genimage??? - if (!img_in) { + md->img_data = image_get(part->image); //TODO: will this work for pre-existing images not generated by genimage??? + if (!md->img_data) { image_error(image, "MDRAID cannot get image definition: %s\n", part->image); return 8; } if (image->size == 0) - image->size = roundup(img_in->size + DATA_OFFSET_BYTES, MDRAID_ALIGN_BYTES); - if (image->size < (img_in->size + DATA_OFFSET_BYTES)) { + image->size = roundup(md->img_data->size + DATA_OFFSET_BYTES, MDRAID_ALIGN_BYTES); + if (image->size < (md->img_data->size + DATA_OFFSET_BYTES)) { image_error(image, "MDRAID image too small to fit %s\n", part->image); return 3; } @@ -310,8 +318,25 @@ static int mdraid_setup(struct image *image, cfg_t *cfg) { } else { image_info(image, "MDRAID is created without data.\n"); } - image->handler_priv = img_in; + //Inherit config from master + char *inherit = cfg_getstr(image->imagesec, "inherit"); + if (inherit) { + //Add inherit image as dependency (so it's built first) + struct partition *part; + part = xzalloc(sizeof *part); + part->image = inherit; + list_add_tail(&part->list, &image->partitions); + + md->img_inherit = image_get(part->image); + + if (md->img_inherit) { + image_error(image, "MDRAID will inherit array metadata config from: %s\n", part->image); + } else { + image_error(image, "MDRAID cannot find image config to inherit metadata from: %s\n", part->image); + return 9; + } + } //Make sure size is aligned if (image->size != roundup(image->size, MDRAID_ALIGN_BYTES)) { @@ -331,6 +356,7 @@ static cfg_opt_t mdraid_opts[] = { CFG_STR("raid-uuid", NULL, CFGF_NONE), CFG_STR("disk-uuid", NULL, CFGF_NONE), CFG_STR("image", NULL, CFGF_NONE), + CFG_STR("inherit", NULL, CFGF_NONE), CFG_END() };