From b8bf338dbd4047138fdf2054a44e3efae328ef5d Mon Sep 17 00:00:00 2001
From: cee1 <fykcee1@gmail.com>
Date: Fri, 18 Mar 2011 10:03:41 +0800
Subject: [PATCH] Detect page size runtime.

Some architectures support multiple machine types with diffenent
page sizes, and some machine types even support multiple
page sizes themselves.
---
 src/macro.h             |   11 +++--------
 src/readahead-collect.c |    9 ++++++++-
 src/readahead-common.c  |   11 +++++++++++
 src/readahead-common.h  |    1 +
 src/readahead-replay.c  |    8 +++++++-
 5 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/macro.h b/src/macro.h
index 996b7c2..e7a4d2c 100644
--- a/src/macro.h
+++ b/src/macro.h
@@ -27,8 +27,6 @@
 #include <sys/uio.h>
 #include <inttypes.h>
 
-#define PAGE_SIZE 4096
-
 #define _printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
 #define _sentinel_ __attribute__ ((sentinel))
 #define _noreturn_ __attribute__((noreturn))
@@ -51,12 +49,9 @@
 #define STRINGIFY(x) XSTRINGIFY(x)
 
 /* Rounds up */
-static inline size_t ALIGN(size_t l) {
-        return ((l + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
-}
-
-static inline size_t PAGE_ALIGN(size_t l) {
-        return ((l + PAGE_SIZE - 1) & ~(PAGE_SIZE -1));
+#define ALIGN(l) ALIGN_TO((l), sizeof(void*))
+static inline size_t ALIGN_TO(size_t l, size_t ali) {
+        return ((l + ali - 1) & ~(ali - 1));
 }
 
 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
diff --git a/src/readahead-collect.c b/src/readahead-collect.c
index ca82271..67f3c4b 100644
--- a/src/readahead-collect.c
+++ b/src/readahead-collect.c
@@ -64,6 +64,10 @@ static unsigned arg_files_max = 16*1024;
 static off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX;
 static usec_t arg_timeout = 2*USEC_PER_MINUTE;
 
+static size_t page_size;
+#undef PAGE_ALIGN
+#define PAGE_ALIGN(l) ALIGN_TO((l), page_size)
+
 static ReadaheadShared *shared = NULL;
 
 /* Avoid collisions with the NULL pointer */
@@ -119,9 +123,10 @@ static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
                 goto finish;
         }
 
-        pages = l / PAGE_SIZE;
+        pages = l / page_size;
 
         vec = alloca(pages);
+        memset(vec, 0, pages);
         if (mincore(start, l, vec) < 0) {
                 log_warning("mincore(%s) failed: %m", fn);
                 r = -errno;
@@ -649,6 +654,8 @@ int main(int argc, char *argv[]) {
                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 
         root = optind < argc ? argv[optind] : "/";
+        page_size = get_pagesize();
+        log_debug("Detected page size is %d.", page_size);
 
         if (fs_on_read_only(root) > 0) {
                 log_info("Disabling readahead collector due to read-only media.");
diff --git a/src/readahead-common.c b/src/readahead-common.c
index 990ffd4..ae6c1e5 100644
--- a/src/readahead-common.c
+++ b/src/readahead-common.c
@@ -33,6 +33,17 @@
 #include "readahead-common.h"
 #include "util.h"
 
+size_t get_pagesize()
+{
+        long pgsz = sysconf(_SC_PAGESIZE);
+        if (pgsz <= 0) {
+                log_warning("sysconf(_SC_PAGESIZE) failed, assume page size is 4096: %m");
+                pgsz = 4096;
+        }
+
+        return (size_t) pgsz;
+}
+
 int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st) {
         assert(fd >= 0);
         assert(fn);
diff --git a/src/readahead-common.h b/src/readahead-common.h
index 167df31..022a7fa 100644
--- a/src/readahead-common.h
+++ b/src/readahead-common.h
@@ -29,6 +29,7 @@
 
 #define READAHEAD_FILE_SIZE_MAX (128*1024*1024)
 
+size_t get_pagesize();
 int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st);
 
 int fs_on_ssd(const char *p);
diff --git a/src/readahead-replay.c b/src/readahead-replay.c
index d2de7ef..8bc241f 100644
--- a/src/readahead-replay.c
+++ b/src/readahead-replay.c
@@ -44,6 +44,10 @@
 
 static off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX;
 
+static size_t page_size;
+#undef PAGE_ALIGN
+#define PAGE_ALIGN(l) ALIGN_TO((l), page_size)
+
 static ReadaheadShared *shared = NULL;
 
 static int unpack_file(FILE *pack) {
@@ -94,7 +98,7 @@ static int unpack_file(FILE *pack) {
                 any = true;
 
                 if (fd >= 0)
-                        if (posix_fadvise(fd, b * PAGE_SIZE, (c - b) * PAGE_SIZE, POSIX_FADV_WILLNEED) < 0) {
+                        if (posix_fadvise(fd, b * page_size, (c - b) * page_size, POSIX_FADV_WILLNEED) < 0) {
                                 log_warning("posix_fadvise() failed: %m");
                                 goto finish;
                         }
@@ -343,6 +347,8 @@ int main(int argc, char*argv[]) {
                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 
         root = optind < argc ? argv[optind] : "/";
+        page_size = get_pagesize();
+        log_debug("Detected page size is %d.", page_size);
 
         if (!enough_ram()) {
                 log_info("Disabling readahead replay due to low memory.");
-- 
1.7.4.1

