[Ocfs2-tools-devel] [PATCH 08/13] libocfs2: Add io_mlock_cache().
Joel Becker
joel.becker at oracle.com
Tue May 26 16:03:28 PDT 2009
An I/O cache is pretty useless if it's actually being swapped out of
RAM. The io_mlock_cache() call allows a cache user to ensure their
cache is in RAM. We don't make it a default part of io_cache_init()
because some users won't have the privileges to mlock.
Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
include/ocfs2/ocfs2.h | 1 +
libocfs2/unix_io.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index e3c62d2..3c4195c 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -248,6 +248,7 @@ errcode_t io_write_block_nocache(io_channel *channel, int64_t blkno, int count,
errcode_t io_init_cache(io_channel *channel, size_t nr_blocks);
void io_set_nocache(io_channel *channel, bool nocache);
errcode_t io_init_cache_size(io_channel *channel, size_t bytes);
+errcode_t io_mlock_cache(io_channel *channel);
void io_destroy_cache(io_channel *channel);
errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb);
diff --git a/libocfs2/unix_io.c b/libocfs2/unix_io.c
index bbc8587..ccdaf93 100644
--- a/libocfs2/unix_io.c
+++ b/libocfs2/unix_io.c
@@ -41,6 +41,7 @@
#include <sys/resource.h>
#include <sys/utsname.h>
#endif
+#include <sys/mman.h>
#include <inttypes.h>
#include "ocfs2/kernel-rbtree.h"
@@ -79,7 +80,10 @@ struct io_cache {
/* Housekeeping */
struct io_cache_block *ic_metadata_buffer;
+ unsigned long ic_metadata_buffer_len;
char *ic_data_buffer;
+ unsigned long ic_data_buffer_len;
+ int ic_locked;
};
struct _io_channel {
@@ -456,10 +460,18 @@ static errcode_t io_cache_write_block(io_channel *channel, int64_t blkno,
static void io_free_cache(struct io_cache *ic)
{
if (ic) {
- if (ic->ic_data_buffer)
+ if (ic->ic_data_buffer) {
+ if (ic->ic_locked)
+ munlock(ic->ic_data_buffer,
+ ic->ic_data_buffer_len);
ocfs2_free(&ic->ic_data_buffer);
- if (ic->ic_metadata_buffer)
+ }
+ if (ic->ic_metadata_buffer) {
+ if (ic->ic_locked)
+ munlock(ic->ic_metadata_buffer,
+ ic->ic_metadata_buffer_len);
ocfs2_free(&ic->ic_metadata_buffer);
+ }
ocfs2_free(&ic);
}
}
@@ -472,6 +484,47 @@ void io_destroy_cache(io_channel *channel)
}
}
+/*
+ * A cache is kind of pointless if it is swappable, right? Let's give
+ * applications the ability to pin the cache memory. This is a separate
+ * call from io_init_cache() because non-privileged users can't do it, and
+ * they still want to create small caches.
+ */
+errcode_t io_mlock_cache(io_channel *channel)
+{
+ int rc;
+ struct io_cache *ic = channel->io_cache;
+ long pages_wanted, avpages;
+
+ if (!ic)
+ return OCFS2_ET_INVALID_ARGUMENT;
+
+ if (ic->ic_locked)
+ return 0;
+
+ /*
+ * We're going to lock our cache pages. We don't want to
+ * request more memory than the system has, though.
+ */
+ pages_wanted = channel->io_blksize * ic->ic_nr_blocks / getpagesize();
+ avpages = sysconf(_SC_AVPHYS_PAGES);
+ if (pages_wanted > avpages)
+ return OCFS2_ET_NO_MEMORY;
+
+ rc = mlock(ic->ic_data_buffer, ic->ic_data_buffer_len);
+ if (!rc) {
+ rc = mlock(ic->ic_metadata_buffer, ic->ic_metadata_buffer_len);
+ if (rc)
+ munlock(ic->ic_data_buffer, ic->ic_data_buffer_len);
+ }
+
+ if (rc)
+ return OCFS2_ET_NO_MEMORY;
+
+ ic->ic_locked = 1;
+ return 0;
+}
+
errcode_t io_init_cache(io_channel *channel, size_t nr_blocks)
{
int i;
@@ -491,11 +544,14 @@ errcode_t io_init_cache(io_channel *channel, size_t nr_blocks)
ret = ocfs2_malloc_blocks(channel, nr_blocks, &ic->ic_data_buffer);
if (ret)
goto out;
+ ic->ic_data_buffer_len = (unsigned long)nr_blocks * channel->io_blksize;
ret = ocfs2_malloc0(sizeof(struct io_cache_block) * nr_blocks,
&ic->ic_metadata_buffer);
if (ret)
goto out;
+ ic->ic_metadata_buffer_len =
+ (unsigned long)nr_blocks * sizeof(struct io_cache_block);
icb_list = ic->ic_metadata_buffer;
dbuf = ic->ic_data_buffer;
--
1.6.3
More information about the Ocfs2-tools-devel
mailing list