[Ocfs2-tools-commits] jlbec commits r319 - trunk/libocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Oct 6 20:42:13 CDT 2004


Author: jlbec
Date: 2004-10-06 20:42:10 -0500 (Wed, 06 Oct 2004)
New Revision: 319

Modified:
   trunk/libocfs2/extent_map.c
   trunk/libocfs2/extents.c
Log:

o Do read-to-leaf lookups.



Modified: trunk/libocfs2/extent_map.c
===================================================================
--- trunk/libocfs2/extent_map.c	2004-10-07 00:44:24 UTC (rev 318)
+++ trunk/libocfs2/extent_map.c	2004-10-07 01:42:10 UTC (rev 319)
@@ -79,6 +79,159 @@
 	return ent;
 }
 
+static errcode_t ocfs2_extent_map_find_leaf(ocfs2_extent_map *em,
+					    uint32_t cpos,
+					    uint32_t clusters,
+					    ocfs2_extent_list *el)
+{
+	errcode_t ret;
+	int i;
+	char *eb_buf = NULL;
+	uint64_t blkno;
+	ocfs2_extent_block *eb;
+	ocfs2_extent_rec *rec;
+
+	if (el->l_tree_depth) {
+		ret = ocfs2_malloc_block(em->em_cinode->ci_fs->fs_io,
+					 &eb_buf);
+		if (ret)
+			return ret;
+	}
+
+	while (el->l_tree_depth)
+	{
+		blkno = 0;
+		for (i = 0; i < el->l_next_free_rec; i++) {
+			rec = &el->l_recs[i];
+
+			ret = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
+			if (rec->e_cpos >=
+			    em->em_cinode->ci_inode->i_clusters)
+				goto out_free;
+
+			if ((rec->e_cpos + rec->e_clusters) <= cpos) {
+				ret = ocfs2_extent_map_insert(em, rec,
+							      el->l_tree_depth);
+				if (ret)
+					goto out_free;
+				continue;
+			}
+			if ((cpos + clusters) <= rec->e_cpos) {
+				ret = ocfs2_extent_map_insert(em, rec,
+							      el->l_tree_depth);
+				if (ret)
+					goto out_free;
+				continue;
+			}
+			
+			/* Check to see if we're stradling */
+			ret = OCFS2_ET_INVALID_EXTENT_LOOKUP;
+			if ((rec->e_cpos > cpos) ||
+			    ((cpos + clusters) >
+			     (rec->e_cpos + rec->e_clusters)))
+				goto out_free;
+			/*
+			 * We don't insert this record because we're
+			 * about to traverse it
+			 */
+			if (blkno)
+				abort();
+			blkno = rec->e_blkno;
+		}
+
+		/*
+		 * We don't support holes, and we're still up
+		 * in the branches, so we'd better have found someone
+		 */
+		if (!blkno)
+			abort();
+
+		ret = ocfs2_read_extent_block(em->em_cinode->ci_fs,
+					      blkno, eb_buf);
+		if (ret)
+			goto out_free;
+
+		eb = (ocfs2_extent_block *)eb_buf;
+		el = &eb->h_list;
+	}
+
+	if (el->l_tree_depth)
+		abort();
+
+	for (i = 0; i < el->l_next_free_rec; i++) {
+		rec = &el->l_recs[i];
+		ret = ocfs2_extent_map_insert(em, rec,
+					      el->l_tree_depth);
+		if (ret)
+			goto out_free;
+	}
+
+	ret = 0;
+
+out_free:
+	if (eb_buf)
+		ocfs2_free(&eb_buf);
+
+	return ret;
+}
+
+/*
+ * This lookup actually will read from disk.  It has one invariant:
+ * It will never re-traverse blocks.  This means that all inserts should
+ * be new regions or more granular regions (both allowed by insert).
+ */
+static errcode_t ocfs2_extent_map_lookup_read(ocfs2_extent_map *em,
+				      uint32_t cpos,
+				      uint32_t clusters,
+				      ocfs2_extent_map_entry **ret_ent)
+{
+	errcode_t ret;
+	ocfs2_extent_map_entry *ent;
+	char *eb_buf = NULL;
+	ocfs2_cached_inode *cinode = em->em_cinode;
+	ocfs2_extent_block *eb;
+	ocfs2_extent_list *el;
+
+	ent = ocfs2_extent_map_lookup(em, cpos, clusters, NULL, NULL);
+	if (ent) {
+		if (!ent->e_tree_depth) {
+			*ret_ent = ent;
+			return 0;
+		}
+
+		ret = ocfs2_malloc_block(cinode->ci_fs->fs_io,
+					 &eb_buf);
+		if (ret)
+			return ret;
+
+		ret = ocfs2_read_extent_block(cinode->ci_fs,
+					      ent->e_rec.e_blkno,
+					      eb_buf);
+		if (ret) {
+			ocfs2_free(&eb_buf);
+			return ret;
+		}
+
+		eb = (ocfs2_extent_block *)eb_buf;
+		el = &eb->h_list;
+	} else 
+		el = &cinode->ci_inode->id2.i_list;
+
+	ret = ocfs2_extent_map_find_leaf(em, cpos, clusters, el);
+	if (eb_buf)
+		ocfs2_free(&eb_buf);
+	if (ret)
+		return ret;
+
+	ent = ocfs2_extent_map_lookup(em, cpos, clusters, NULL, NULL);
+	if (!ent || ent->e_tree_depth)
+		return OCFS2_ET_CORRUPT_EXTENT_BLOCK;
+
+	*ret_ent = ent;
+
+	return 0;
+}
+
 static errcode_t ocfs2_extent_map_insert_entry(ocfs2_extent_map *em,
 					       ocfs2_extent_map_entry *ent)
 {
@@ -216,16 +369,20 @@
 				   uint32_t cpos,
 				   ocfs2_extent_rec **rec)
 {
-	ocfs2_extent_map_entry *ent;
+	errcode_t ret;
+	ocfs2_extent_map_entry *ent = NULL;
 
 	*rec = NULL;
 
-	ent = ocfs2_extent_map_lookup(em, cpos, 1, NULL, NULL);
+	if (cpos >= em->em_cinode->ci_inode->i_clusters)
+		return OCFS2_ET_INVALID_EXTENT_LOOKUP;
+
+	ret = ocfs2_extent_map_lookup_read(em, cpos, 1, &ent);
 	
-	if (ent)
+	if (!ret)
 		*rec = &ent->e_rec;
 
-	return 0;
+	return ret;
 }
 
 errcode_t ocfs2_extent_map_get_clusters(ocfs2_extent_map *em,
@@ -233,16 +390,20 @@
 					uint32_t *p_cpos,
 					int *ret_count)
 {
+	errcode_t ret;
 	uint32_t coff, ccount;
-	ocfs2_extent_map_entry *ent;
+	ocfs2_extent_map_entry *ent = NULL;
 	ocfs2_filesys *fs = em->em_cinode->ci_fs;
 
 	*p_cpos = ccount = 0;
 
-	if ((v_cpos + count) >= em->em_cinode->ci_inode->i_clusters)
+	if ((v_cpos + count) > em->em_cinode->ci_inode->i_clusters)
 		return OCFS2_ET_INVALID_EXTENT_LOOKUP;
 
-	ent = ocfs2_extent_map_lookup(em, v_cpos, count, NULL, NULL);
+	ret = ocfs2_extent_map_lookup_read(em, v_cpos, count, &ent);
+	if (ret)
+		return ret;
+
 	if (ent) {
 		/* We should never find ourselves straddling an interval */
 		if ((ent->e_rec.e_cpos > v_cpos) ||
@@ -269,11 +430,12 @@
 				      uint64_t v_blkno, int count,
 				      uint64_t *p_blkno, int *ret_count)
 {
+	errcode_t ret;
 	uint64_t boff;
 	uint32_t cpos, clusters;
 	ocfs2_filesys *fs = em->em_cinode->ci_fs;
 	int bpc = ocfs2_clusters_to_blocks(fs, 1);
-	ocfs2_extent_map_entry *ent;
+	ocfs2_extent_map_entry *ent = NULL;
 	ocfs2_extent_rec *rec;
 
 	*p_blkno = 0;
@@ -281,10 +443,13 @@
 	cpos = ocfs2_blocks_to_clusters(fs, v_blkno);
 	clusters = ocfs2_blocks_to_clusters(fs,
 					    (uint64_t)count + bpc - 1);
-	if ((cpos + clusters) >= em->em_cinode->ci_inode->i_clusters)
+	if ((cpos + clusters) > em->em_cinode->ci_inode->i_clusters)
 		return OCFS2_ET_INVALID_EXTENT_LOOKUP;
 
-	ent = ocfs2_extent_map_lookup(em, cpos, clusters, NULL, NULL);
+	ret = ocfs2_extent_map_lookup_read(em, cpos, clusters, &ent);
+	if (ret)
+		return ret;
+
 	if (ent)
 	{
 		rec = &ent->e_rec;
@@ -379,11 +544,16 @@
 	int iret = 0;
 	struct extent_map_context *ctxt = priv_data;
 
-	ret = ocfs2_extent_map_insert(ctxt->cinode->ci_map, rec,
-				      tree_depth);
-	if (ret) {
-		ctxt->errcode = ret;
+	if (rec->e_cpos >= ctxt->cinode->ci_inode->i_clusters) {
+		ctxt->errcode = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
 		iret |= OCFS2_EXTENT_ABORT;
+	} else {
+		ret = ocfs2_extent_map_insert(ctxt->cinode->ci_map, rec,
+					      tree_depth);
+		if (ret) {
+			ctxt->errcode = ret;
+			iret |= OCFS2_EXTENT_ABORT;
+		}
 	}
 
 	return iret;
@@ -441,7 +611,16 @@
 #ifdef DEBUG_EXE
 #include <stdlib.h>
 #include <getopt.h>
+#include <limits.h>
 
+enum debug_op {
+	OP_NONE = 0,
+	OP_WALK,
+	OP_LOOKUP_CLUSTER,
+	OP_LOOKUP_BLOCK,
+	OP_LOOKUP_REC,
+};
+
 static uint64_t read_number(const char *num)
 {
 	uint64_t val;
@@ -454,19 +633,73 @@
 	return val;
 }
 
+static int read_b_numbers(const char *num, uint64_t *blkno, int *count)
+{
+	uint64_t val;
+	char *ptr;
+
+	val = strtoull(num, &ptr, 0);
+	if (!ptr)
+		return 1;
+	if (*ptr != ':')
+		return 1;
+	*blkno = val;
+
+	ptr++;
+
+	val = strtoull(ptr, &ptr, 0);
+	if (!ptr || *ptr)
+		return 1;
+	if (val > INT_MAX)
+		return 1;
+	*count = (int)val;
+
+	return 0;
+}
+
+static int read_c_numbers(const char *num, uint32_t *cpos, int *count)
+{
+	uint64_t val;
+	char *ptr;
+
+	val = strtoull(num, &ptr, 0);
+	if (!ptr)
+		return 1;
+	if (*ptr != ':')
+		return 1;
+	if (val > UINT32_MAX)
+		return 1;
+	*cpos = (uint32_t)val;
+
+	ptr++;
+
+	val = strtoull(ptr, &ptr, 0);
+	if (!ptr || *ptr)
+		return 1;
+	if (val > INT_MAX)
+		return 1;
+	*count = (int)val;
+
+	return 0;
+}
+
 static void print_usage(void)
 {
 	fprintf(stderr,
-		"Usage: extent_map -i <inode_blkno> <filename>\n");
+		"Usage: extent_map -i <inode_blkno> -w <filename>\n"
+		"       extent_map -i <inode_blkno> -b <blkno>:<blocks> <filename>\n"
+		"       extent_map -i <inode_blkno> -c <cpos>:<clusters> <filename>\n"
+		"       extent_map -i <inode_blkno> -r <cpos> <filename>\n");
 }
 
 static int walk_extents_func(ocfs2_filesys *fs,
-			     ocfs2_cached_inode *cinode)
+			     ocfs2_cached_inode *cinode, int op)
 {
 	ocfs2_extent_map *em;
 	struct rb_node *node;
 	uint32_t ccount;
 	ocfs2_extent_map_entry *ent;
+	int i;
 
 	em = cinode->ci_map;
 
@@ -477,17 +710,36 @@
 	for (node = rb_first(&em->em_extents); node; node = rb_next(node)) {
 		ent = rb_entry(node, ocfs2_extent_map_entry, e_node);
 
-		fprintf(stdout, "(%08"PRIu32", %08"PRIu32", %08"PRIu64") |"
+		if (op == OP_WALK) {
+			fprintf(stdout,
+				"(%08"PRIu32", %08"PRIu32", %08"PRIu64") |"
 				" + %08"PRIu32" = %08"PRIu32" / %08"PRIu32"\n",
-			ent->e_rec.e_cpos, ent->e_rec.e_clusters,
-			ent->e_rec.e_blkno, ccount,
-			ccount + ent->e_rec.e_clusters,
-			cinode->ci_inode->i_clusters);
+				ent->e_rec.e_cpos,
+				ent->e_rec.e_clusters,
+				ent->e_rec.e_blkno, ccount,
+				ccount + ent->e_rec.e_clusters,
+				cinode->ci_inode->i_clusters);
 
-		ccount += ent->e_rec.e_clusters;
+			ccount += ent->e_rec.e_clusters;
+		} else {
+			fprintf(stdout, "@%d: ",
+				ent->e_tree_depth);
+
+			for (i = cinode->ci_inode->id2.i_list.l_tree_depth;
+			     i > ent->e_tree_depth; i--)
+				fprintf(stdout, "  ");
+
+			fprintf(stdout,
+				"(%08"PRIu32", %08"PRIu32", %09"PRIu64")\n",
+				ent->e_rec.e_cpos,
+				ent->e_rec.e_clusters,
+				ent->e_rec.e_blkno);
+		}
 	}
 
-	fprintf(stdout, "TOTAL: %"PRIu32"\n", cinode->ci_inode->i_clusters);
+	if (op == OP_WALK)
+		fprintf(stdout, "TOTAL: %"PRIu32"\n",
+			cinode->ci_inode->i_clusters);
 
 	return 0;
 }
@@ -499,17 +751,20 @@
 int main(int argc, char *argv[])
 {
 	errcode_t ret;
-	uint64_t blkno;
-	int c;
+	uint64_t blkno, blkoff;
+	uint32_t cpos, coff;
+	int count, contig;
+	int c, op = 0;
 	char *filename;
 	ocfs2_filesys *fs;
 	ocfs2_cached_inode *cinode;
+	ocfs2_extent_rec *rec;
 
 	blkno = OCFS2_SUPER_BLOCK_BLKNO;
 
 	initialize_ocfs_error_table();
 
-	while ((c = getopt(argc, argv, "i:")) != EOF) {
+	while ((c = getopt(argc, argv, "i:b:c:r:w")) != EOF) {
 		switch (c) {
 			case 'i':
 				blkno = read_number(optarg);
@@ -522,12 +777,67 @@
 				}
 				break;
 
+			case 'w':
+				if (op) {
+					fprintf(stderr, "Cannot specify more than one operation\n");
+					print_usage();
+					return 1;
+				}
+				op = OP_WALK;
+				break;
+
+			case 'b':
+				if (op) {
+					fprintf(stderr, "Cannot specify more than one operation\n");
+					print_usage();
+					return 1;
+				}
+				if (read_b_numbers(optarg,
+						   &blkoff, &count)) {
+					fprintf(stderr, "Invalid block range: %s\n", optarg);
+					print_usage();
+					return 1;
+				}
+				op = OP_LOOKUP_BLOCK;
+				break;
+
+			case 'c':
+				if (op) {
+					fprintf(stderr, "Cannot specify more than one operation\n");
+					print_usage();
+					return 1;
+				}
+				if (read_c_numbers(optarg,
+						   &cpos, &count)) {
+					fprintf(stderr, "Invalid cluster range: %s\n", optarg);
+					print_usage();
+					return 1;
+				}
+				op = OP_LOOKUP_CLUSTER;
+				break;
+
+			case 'r':
+				if (op) {
+					fprintf(stderr, "Cannot specify more than one operation\n");
+					print_usage();
+					return 1;
+				}
+				cpos = read_number(optarg);
+				op = OP_LOOKUP_REC;
+				break;
+
 			default:
 				print_usage();
 				return 1;
 				break;
 		}
 	}
+	
+	if (!op) {
+		fprintf(stderr, "Missing operation\n");
+		print_usage();
+		return 1;
+	}
 
 	if (optind >= argc) {
 		fprintf(stderr, "Missing filename\n");
@@ -553,14 +863,75 @@
 		blkno, filename,
 		cinode->ci_inode->id2.i_list.l_tree_depth);
 
-	ret = ocfs2_load_extent_map(fs, cinode);
-	if (ret) {
-		com_err(argv[0], ret,
-			"while loading extents");
-		goto out_free;
+	if (op == OP_WALK) {
+		ret = ocfs2_load_extent_map(fs, cinode);
+		if (ret) {
+			com_err(argv[0], ret,
+				"while loading extents");
+			goto out_free;
+		}
+	} else {
+		ret = ocfs2_extent_map_new(fs, cinode, &cinode->ci_map);
+		if (ret) {
+			com_err(argv[0], ret,
+				"while initializing extent map");
+			goto out_free;
+		}
+
+		switch (op) {
+			case OP_LOOKUP_BLOCK:
+				ret = ocfs2_extent_map_get_blocks(cinode->ci_map,
+								  blkoff,
+								  count,
+								  &blkno,
+								  &contig);
+				if (ret) {
+					com_err(argv[0], ret, 
+						"looking up block range %"PRIu64":%d", blkoff, count);
+					goto out_free;
+				}
+				fprintf(stdout, "Lookup of block range %"PRIu64":%d returned %"PRIu64":%d\n",
+					blkoff, count, blkno, contig);
+				break;
+
+			case OP_LOOKUP_CLUSTER:
+				ret = ocfs2_extent_map_get_clusters(cinode->ci_map,
+								  cpos,
+								  count,
+								  &coff,
+								  &contig);
+				if (ret) {
+					com_err(argv[0], ret, 
+						"looking up cluster range %"PRIu32":%d", cpos, count);
+					goto out_free;
+				}
+				fprintf(stdout, "Lookup of cluster range %"PRIu32":%d returned %"PRIu32":%d\n",
+					cpos, count, coff, contig);
+				break;
+				
+			case OP_LOOKUP_REC:
+				ret = ocfs2_extent_map_get_rec(cinode->ci_map,
+							       cpos,
+							       &rec);
+				if (ret) {
+					com_err(argv[0], ret, 
+						"looking up cluster %"PRIu32"", cpos);
+					goto out_free;
+				}
+				fprintf(stdout, "Lookup of cluster %"PRIu32" returned (%"PRIu32", %"PRIu32", %"PRIu64")\n",
+					cpos, rec->e_cpos,
+					rec->e_clusters, rec->e_blkno);
+				break;
+
+			default:
+				ret = OCFS2_ET_INTERNAL_FAILURE;
+				com_err(argv[0], ret,
+					"Invalid op can't happen!\n");
+				goto out_free;
+		}
 	}
 
-	walk_extents_func(fs, cinode);
+	walk_extents_func(fs, cinode, op);
 
 out_free:
 	ocfs2_free_cached_inode(fs, cinode);

Modified: trunk/libocfs2/extents.c
===================================================================
--- trunk/libocfs2/extents.c	2004-10-07 00:44:24 UTC (rev 318)
+++ trunk/libocfs2/extents.c	2004-10-07 01:42:10 UTC (rev 319)
@@ -67,6 +67,10 @@
 
 	memcpy(eb_buf, blk, fs->fs_blocksize);
 
+	ret = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
+	if (eb->h_list.l_next_free_rec > eb->h_list.l_count)
+		goto out;
+
 	ret = 0;
 out:
 	ocfs2_free(&blk);



More information about the Ocfs2-tools-commits mailing list