[Ocfs2-tools-devel] [PATCH 11/11] fsck.ocfs2: Add readahead in Pass 2

Sunil Mushran sunil.mushran at oracle.com
Fri Sep 30 12:22:21 PDT 2011


This patch adds code to readahead directory blocks in pass 2. It reads upto
1024 blocks. Those blocks are then verified after which the utility reads
another 1024 blocks. And so on. This scheme prevents blowing up the cache.

What this does not as yet is pre-read the directory index blocks and the
inodes specified in the directory block. That is left for a later exercise.

The test was run on a 2TB volume having 15M files. The cache size was 820MB.

Pass 2: Checking directory entries

Before:
  I/O read disk/cache: 3897MB / 131MB, write: 0MB, rate: 2.84MB/s
  Times real: 1416.929s, user: 124.587s, sys: 17.412s

After:
  I/O read disk/cache: 3902MB / 3937MB, write: 0MB, rate: 25.82MB/s
  Times real: 303.600s, user: 95.781s, sys: 13.443s

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 fsck.ocfs2/dirblocks.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/fsck.ocfs2/dirblocks.c b/fsck.ocfs2/dirblocks.c
index 67b0eb5..af0b5ce 100644
--- a/fsck.ocfs2/dirblocks.c
+++ b/fsck.ocfs2/dirblocks.c
@@ -36,6 +36,52 @@
 #include "util.h"
 #include "extent.h"
 
+#define NUM_RA_BLOCKS		1024
+static void o2fsck_readahead_dirblocks(o2fsck_state *ost, struct rb_node *node,
+				       struct rb_node **last_read_node)
+{
+	ocfs2_filesys *fs = ost->ost_fs;
+	o2fsck_dirblock_entry *dbe;
+	struct io_vec_unit *ivus = NULL;
+	char *buf = NULL;
+	int buflen =  NUM_RA_BLOCKS * fs->fs_blocksize;
+	uint32_t offset = 0;
+	int i;
+	errcode_t ret;
+
+	*last_read_node = NULL;
+
+	if (!fs->fs_io)
+		return;
+
+	if (buflen > io_get_cache_size(fs->fs_io))
+		return;
+
+	ret = ocfs2_malloc_blocks(fs->fs_io, NUM_RA_BLOCKS, &buf);
+	if (ret)
+		goto out;
+	 memset(buf, 0, buflen);
+
+	ret = ocfs2_malloc(sizeof(struct io_vec_unit) * NUM_RA_BLOCKS, &ivus);
+	if (ret)
+		goto out;
+
+	for (i = 0; node && (i < NUM_RA_BLOCKS); ++i, node = rb_next(node)) {
+		dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+		ivus[i].ivu_blkno = dbe->e_blkno;
+		ivus[i].ivu_buf = buf + offset;
+		ivus[i].ivu_buflen = fs->fs_blocksize;
+		offset += fs->fs_blocksize;
+		*last_read_node = node;
+	}
+
+	ret = io_vec_read_blocks(fs->fs_io, ivus, i);
+
+out:
+	ocfs2_free(&ivus);
+	ocfs2_free(&buf);
+}
+
 errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
 			       uint64_t blkno, uint64_t blkcount)
 {
@@ -143,16 +189,22 @@ void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
 {
 	o2fsck_dirblocks *db = &ost->ost_dirblocks;
 	o2fsck_dirblock_entry *dbe;
-	struct rb_node *node;
+	struct rb_node *node, *last_read_node = NULL;
 	unsigned ret;
+	int readahead = 1;
 
 	for (node = rb_first(&db->db_root); node; node = rb_next(node)) {
 		dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+		if (readahead)
+			o2fsck_readahead_dirblocks(ost, node, &last_read_node);
+		readahead = 0;
 		ret = func(dbe, priv_data);
 		if (ret & OCFS2_DIRENT_ABORT)
 			break;
 		if (ost->ost_prog)
 			tools_progress_step(ost->ost_prog, 1);
+		if (last_read_node == node)
+			readahead = 1;
 	}
 }
 
-- 
1.7.4.1




More information about the Ocfs2-tools-devel mailing list