[Ocfs2-tools-devel] [PATCH 09/11] fsck.ocfs2: Move the cache utilities to util.c

Joel Becker joel.becker at oracle.com
Fri May 22 18:00:24 PDT 2009


We're going to add a few more things.  We add a cache fill gate, where a
caller can check to see if they've just filled the cache.  Right now its
only used to see if we even have a cache.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 fsck.ocfs2/fsck.c         |   88 -------------------------------------
 fsck.ocfs2/include/util.h |   12 +++++
 fsck.ocfs2/pass0.c        |   18 +++++---
 fsck.ocfs2/util.c         |  105 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 128 insertions(+), 95 deletions(-)

diff --git a/fsck.ocfs2/fsck.c b/fsck.ocfs2/fsck.c
index 925b5f7..b269e75 100644
--- a/fsck.ocfs2/fsck.c
+++ b/fsck.ocfs2/fsck.c
@@ -53,7 +53,6 @@
 #include <string.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <assert.h>
 
 #include "ocfs2/ocfs2.h"
 
@@ -643,93 +642,6 @@ bail:
 	return ret;
 }
 
-enum o2fsck_cache_hint {
-	O2FSCK_CACHE_MODE_NONE = 0,
-	O2FSCK_CACHE_MODE_JOURNAL,	/* Enough of a cache to replay a
-					   journal */
-	O2FSCK_CACHE_MODE_FULL,		/* Enough of a cache to recover the
-					   filesystem */
-};
-
-static void o2fsck_init_cache(o2fsck_state *ost, enum o2fsck_cache_hint hint)
-{
-	errcode_t ret;
-	uint64_t blocks_wanted;
-	int leave_room;
-	ocfs2_filesys *fs = ost->ost_fs;
-	int max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
-
-	switch (hint) {
-		case O2FSCK_CACHE_MODE_FULL:
-			leave_room = 1;
-			blocks_wanted = fs->fs_blocks;
-			break;
-		case O2FSCK_CACHE_MODE_JOURNAL:
-			/*
-			 * We need enough blocks for all the journal
-			 * data.  Let's guess at 256M journals.
-			 */
-			leave_room = 0;
-			blocks_wanted = ocfs2_blocks_in_bytes(fs,
-					max_slots * 1024 * 1024 * 256);
-			break;
-		case O2FSCK_CACHE_MODE_NONE:
-			return;
-		default:
-			assert(0);
-	}
-
-	verbosef("Want %"PRIu64" blocks for the I/O cache\n",
-		 blocks_wanted);
-	/*
-	 * leave_room means that we don't want our cache to be taking
-	 * all available memory.  So we try to get twice as much as we
-	 * want; if that works, we know that getting exactly as much as
-	 * we want is going to be safe.
-	 */
-	if (leave_room)
-		blocks_wanted <<= 2;
-
-	if (blocks_wanted > INT_MAX)
-		blocks_wanted = INT_MAX;
-
-	while (blocks_wanted > 0) {
-		io_destroy_cache(fs->fs_io);
-		verbosef("Asking for %"PRIu64" blocks of I/O cache\n",
-			 blocks_wanted);
-		ret = io_init_cache(fs->fs_io, blocks_wanted);
-		if (!ret) {
-			/*
-			 * We want to pin our cache; there's no point in
-			 * having a large cache if half of it is in swap.
-			 * However, some callers may not be privileged
-			 * enough, so once we get down to a small enough
-			 * number (512 blocks), we'll stop caring.
-			 */
-			ret = io_mlock_cache(fs->fs_io);
-			if (ret && (blocks_wanted <= 512))
-				ret = 0;
-		}
-		if (!ret) {
-			verbosef("Got %"PRIu64" blocks\n", blocks_wanted);
-			/*
-			 * We've found an allocation that works.  If
-			 * we're not leaving room, we're done.  But if
-			 * we're leaving room, we clear leave_room and go
-			 * around again.  We expect to succeed there.
-			 */
-			if (!leave_room)
-				break;
-
-			verbosef("Leaving room for other %s\n",
-				 "allocations");
-			leave_room = 0;
-		}
-
-		blocks_wanted >>= 1;
-	}
-}
-
 int main(int argc, char **argv)
 {
 	char *filename;
diff --git a/fsck.ocfs2/include/util.h b/fsck.ocfs2/include/util.h
index 98fc24a..77d36e4 100644
--- a/fsck.ocfs2/include/util.h
+++ b/fsck.ocfs2/include/util.h
@@ -37,6 +37,18 @@
 #define FSCK_CANCELED    32     /* Aborted with a signal or ^C */
 #define FSCK_LIBRARY     128    /* Shared library error */
 
+/* Managing the I/O cache */
+enum o2fsck_cache_hint {
+	O2FSCK_CACHE_MODE_NONE = 0,
+	O2FSCK_CACHE_MODE_JOURNAL,	/* Enough of a cache to replay a
+					   journal */
+	O2FSCK_CACHE_MODE_FULL,		/* Enough of a cache to recover the
+					   filesystem */
+};
+void o2fsck_init_cache(o2fsck_state *ost, enum o2fsck_cache_hint hint);
+int o2fsck_worth_caching(int blocks_to_read);
+void o2fsck_reset_blocks_cached(void);
+
 void o2fsck_write_inode(o2fsck_state *ost, uint64_t blkno,
                         struct ocfs2_dinode *di);
 void o2fsck_mark_cluster_allocated(o2fsck_state *ost, uint32_t cluster);
diff --git a/fsck.ocfs2/pass0.c b/fsck.ocfs2/pass0.c
index 8b4159b..1961aae 100644
--- a/fsck.ocfs2/pass0.c
+++ b/fsck.ocfs2/pass0.c
@@ -1086,14 +1086,18 @@ errcode_t o2fsck_pass0(o2fsck_state *ost)
 	 * us to pre-fill the I/O cache; we're already reading the group
 	 * descriptor, so slurping the whole thing shouldn't hurt.
 	 *
-	 * If this allocatoin fails, we just ignore it.  It's a cache.
+	 * If this allocation fails, we just ignore it.  It's a cache.
 	 */
-	ret = ocfs2_malloc_blocks(fs->fs_io,
-				  ocfs2_blocks_in_bytes(fs, 4 * 1024 * 1024),
-				  &pre_cache_buf);
-	if (ret)
-		verbosef("Unable to allocate group pre-cache buffer, %s\n",
-			 "ignoring");
+	o2fsck_reset_blocks_cached();
+	if (o2fsck_worth_caching(1)) {
+		ret = ocfs2_malloc_blocks(fs->fs_io,
+					  ocfs2_blocks_in_bytes(fs, 4 * 1024 * 1024),
+					  &pre_cache_buf);
+		if (ret)
+			verbosef("Unable to allocate group pre-cache "
+				 "buffer, %s\n",
+				 "ignoring");
+	}
 
 	ret = ocfs2_malloc0(max_slots * sizeof(ocfs2_cached_inode *), 
 			    &ost->ost_inode_allocs);
diff --git a/fsck.ocfs2/util.c b/fsck.ocfs2/util.c
index 86d5972..54ad322 100644
--- a/fsck.ocfs2/util.c
+++ b/fsck.ocfs2/util.c
@@ -27,6 +27,7 @@
  */
 #include <inttypes.h>
 #include <string.h>
+#include <assert.h>
 #include "ocfs2/ocfs2.h"
 
 #include "util.h"
@@ -169,3 +170,107 @@ bail:
 		ocfs2_free(&buf);
 	return ret;
 }
+
+/* Number of blocks available in the I/O cache */
+static int cache_blocks;
+/*
+ * Number of blocks we've currently cached.  This is an imperfect guess
+ * designed for pre-caching.  Code can keep slurping blocks until
+ * o2fsck_worth_caching() returns 0.
+ */
+static int blocks_cached;
+
+void o2fsck_init_cache(o2fsck_state *ost, enum o2fsck_cache_hint hint)
+{
+	errcode_t ret;
+	uint64_t blocks_wanted;
+	int leave_room;
+	ocfs2_filesys *fs = ost->ost_fs;
+	int max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
+
+	switch (hint) {
+		case O2FSCK_CACHE_MODE_FULL:
+			leave_room = 1;
+			blocks_wanted = fs->fs_blocks;
+			break;
+		case O2FSCK_CACHE_MODE_JOURNAL:
+			/*
+			 * We need enough blocks for all the journal
+			 * data.  Let's guess at 256M journals.
+			 */
+			leave_room = 0;
+			blocks_wanted = ocfs2_blocks_in_bytes(fs,
+					max_slots * 1024 * 1024 * 256);
+			break;
+		case O2FSCK_CACHE_MODE_NONE:
+			return;
+		default:
+			assert(0);
+	}
+
+	verbosef("Want %"PRIu64" blocks for the I/O cache\n",
+		 blocks_wanted);
+	/*
+	 * leave_room means that we don't want our cache to be taking
+	 * all available memory.  So we try to get twice as much as we
+	 * want; if that works, we know that getting exactly as much as
+	 * we want is going to be safe.
+	 */
+	if (leave_room)
+		blocks_wanted <<= 2;
+
+	if (blocks_wanted > INT_MAX)
+		blocks_wanted = INT_MAX;
+
+	while (blocks_wanted > 0) {
+		io_destroy_cache(fs->fs_io);
+		verbosef("Asking for %"PRIu64" blocks of I/O cache\n",
+			 blocks_wanted);
+		ret = io_init_cache(fs->fs_io, blocks_wanted);
+		if (!ret) {
+			/*
+			 * We want to pin our cache; there's no point in
+			 * having a large cache if half of it is in swap.
+			 * However, some callers may not be privileged
+			 * enough, so once we get down to a small enough
+			 * number (512 blocks), we'll stop caring.
+			 */
+			ret = io_mlock_cache(fs->fs_io);
+			if (ret && (blocks_wanted <= 512))
+				ret = 0;
+		}
+		if (!ret) {
+			verbosef("Got %"PRIu64" blocks\n", blocks_wanted);
+			/*
+			 * We've found an allocation that works.  If
+			 * we're not leaving room, we're done.  But if
+			 * we're leaving room, we clear leave_room and go
+			 * around again.  We expect to succeed there.
+			 */
+			if (!leave_room) {
+				cache_blocks = blocks_wanted;
+				break;
+			}
+
+			verbosef("Leaving room for other %s\n",
+				 "allocations");
+			leave_room = 0;
+		}
+
+		blocks_wanted >>= 1;
+	}
+}
+
+int o2fsck_worth_caching(int blocks_to_read)
+{
+	if ((blocks_to_read + blocks_cached) > cache_blocks)
+		return 0;
+
+	blocks_cached += blocks_to_read;
+	return 1;
+}
+
+void o2fsck_reset_blocks_cached(void)
+{
+	blocks_cached = 0;
+}
-- 
1.6.3




More information about the Ocfs2-tools-devel mailing list