[PATCH] 1/1: Implement asr_write to write RAID metadata

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux RAID]     [Linux Device Mapper]     [Linux IDE]     [Linux SCSI]     [Kernel]     [Linux Books]     [Linux Admin]     [GFS]     [RPM]     [Yosemite Campgrounds]     [AMD 64]

  Powered by Linux