[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-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.