[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