Commit f1ca529a authored by Julius Plenz's avatar Julius Plenz

Simple implementaion invalidates pages on close()

parent 34f45b4a
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
#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);
}
#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);
......@@ -10,22 +13,96 @@ 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment