[Ocfs2-tools-devel] [PATCH 08/11] libocfs2: Read the chain allocator efficiently

Sunil Mushran sunil.mushran at oracle.com
Thu Sep 22 19:04:36 PDT 2011


As the chain allocators are not linked in an ascending block number order,
reading it is a very seeky affair. This is a huge performance bottleneck in
various tools that have to load the allocators.

This patch adds public function ocfs2_cache_chain_allocator_blocks() in libocfs2
to read the chained groups efficiently and warm the cache with the blocks.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 include/ocfs2/ocfs2.h |    2 +
 libocfs2/chain.c      |   86 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index c44b764..7f08d15 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -680,6 +680,8 @@ uint64_t ocfs2_get_block_from_group(ocfs2_filesys *fs,
 				    struct ocfs2_group_desc *grp,
 				    int bpc, int bit_offset);
 
+errcode_t ocfs2_cache_chain_allocator_blocks(ocfs2_filesys *fs,
+					     struct ocfs2_dinode *di);
 errcode_t ocfs2_chain_iterate(ocfs2_filesys *fs,
 			      uint64_t blkno,
 			      int (*func)(ocfs2_filesys *fs,
diff --git a/libocfs2/chain.c b/libocfs2/chain.c
index f412fa1..801f0c1 100644
--- a/libocfs2/chain.c
+++ b/libocfs2/chain.c
@@ -303,6 +303,92 @@ uint64_t ocfs2_get_block_from_group(ocfs2_filesys *fs,
 		ocfs2_clusters_to_blocks(fs, rec->e_cpos));
 }
 
+errcode_t ocfs2_cache_chain_allocator_blocks(ocfs2_filesys *fs,
+					     struct ocfs2_dinode *di)
+{
+	struct io_aio_unit *aios = NULL;
+	char *buf = NULL;
+	errcode_t ret = 0;
+	int i, j, count;
+	struct ocfs2_chain_list *cl;
+	struct ocfs2_chain_rec *cr;
+	struct ocfs2_group_desc *gd;
+	io_channel *channel = fs->fs_io;
+	int blocksize = fs->fs_blocksize;
+	int64_t group_size;
+
+	if (!(di->i_flags & OCFS2_CHAIN_FL)) {
+		ret = OCFS2_ET_INODE_NOT_VALID;
+		goto out;
+	}
+
+	if (!channel)
+		goto out;
+
+	if (!di->i_clusters)
+		goto out;
+
+	group_size = (int64_t)di->i_clusters / di->id2.i_chain.cl_cpg;
+	group_size *= blocksize;
+
+	if (group_size > io_get_cache_size(channel))
+		goto out;
+
+	cl = &(di->id2.i_chain);
+	count = cl->cl_next_free_rec;
+
+	ret = ocfs2_malloc_blocks(channel, count, &buf);
+	if (ret)
+		goto out;
+	memset(buf, 0, count * blocksize);
+
+	ret = ocfs2_malloc(sizeof(struct io_aio_unit) * count, &aios);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < count; ++i) {
+		cr = &(cl->cl_recs[i]);
+		aios[i].aio_blkno = cr->c_blkno;
+		aios[i].aio_buf = buf + (i * blocksize);
+	}
+
+	while (count) {
+		ret = io_aio_read_blocks(channel, aios, count);
+		if (ret)
+			goto out;
+
+		for (i = 0, j = 0; i < count; ++i) {
+			gd = (struct ocfs2_group_desc *)aios[i].aio_buf;
+
+			ret = ocfs2_validate_meta_ecc(fs, aios[i].aio_buf,
+						      &gd->bg_check);
+			if (ret)
+				goto out;
+
+			if (memcmp(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
+				   strlen(OCFS2_GROUP_DESC_SIGNATURE))) {
+				ret = OCFS2_ET_BAD_GROUP_DESC_MAGIC;
+				goto out;
+			}
+			ocfs2_swap_group_desc_to_cpu(fs, gd);
+
+			if ((gd->bg_next_group > OCFS2_SUPER_BLOCK_BLKNO) &&
+			    (gd->bg_next_group < fs->fs_blocks)) {
+				aios[j].aio_blkno = gd->bg_next_group;
+				memset(aios[j].aio_buf, 0, blocksize);
+				j++;
+			}
+		}
+
+		count = j;
+	}
+
+out:
+	ocfs2_free(&aios);
+	ocfs2_free(&buf);
+	return ret;
+}
+
 #ifdef DEBUG_EXE
 #include <stdlib.h>
 #include <getopt.h>
-- 
1.7.4.1




More information about the Ocfs2-tools-devel mailing list