[PATCH] 1/1: Implement asr_write to write RAID metadata
"Darrick J. Wong" <[email protected]>
| Newsgroups | gmane.linux.ataraid |
|---|---|
| Organization | IBM LTC |
| Message-ID | <[email protected]> |
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 <[email protected]> _______________________________________________ Ataraid-list mailing list [email protected] https://www.redhat.com/mailman/listinfo/ataraid-list
asr-write_1.patch
(text/x-patch, 12.7 KB)
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 */
signature.asc
(application/pgp-signature, 191 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.2 (GNU/Linux) iD8DBQFEZQ3Ba6vRYYgWQuURAjiSAJ46ZR087Joc00gRezH0BdqG+SsVSQCeL/Zi TTkMU/ubb/75LTG9j865XeE= =uUwG -----END PGP SIGNATURE-----