Hi again, The attached patch implements asr_write to write HostRAID metadata to disk. This required the conversion of rt in struct asr to a pointer so that the metadata would be written correctly. I also modified file_metadata_areas so that it writes metadata in one big chunk since one can only call file_metadata once, apparently. The patch should apply cleanly against 1.0.0rc11-pre1. Questions? Comments? --Darrick Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
diff -Naurp v7.asr.spare/lib/format/ataraid/asr.c v7-asr-write-cond/lib/format/ataraid/asr.c --- v7.asr.spare/lib/format/ataraid/asr.c 2006-05-12 15:16:10.000000000 -0700 +++ v7-asr-write-cond/lib/format/ataraid/asr.c 2006-05-12 15:21:51.000000000 -0700 @@ -24,6 +24,8 @@ static const char *handler = HANDLER; #define SPARE_ARRAY ".asr_spares" +static int asr_write(struct lib_context *lc, struct raid_dev *rd, int erase); + /* Map ASR disk status to dmraid status */ static enum status disk_status(struct asr_raid_configline *disk) { if (disk == NULL) @@ -56,9 +58,9 @@ static struct asr_raid_configline *get_c { unsigned int i; - for (i = 0; i < asr->rt.elmcnt; i++) { - if (asr->rt.ent[i].raidmagic == magic) - return asr->rt.ent + i; + for (i = 0; i < asr->rt->elmcnt; i++) { + if (asr->rt->ent[i].raidmagic == magic) + return asr->rt->ent + i; } return NULL; @@ -154,8 +156,9 @@ static void to_cpu(void *meta, unsigned { int i; struct asr *asr = meta; - int elmcnt = asr->rt.elmcnt; - int use_old_elmcnt = (asr->rt.ridcode == RVALID2); + int elmcnt = asr->rt->elmcnt; + + int use_old_elmcnt = (asr->rt->ridcode == RVALID2); if (cvt & ASR_BLOCK) { CVT32(asr->rb.b0idcode); @@ -171,30 +174,30 @@ static void to_cpu(void *meta, unsigned } if (cvt & ASR_TABLE) { - CVT32(asr->rt.ridcode); - CVT32(asr->rt.rversion); - CVT16(asr->rt.maxelm); - CVT16(asr->rt.elmcnt); + CVT32(asr->rt->ridcode); + CVT32(asr->rt->rversion); + CVT16(asr->rt->maxelm); + CVT16(asr->rt->elmcnt); if (!use_old_elmcnt) - elmcnt = asr->rt.elmcnt; - CVT16(asr->rt.elmsize); - CVT32(asr->rt.raidFlags); - CVT32(asr->rt.timestamp); - CVT16(asr->rt.rchksum); - CVT32(asr->rt.sparedrivemagic); - CVT32(asr->rt.raidmagic); - CVT32(asr->rt.verifyDate); - CVT32(asr->rt.recreateDate); + elmcnt = asr->rt->elmcnt; + CVT16(asr->rt->elmsize); + CVT32(asr->rt->raidFlags); + CVT32(asr->rt->timestamp); + CVT16(asr->rt->rchksum); + CVT32(asr->rt->sparedrivemagic); + CVT32(asr->rt->raidmagic); + CVT32(asr->rt->verifyDate); + CVT32(asr->rt->recreateDate); /* Convert the first seven config lines */ for (i = 0; i < (elmcnt < 7 ? elmcnt : 7); i++) - cvt_configline(asr->rt.ent + i); + cvt_configline(asr->rt->ent + i); } if (cvt & ASR_EXTTABLE) { for (i = 7; i < elmcnt; i++) { - cvt_configline(asr->rt.ent + i); + cvt_configline(asr->rt->ent + i); } } } @@ -203,17 +206,32 @@ static void to_cpu(void *meta, unsigned # define to_cpu(x, y) #endif +/* Compute the checksum of RAID metadata */ +static unsigned int compute_checksum(struct asr *asr) +{ + uint8_t *ptr; + unsigned int i, checksum; + + /* Compute checksum. */ + ptr = (uint8_t*) asr->rt->ent; + checksum = 0; + for (i = 0; i < sizeof(*asr->rt->ent) * asr->rt->elmcnt; i++) + checksum += ptr[i]; + + return checksum & 0xFFFF; +} + +/* Read extended metadata areas */ static int read_extended(struct lib_context *lc, struct dev_info *di, struct asr *asr) { - unsigned int remaining, i, checksum; + unsigned int remaining, i, chk; int j; - uint8_t *ptr; log_info(lc, "%s: reading extended data", di->path); /* Read the RAID table. */ - if (!read_file(lc, handler, di->path, &asr->rt, ASR_DISK_BLOCK_SIZE, + if (!read_file(lc, handler, di->path, asr->rt, ASR_DISK_BLOCK_SIZE, (uint64_t) asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE)) LOG_ERR(lc, 0, "%s: Could not read metadata.", handler); @@ -221,24 +239,25 @@ static int read_extended(struct lib_cont to_cpu(asr, ASR_TABLE); /* Is this ok? */ - if (asr->rt.ridcode != RVALID2) - LOG_ERR(lc, 0, "%s: Invalid magic number in RAID table.", - handler); + if (asr->rt->ridcode != RVALID2) + LOG_ERR(lc, 0, "%s: Invalid magic number in RAID table; " + "saw 0x%X, expected 0x%X.", handler, asr->rt->ridcode, + RVALID2); /* Have we a valid element count? */ - if (asr->rt.elmcnt >= asr->rt.maxelm) + if (asr->rt->elmcnt >= asr->rt->maxelm) LOG_ERR(lc, 0, "%s: Invalid RAID config table count.\n", handler); /* Is each element the right size? */ - if (asr->rt.elmsize != sizeof(struct asr_raid_configline)) + if (asr->rt->elmsize != sizeof(struct asr_raid_configline)) LOG_ERR(lc, 0, "%s: RAID config line is the wrong size.\n", handler); /* Figure out how much else we need to read. */ - if (asr->rt.elmcnt > 7) { - remaining = asr->rt.elmsize * (asr->rt.elmcnt - 7); - if (!read_file(lc, handler, di->path, asr->rt.ent + 7, + if (asr->rt->elmcnt > 7) { + remaining = asr->rt->elmsize * (asr->rt->elmcnt - 7); + if (!read_file(lc, handler, di->path, asr->rt->ent + 7, remaining, (uint64_t)(asr->rb.raidtbl + 1) * ASR_DISK_BLOCK_SIZE)) return 0; @@ -246,21 +265,14 @@ static int read_extended(struct lib_cont to_cpu(asr, ASR_EXTTABLE); } - /* Compute checksum. */ - ptr = (uint8_t*) asr->rt.ent; - checksum = 0; - for (i = 0; i < sizeof(*asr->rt.ent) * asr->rt.elmcnt; i++) - checksum += ptr[i]; - - checksum &= 0xFFFF; - - if (checksum != asr->rt.rchksum) + chk = compute_checksum(asr); + if (chk != asr->rt->rchksum) LOG_ERR(lc, 0,"%s: Invalid RAID config table checksum " "(0x%X vs. 0x%X).", - handler, checksum, asr->rt.rchksum); + handler, chk, asr->rt->rchksum); /* Process the name of each line of the config line. */ - for (i = 0; i < asr->rt.elmcnt; i++) { + for (i = 0; i < asr->rt->elmcnt; i++) { /* * Weird quirks of the name field of the config line: * @@ -283,14 +295,15 @@ static int read_extended(struct lib_cont * * This is nuts. */ - if (!asr->rt.ent[i].name) - memcpy(asr->rt.ent[i].name, asr->rt.ent[0].name, 16); + if (!asr->rt->ent[i].name) + memcpy(asr->rt->ent[i].name, asr->rt->ent[0].name, 16); /* Now truncate trailing whitespace in the name. */ for (j = 15; j >= 0; j--) { - if (asr->rt.ent[i].name[j] == ' ') - asr->rt.ent[i].name[j] = 0; + if (asr->rt->ent[i].name[j] != ' ') + break; } + asr->rt->ent[i].name[j + 1] = 0; } return 1; @@ -346,10 +359,13 @@ static void *read_metadata_areas(struct * RAID table. Everything else appears to be unused in v8. */ if (!(asr = alloc_private(lc, handler, sizeof(struct asr)))) - goto out; + goto bad0; + + if (!(asr->rt = alloc_private(lc, handler, sizeof(struct asr_raidtable)))) + goto bad1; if (!read_file(lc, handler, di->path, &asr->rb, size, asr_sboffset)) - goto bad; + goto bad2; /* * Convert metadata and read in @@ -359,19 +375,23 @@ static void *read_metadata_areas(struct /* Check Signature and read optional extended metadata. */ if (!is_asr(lc, di, asr) || !read_extended(lc, di, asr)) - goto bad; + goto bad2; /* * Now that we made sure that we have all the metadata, we exit. */ cl = this_disk(asr); if (cl->raidstate == LSU_COMPONENT_STATE_FAILED) - goto bad; + goto bad2; goto out; - bad: + bad2: + dbg_free(asr->rt); + bad1: + asr->rt = NULL; dbg_free(asr); + bad0: asr = NULL; out: @@ -386,30 +406,12 @@ static void file_metadata_areas(struct l void *meta) { struct asr *asr = meta; - - /* - * NOTE: We could probably just register the last 17 sectors - * of the drive in one big operation... - */ - - /* Register the reserved block. */ - file_metadata(lc, handler, di->path, &asr->rb, ASR_DISK_BLOCK_SIZE, - ASR_CONFIGOFFSET); - /* Register the raid table. */ - file_metadata(lc, handler, di->path, &asr->rt, ASR_DISK_BLOCK_SIZE, + /* Register the raid tables. */ + file_metadata(lc, handler, di->path, asr->rt, + ASR_DISK_BLOCK_SIZE * 17, (uint64_t)asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE); - /* - * Register the rest of the config table. We need to register - * all the space (i.e. maxelm), not just what we're using now. - */ - file_metadata(lc, handler, di->path, &asr->rt.ent[7], - (asr->rt.maxelm-7) * - sizeof(struct asr_raid_configline), - (uint64_t)(asr->rb.raidtbl+1) * - ASR_DISK_BLOCK_SIZE); - /* Record the device size if -D was specified. */ file_dev_size(lc, handler, di); } @@ -461,12 +463,12 @@ static int find_toplevel(struct lib_cont { int i, toplevel = -1; - for (i = 0; i < asr->rt.elmcnt; i++) { - if (asr->rt.ent[i].raidlevel == FWL) + for (i = 0; i < asr->rt->elmcnt; i++) { + if (asr->rt->ent[i].raidlevel == FWL) { toplevel = i; } - else if (asr->rt.ent[i].raidlevel == FWL_2) + else if (asr->rt->ent[i].raidlevel == FWL_2) { toplevel = i; break; @@ -485,13 +487,13 @@ static struct asr_raid_configline *find_ int i, j; /* This MUST be done backwards! */ - for (i = asr->rt.elmcnt - 1; i > -1; i--) { - if (asr->rt.ent[i].raidmagic == asr->rb.drivemagic) + for (i = asr->rt->elmcnt - 1; i > -1; i--) { + if (asr->rt->ent[i].raidmagic == asr->rb.drivemagic) { for (j = i - 1; j > -1; j--) { - if (asr->rt.ent[j].raidlevel == FWL) + if (asr->rt->ent[j].raidlevel == FWL) { - return &asr->rt.ent[j]; + return &asr->rt->ent[j]; } } } @@ -521,7 +523,7 @@ static int event_io(struct lib_context * if (rd->status & s_broken) return 0; - log_err(lc, "I/O error on device %s at sector %lu.\n", + log_err(lc, "I/O error on device %s at sector %lu.", e_io->rd->di->path, e_io->sector); /* Mark the array as degraded and the disk as failed. */ @@ -589,7 +591,7 @@ static struct raid_set *asr_group(struct } /* This is a simple RAID0/1 array. Find the set. */ - if (asr->rt.ent[top_idx].raidlevel == FWL) + if (asr->rt->ent[top_idx].raidlevel == FWL) { set = find_or_alloc_raid_set(lc, name(lc, asr), FIND_TOP, rd, LC_RS(lc), NO_CREATE, NO_CREATE_ARG); @@ -609,7 +611,7 @@ static struct raid_set *asr_group(struct * parent set; create it if necessary. Then, find the top-level set * and use join_superset to attach the parent set to the top set. */ - if (asr->rt.ent[top_idx].raidlevel == FWL_2) + if (asr->rt->ent[top_idx].raidlevel == FWL_2) { /* First compute the name of the disk's direct parent. */ fwl = find_logical(asr); @@ -639,7 +641,7 @@ static struct raid_set *asr_group(struct sset->stride = stride(cl); sset->status = s_ok; - sset->type = type(&asr->rt.ent[top_idx]); + sset->type = type(&asr->rt->ent[top_idx]); return sset; } @@ -651,12 +653,39 @@ static struct raid_set *asr_group(struct /* Write metadata. */ static int asr_write(struct lib_context *lc, struct raid_dev *rd, int erase) { - int ret; + int ret, i, j; struct asr *asr = META(rd, asr); + int elmcnt = asr->rt->elmcnt; + + /* Untruncate trailing whitespace in the name. */ + for (i = 0; i < elmcnt; i++) { + for (j = 15; j >= 0; j--) { + if (asr->rt->ent[i].name[j] == 0) + break; + } + asr->rt->ent[i].name[j] = ' '; + } + + /* Compute checksum */ + asr->rt->rchksum = compute_checksum(asr); + /* Convert back to disk format */ to_disk(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); + + /* Write data */ ret = write_metadata(lc, handler, rd, -1, erase); + + /* Go back to CPU format */ to_cpu(asr, ASR_BLOCK | ASR_TABLE | ASR_EXTTABLE); + + /* Truncate trailing whitespace in the name. */ + for (i = 0; i < elmcnt; i++) { + for (j = 15; j >= 0; j--) { + if (asr->rt->ent[i].name[j] != ' ') + break; + } + asr->rt->ent[i].name[j + 1] = 0; + } return ret; } @@ -775,7 +804,7 @@ static void asr_log(struct lib_context * log_print(lc, "%s (%s):", rd->di->path, handler); dump_rb(lc, &asr->rb); - dump_rt(lc, &asr->rt); + dump_rt(lc, asr->rt); } #endif @@ -814,11 +843,11 @@ static int setup_rd(struct lib_context * LOG_ERR(lc, 0, "%s: Could not find current disk!\n", handler); - /* We need three metadata areas */ - if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 3))) + /* We need two metadata areas */ + if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 2))) return 0; - /* First area: reserved block. */ + /* First area: raid reserved block. */ ma = rd->meta_areas; ma->offset = ASR_CONFIGOFFSET >> 9; ma->size = ASR_DISK_BLOCK_SIZE; @@ -827,14 +856,8 @@ static int setup_rd(struct lib_context * /* Second area: raid table. */ ma++; ma->offset = asr->rb.raidtbl; - ma->size = ASR_DISK_BLOCK_SIZE; - ma->area = (void*) asr; - - /* Third area: raid config table. */ - ma++; - ma->offset = asr->rb.raidtbl + 1; - ma->size = 15 * ASR_DISK_BLOCK_SIZE; - ma->area = (void*) asr; + ma->size = ASR_DISK_BLOCK_SIZE * 16; + ma->area = (void*) asr->rt; /* Now set up the rest of the metadata info */ rd->di = di; diff -Naurp v7.asr.spare/lib/format/ataraid/asr.h v7-asr-write-cond/lib/format/ataraid/asr.h --- v7.asr.spare/lib/format/ataraid/asr.h 2006-01-19 02:08:10.000000000 -0800 +++ v7-asr-write-cond/lib/format/ataraid/asr.h 2006-03-03 14:56:48.000000000 -0800 @@ -378,7 +378,7 @@ struct asr_reservedblock struct asr { struct asr_reservedblock rb; - struct asr_raidtable rt; + struct asr_raidtable *rt; }; #endif /* FORMAT_HANDLER */
Attachment:
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Ataraid-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/ataraid-list