Permalink
Browse files

Simple implementaion invalidates pages on close()

  • Loading branch information...
1 parent 34f45b4 commit f1ca529abfeaf2d8328f2c925b0ba67470ba8b83 @Feh committed Feb 3, 2012
Showing with 92 additions and 5 deletions.
  1. +2 −1 Makefile
  2. +9 −0 fadv_dontneed.c
  3. +81 −4 nocache.c
View
@@ -1,3 +1,4 @@
default:
gcc -Wall -fPIC -c -o nocache.o nocache.c
- gcc -Wall -shared -Wl,-soname,nocache.so.1 -ldl -o nocache.so nocache.o
+ gcc -Wall -fPIC -c -o fadv_dontneed.o fadv_dontneed.c
+ gcc -Wall -shared -Wl,-soname,nocache.so.1 -ldl -o nocache.so nocache.o fadv_dontneed.o
View
@@ -0,0 +1,9 @@
+#include <fcntl.h>
+
+/* Since open() and close() are re-defined in nocache.c, it's not
+ * possible to include <fcntl.h> there. So we do it here. */
+
+int fadv_dontneed(int fd, off_t offset, off_t len)
+{
+ return posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);
+}
View
@@ -1,31 +1,108 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
-#include <dlfcn.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <stdio.h>
+#include <dlfcn.h>
int (*_original_open)(const char *pathname, int flags, mode_t mode);
int (*_original_close)(int fd);
void init(void) __attribute__((constructor));
int open(const char *pathname, int flags, mode_t mode);
int close(int fd);
+static void store_pageinfo(int fd);
+static void free_pages(int fd);
+extern int fadv_dontneed(int fd, off_t offset, off_t len);
+
+#define _MAX_FDS 1024
+
+struct fadv_info {
+ int fd;
+ unsigned int nr_pages;
+ void *info;
+};
+static struct fadv_info fds[_MAX_FDS];
+static size_t PAGESIZE;
void init(void)
{
_original_open = (int (*)(const char *, int, mode_t))
dlsym(RTLD_NEXT, "open");
_original_close = (int (*)(int)) dlsym(RTLD_NEXT, "close");
+ PAGESIZE = sysconf(_SC_PAGESIZE);
}
int open(const char *pathname, int flags, mode_t mode)
{
- fprintf(stderr, "I intercepted the open() call!\n");
- return _original_open(pathname, flags, mode);
+ int fd;
+ if((fd = _original_open(pathname, flags, mode)) != -1)
+ store_pageinfo(fd);
+ return fd;
}
int close(int fd)
{
- fprintf(stderr, "I intercepted the close() call!\n");
+ free_pages(fd);
return _original_close(fd);
}
+
+static void store_pageinfo(int fd)
+{
+ int i;
+ int pages;
+ struct stat st;
+ void *file;
+ unsigned char *pageinfo;
+
+ /* check if there's space to store the info */
+ for(i = 0; i < _MAX_FDS && fds[i].fd; i++)
+ ;
+ if(i == _MAX_FDS)
+ return; /* no space! */
+ fds[i].fd = fd;
+
+ if(fstat(fd, &st) == -1)
+ return;
+
+ pages = fds[i].nr_pages = (st.st_size + PAGESIZE - 1) / PAGESIZE;
+ pageinfo = calloc(sizeof(*pageinfo), pages);
+ if(!pageinfo)
+ return;
+
+ file = mmap(NULL, st.st_size, PROT_NONE, MAP_SHARED, fd, 0);
+ if(file == MAP_FAILED)
+ return;
+ if(mincore(file, st.st_size, pageinfo) == -1)
+ return;
+
+ fds[i].info = pageinfo;
+
+#if DEBUG
+ fprintf(stderr, "cache stats: ");
+ int j;
+ for(j=0; i<pages; i++) {
+ fprintf(stderr, "%c", (pageinfo[j] & 1) ? 'Y' : 'N');
+ }
+ fprintf(stderr, "\n");
+#endif
+
+ munmap(file, st.st_size);
+}
+
+static void free_pages(int fd)
+{
+ int i, j;
+
+ for(i = 0; i < _MAX_FDS; i++)
+ if(fds[i].fd == fd)
+ break;
+ if(i == _MAX_FDS)
+ return; /* not found */
+
+ for(j = 0; j < fds[i].nr_pages; j++)
+ if(!(((unsigned char *)fds[i].info)[j] & 1))
+ fadv_dontneed(fd, j*PAGESIZE, PAGESIZE);
+}

0 comments on commit f1ca529

Please sign in to comment.