[Ocfs2-tools-commits] taoma commits r1320 - in
branches/sparse-files/libocfs2: . include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Mar 19 22:53:15 PDT 2007
Author: taoma
Date: 2007-03-19 22:53:11 -0700 (Mon, 19 Mar 2007)
New Revision: 1320
Modified:
branches/sparse-files/libocfs2/extend_file.c
branches/sparse-files/libocfs2/extent_map.c
branches/sparse-files/libocfs2/fileio.c
branches/sparse-files/libocfs2/include/ocfs2.h
Log:
Change extent-map based block searching to find_path based.
This search mechanism is based on the commit Mark checked in ocfs2 kernel on Dec.9th, 2006.
Commit hash is c0bc8e34d4298a632612ab7dc0fa22520377dab2.
Modified: branches/sparse-files/libocfs2/extend_file.c
===================================================================
--- branches/sparse-files/libocfs2/extend_file.c 2007-03-19 05:47:26 UTC (rev 1319)
+++ branches/sparse-files/libocfs2/extend_file.c 2007-03-20 05:53:11 UTC (rev 1320)
@@ -817,6 +817,43 @@
}
/*
+ * Find the leaf block in the tree which would contain cpos. No
+ * checking of the actual leaf is done.
+ *
+ * This function doesn't handle non btree extent lists.
+ */
+int ocfs2_find_leaf(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ uint32_t cpos, char **leaf_buf)
+{
+ int ret;
+ char *buf = NULL;
+ struct ocfs2_path *path = NULL;
+ struct ocfs2_extent_list *el = &di->id2.i_list;
+
+ assert(el->l_tree_depth > 0);
+
+ path = ocfs2_new_inode_path(fs, di);
+ if (!path) {
+ ret = OCFS2_ET_NO_MEMORY;
+ goto out;
+ }
+
+ ret = ocfs2_find_path(fs, path, cpos);
+ if (ret)
+ goto out;
+
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ goto out;
+
+ memcpy(buf, path_leaf_buf(path), fs->fs_blocksize);
+ *leaf_buf = buf;
+out:
+ ocfs2_free_path(path);
+ return ret;
+}
+
+/*
* Adjust the adjacent records (left_rec, right_rec) involved in a rotation.
*
* Basically, we've moved stuff around at the bottom of the tree and
Modified: branches/sparse-files/libocfs2/extent_map.c
===================================================================
--- branches/sparse-files/libocfs2/extent_map.c 2007-03-19 05:47:26 UTC (rev 1319)
+++ branches/sparse-files/libocfs2/extent_map.c 2007-03-20 05:53:11 UTC (rev 1320)
@@ -27,11 +27,14 @@
#include <string.h>
#include <inttypes.h>
+#include <assert.h>
#include "ocfs2.h"
#include "extent_map.h"
+/* remove all the old extent map mechanism, and use ocfs2_find_path instead. */
+#if 0
struct extent_map_context {
ocfs2_cached_inode *cinode;
errcode_t errcode;
@@ -474,87 +477,97 @@
return ret;
}
+#endif
-
/*
- * Look up the record containing this cluster offset. This record is
- * part of the extent map. Do not free it. Any changes you make to
- * it will reflect in the extent map. So, if your last extent
- * is (cpos = 10, clusters = 10) and you truncate the file by 5
- * clusters, you want to do:
+ * Return the index of the extent record which contains cluster #v_cluster.
+ * -1 is returned if it was not found.
*
- * ret = ocfs2_extent_map_get_rec(em, orig_size - 5, &rec);
- * rec->e_clusters -= 5;
+ * Should work fine on interior and exterior nodes.
*/
-errcode_t ocfs2_extent_map_get_rec(ocfs2_cached_inode *cinode,
- uint32_t cpos,
- struct ocfs2_extent_rec **rec)
+static int ocfs2_search_extent_list(struct ocfs2_extent_list *el,
+ uint32_t v_cluster)
{
- errcode_t ret = OCFS2_ET_EXTENT_NOT_FOUND;
- ocfs2_extent_map *em = cinode->ci_map;
- ocfs2_extent_map_entry *ent = NULL;
+ int ret = -1;
+ int i;
+ struct ocfs2_extent_rec *rec;
+ uint32_t rec_end, rec_start;
- *rec = NULL;
+ for(i = 0; i < el->l_next_free_rec; i++) {
+ rec = &el->l_recs[i];
- if (!em)
- return OCFS2_ET_INVALID_ARGUMENT;
+ rec_start = rec->e_cpos;
+ rec_end = rec_start + rec->e_clusters;
- if (cpos >= em->em_clusters)
- return OCFS2_ET_INVALID_EXTENT_LOOKUP;
-
- ent = ocfs2_extent_map_lookup(em, cpos, 1, NULL, NULL);
-
- if (ent) {
- *rec = &ent->e_rec;
- ret = 0;
+ if (v_cluster >= rec_start && v_cluster < rec_end) {
+ ret = i;
+ break;
+ }
}
return ret;
}
-errcode_t ocfs2_extent_map_get_clusters(ocfs2_cached_inode *cinode,
- uint32_t v_cpos, int count,
- uint32_t *p_cpos,
- int *ret_count)
+static int ocfs2_get_clusters(ocfs2_cached_inode *cinode, uint32_t v_cluster,
+ uint32_t *p_cluster, uint32_t *num_clusters)
{
- errcode_t ret;
- uint32_t coff, ccount;
- ocfs2_extent_map_entry *ent = NULL;
+ int i;
+ errcode_t ret = 0;
ocfs2_filesys *fs = cinode->ci_fs;
+ struct ocfs2_dinode *di;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_extent_rec *rec;
+ char *eb_buf = NULL;
+ uint32_t coff;
- *p_cpos = ccount = 0;
+ di = cinode->ci_inode;
+ el = &di->id2.i_list;
- if (!cinode->ci_map)
- return OCFS2_ET_INVALID_ARGUMENT;
+ if (el->l_tree_depth) {
+ ret = ocfs2_find_leaf(fs, di, v_cluster, &eb_buf);
+ if (ret)
+ goto out;
- if ((v_cpos + count) > cinode->ci_map->em_clusters)
- return OCFS2_ET_INVALID_EXTENT_LOOKUP;
+ eb = (struct ocfs2_extent_block *) eb_buf;
+ el = &eb->h_list;
+ }
- ret = ocfs2_extent_map_lookup_read(cinode, v_cpos, count, &ent);
- if (ret)
- return ret;
+ i = ocfs2_search_extent_list(el, v_cluster);
+ if (i == -1) {
+ /*
+ * A hole was found. Return some canned values that
+ * callers can key on.
+ */
+ *p_cluster = 0;
+ if (num_clusters)
+ *num_clusters = 1;
+ } else {
+ rec = &el->l_recs[i];
- if (ent) {
- /* We should never find ourselves straddling an interval */
- if ((ent->e_rec.e_cpos > v_cpos) ||
- ((v_cpos + count) >
- (ent->e_rec.e_cpos + ent->e_rec.e_clusters)))
- return OCFS2_ET_INVALID_EXTENT_LOOKUP;
+ assert(v_cluster >= rec->e_cpos);
- coff = v_cpos - ent->e_rec.e_cpos;
- if (ent->e_rec.e_blkno)
- *p_cpos = ocfs2_blocks_to_clusters(fs,
- ent->e_rec.e_blkno) +
- coff;
+ if (!rec->e_blkno) {
+ fprintf(stderr, "Inode %"PRIu64" has bad extent "
+ "record (%u, %u, 0)", di->i_blkno,
+ rec->e_cpos, rec->e_clusters);
+ ret = OCFS2_ET_BAD_BLKNO;
+ goto out;
+ }
- if (ret_count)
- *ret_count = ent->e_rec.e_clusters - coff;
+ coff = v_cluster - rec->e_cpos;
- return 0;
+ *p_cluster = ocfs2_blocks_to_clusters(fs, rec->e_blkno);
+ *p_cluster = *p_cluster + coff;
+
+ if (num_clusters)
+ *num_clusters = rec->e_clusters - coff;
}
-
- return OCFS2_ET_EXTENT_NOT_FOUND;
+out:
+ if (eb_buf)
+ ocfs2_free(&eb_buf);
+ return ret;
}
errcode_t ocfs2_extent_map_get_blocks(ocfs2_cached_inode *cinode,
@@ -562,52 +575,35 @@
uint64_t *p_blkno, int *ret_count)
{
errcode_t ret;
- uint64_t boff;
- uint32_t cpos, clusters;
+ int bpc;
+ uint32_t cpos, num_clusters, p_cluster;
+ uint64_t boff = 0;
ocfs2_filesys *fs = cinode->ci_fs;
- int bpc = ocfs2_clusters_to_blocks(fs, 1);
- ocfs2_extent_map_entry *ent = NULL;
- struct ocfs2_extent_rec *rec;
- *p_blkno = 0;
-
- if (!cinode->ci_map)
- return OCFS2_ET_INVALID_ARGUMENT;
-
+ bpc = ocfs2_clusters_to_blocks(fs, 1);
cpos = ocfs2_blocks_to_clusters(fs, v_blkno);
- clusters = ocfs2_blocks_to_clusters(fs,
- (uint64_t)count + bpc - 1);
- if ((cpos + clusters) > cinode->ci_map->em_clusters)
- return OCFS2_ET_INVALID_EXTENT_LOOKUP;
- ret = ocfs2_extent_map_lookup_read(cinode, cpos, clusters, &ent);
+ ret = ocfs2_get_clusters(cinode, cpos, &p_cluster, &num_clusters);
if (ret)
- return ret;
+ goto out;
- if (ent)
- {
- rec = &ent->e_rec;
+ /*
+ * p_cluster == 0 indicates a hole.
+ */
+ if (p_cluster) {
+ boff = ocfs2_clusters_to_blocks(fs, p_cluster);
+ boff += (v_blkno & (uint64_t)(bpc - 1));
+ }
- /* We should never find ourselves straddling an interval */
- if ((rec->e_cpos > cpos) ||
- ((cpos + clusters) >
- (rec->e_cpos + rec->e_clusters)))
- return OCFS2_ET_INVALID_EXTENT_LOOKUP;
+ *p_blkno = boff;
- boff = ocfs2_clusters_to_blocks(fs, cpos - rec->e_cpos);
- boff += (v_blkno % bpc);
- if (rec->e_blkno)
- *p_blkno = rec->e_blkno + boff;
-
- if (ret_count) {
- *ret_count = ocfs2_clusters_to_blocks(fs,
- rec->e_clusters) - boff;
- }
-
- return 0;
+ if (ret_count) {
+ *ret_count = ocfs2_clusters_to_blocks(fs, num_clusters);
+ *ret_count -= v_blkno & (uint64_t)(bpc - 1);
}
- return OCFS2_ET_EXTENT_NOT_FOUND;
+out:
+ return ret;
}
errcode_t ocfs2_extent_map_init(ocfs2_filesys *fs,
@@ -647,11 +643,10 @@
if (!cinode->ci_map)
return;
- ocfs2_extent_map_drop(cinode, 0);
ocfs2_free(&cinode->ci_map);
}
-
+#if 0
static int extent_map_func(ocfs2_filesys *fs,
struct ocfs2_extent_rec *rec,
int tree_depth,
@@ -825,8 +820,8 @@
return 0;
}
+#endif
-
#ifdef DEBUG_EXE
#include <stdlib.h>
#include <getopt.h>
@@ -834,10 +829,7 @@
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)
@@ -905,65 +897,9 @@
static void print_usage(void)
{
fprintf(stderr,
- "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");
+ "Usage: extent_map -i <inode_blkno> -b <blkno>:<blocks> <filename>\n");
}
-static int walk_extents_func(ocfs2_filesys *fs,
- 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;
-
- fprintf(stdout, "EXTENTS:\n");
-
- ccount = 0;
-
- for (node = rb_first(&em->em_extents); node; node = rb_next(node)) {
- ent = rb_entry(node, ocfs2_extent_map_entry, e_node);
-
- 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);
-
- 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);
- }
- }
-
- if (op == OP_WALK)
- fprintf(stdout, "TOTAL: %"PRIu32"\n",
- cinode->ci_inode->i_clusters);
-
- return 0;
-}
-
-
extern int opterr, optind;
extern char *optarg;
@@ -983,7 +919,7 @@
initialize_ocfs_error_table();
- while ((c = getopt(argc, argv, "i:b:c:r:w")) != EOF) {
+ while ((c = getopt(argc, argv, "i:b:")) != EOF) {
switch (c) {
case 'i':
blkno = read_number(optarg);
@@ -996,15 +932,6 @@
}
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");
@@ -1020,31 +947,6 @@
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;
@@ -1082,88 +984,26 @@
blkno, filename,
cinode->ci_inode->id2.i_list.l_tree_depth);
- 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_init(fs, cinode);
- if (ret) {
- com_err(argv[0], ret,
- "while initializing extent map");
- goto out_free;
- }
+ ret = ocfs2_extent_map_init(fs, cinode);
+ 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,
- 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,
- 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);
- ret = ocfs2_extent_map_get_clusters(cinode,
- 11,
- 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,
- 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;
- }
+ ret = ocfs2_extent_map_get_blocks(cinode,
+ 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);
- walk_extents_func(fs, cinode, op);
-
out_free:
ocfs2_free_cached_inode(fs, cinode);
Modified: branches/sparse-files/libocfs2/fileio.c
===================================================================
--- branches/sparse-files/libocfs2/fileio.c 2007-03-19 05:47:26 UTC (rev 1319)
+++ branches/sparse-files/libocfs2/fileio.c 2007-03-20 05:53:11 UTC (rev 1320)
@@ -190,6 +190,31 @@
return ret;
}
+/*
+ * Search the space [start_pos, start_pos + n_clusters), and find the
+ * cluster num a hole poccesses starting from start_pos.
+ */
+static uint32_t find_cluster_hole(ocfs2_cached_inode *ci, uint32_t start_pos,
+ uint32_t n_clusters)
+{
+ errcode_t ret;
+ uint32_t cluster_hole, i;
+ uint64_t blkno = ocfs2_clusters_to_blocks(ci->ci_fs,start_pos);
+ uint32_t bpc = ci->ci_fs->fs_clustersize / ci->ci_fs->fs_blocksize;
+ uint64_t p_blkno;
+ int contig_blocks;
+
+ for (i = 0; i < n_clusters; i++, blkno += bpc) {
+ ret = ocfs2_extent_map_get_blocks(ci, blkno, 1,
+ &p_blkno, &contig_blocks);
+ if (ret || p_blkno)
+ break;
+ }
+ cluster_hole = i;
+
+ return cluster_hole;
+}
+
errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
uint64_t offset, uint32_t *wrote)
{
@@ -238,6 +263,8 @@
cluster_end = ocfs2_blocks_to_clusters(fs,
v_blkno + contig_blocks -1);
n_clusters = cluster_end - cluster_begin + 1;
+ n_clusters = find_cluster_hole(ci, cluster_begin,
+ n_clusters);
ret = ocfs2_new_clusters(fs, 1, n_clusters, &p_blkno,
&n_clusters);
if (ret)
Modified: branches/sparse-files/libocfs2/include/ocfs2.h
===================================================================
--- branches/sparse-files/libocfs2/include/ocfs2.h 2007-03-19 05:47:26 UTC (rev 1319)
+++ branches/sparse-files/libocfs2/include/ocfs2.h 2007-03-20 05:53:11 UTC (rev 1320)
@@ -295,27 +295,12 @@
errcode_t ocfs2_extent_map_init(ocfs2_filesys *fs,
ocfs2_cached_inode *cinode);
void ocfs2_extent_map_free(ocfs2_cached_inode *cinode);
-errcode_t ocfs2_extent_map_insert(ocfs2_cached_inode *cinode,
- struct ocfs2_extent_rec *rec,
- int tree_depth);
-errcode_t ocfs2_extent_map_drop(ocfs2_cached_inode *cinode,
- uint32_t new_clusters);
-errcode_t ocfs2_extent_map_trunc(ocfs2_cached_inode *cinode,
- uint32_t new_clusters);
-errcode_t ocfs2_extent_map_get_rec(ocfs2_cached_inode *cinode,
- uint32_t cpos,
- struct ocfs2_extent_rec **rec);
-errcode_t ocfs2_extent_map_get_clusters(ocfs2_cached_inode *cinode,
- uint32_t v_cpos, int count,
- uint32_t *p_cpos,
- int *ret_count);
errcode_t ocfs2_extent_map_get_blocks(ocfs2_cached_inode *cinode,
uint64_t v_blkno, int count,
uint64_t *p_blkno,
int *ret_count);
-errcode_t ocfs2_load_extent_map(ocfs2_filesys *fs,
- ocfs2_cached_inode *cinode);
-
+int ocfs2_find_leaf(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ uint32_t cpos, char **leaf_buf);
void ocfs2_swap_journal_superblock(journal_superblock_t *jsb);
errcode_t ocfs2_init_journal_superblock(ocfs2_filesys *fs, char *buf,
int buflen, uint32_t jrnl_size);
More information about the Ocfs2-tools-commits
mailing list