[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