diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d435f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.so +cachedel +cachestats +nocache diff --git a/Makefile b/Makefile index 88aa8e2..4f8b4bf 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,11 @@ bindir = $(DESTDIR)$(PREFIX)$(BINDIR) libdir = $(DESTDIR)$(PREFIX)$(LIBDIR) CACHE_BINS=cachedel cachestats -NOCACHE_BINS=nocache.o fcntl_helpers.o pageinfo.o +NOCACHE_BINS=nocache.o fcntl_helpers.o pageinfo.o wrappers.o MANPAGES=$(wildcard man/*.1) CC ?= gcc -CFLAGS+= -Wall +CFLAGS+= -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64 COMPILE = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) .PHONY: all diff --git a/nocache.c b/nocache.c index ae2699b..fccb3f3 100644 --- a/nocache.c +++ b/nocache.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -15,8 +16,10 @@ #include #include +#include "wrappers.h" #include "pageinfo.h" #include "fcntl_helpers.h" +#include "nocache.h" static void init(void) __attribute__((constructor)); static void destroy(void) __attribute__((destructor)); @@ -24,38 +27,6 @@ static void init_mutexes(void); static void init_debugging(void); static void handle_stdout(void); -static void store_pageinfo(int fd); -static void free_unclaimed_pages(int fd, bool block_signals); - -int open(const char *pathname, int flags, mode_t mode); -int open64(const char *pathname, int flags, mode_t mode); -int creat(const char *pathname, int flags, mode_t mode); -int creat64(const char *pathname, int flags, mode_t mode); -int openat(int dirfd, const char *pathname, int flags, mode_t mode); -int openat64(int dirfd, const char *pathname, int flags, mode_t mode); -int __openat_2(int dirfd, const char *pathname, int flags, mode_t mode) - __attribute__ ((alias ("openat"))); -int dup(int oldfd); -int dup2(int oldfd, int newfd); -int close(int fd); -FILE *fopen(const char *path, const char *mode); -FILE *fopen64(const char *path, const char *mode); -int fclose(FILE *fp); - -int (*_original_open)(const char *pathname, int flags, mode_t mode); -int (*_original_open64)(const char *pathname, int flags, mode_t mode); -int (*_original_creat)(const char *pathname, int flags, mode_t mode); -int (*_original_creat64)(const char *pathname, int flags, mode_t mode); -int (*_original_openat)(int dirfd, const char *pathname, int flags, mode_t mode); -int (*_original_openat64)(int dirfd, const char *pathname, int flags, mode_t mode); -int (*_original_dup)(int fd); -int (*_original_dup2)(int newfd, int oldfd); -int (*_original_close)(int fd); -FILE *(*_original_fopen)(const char *path, const char *mode); -FILE *(*_original_fopen64)(const char *path, const char *mode); -int (*_original_fclose)(FILE *fp); - - /* Info about a file descriptor 'fd' is stored in fds[fd]. Before accessing an * element, callers MUST both check fds_lock != NULL and then acquire * fds_lock[fd] while holding the fds_iter_lock. While any mutex in fds_lock is @@ -70,9 +41,11 @@ static size_t PAGESIZE; static char *env_nr_fadvise = "NOCACHE_NR_FADVISE"; static int nr_fadvise; +int nocache_EOF; + static char *env_debugfd = "NOCACHE_DEBUGFD"; -int debugfd = -1; -FILE *debugfp; +static int debugfd = -1; +static FILE *debugfp; static char *env_flushall = "NOCACHE_FLUSHALL"; static char flushall; @@ -80,12 +53,21 @@ static char flushall; static char *env_max_fds = "NOCACHE_MAX_FDS"; static rlim_t max_fd_limit = 1 << 20; -#define DEBUG(...) \ - do { \ - if(debugfp != NULL) { \ - fprintf(debugfp, "[nocache] DEBUG: " __VA_ARGS__); \ - } \ - } while(0) +int nocache_fileno(FILE *fp) +{ + return fileno(fp); +} + +void debug(const char *fmt, ...) +{ + if(debugfp != NULL) { + va_list args; + + va_start(args, fmt); + vfprintf(debugfp, fmt, args); + va_end(args); + } +} static void init(void) { @@ -141,6 +123,7 @@ static void init(void) } PAGESIZE = getpagesize(); + nocache_EOF = EOF; pthread_mutex_lock(&fds_iter_lock); for(i = 0; i < max_fds; i++) { pthread_mutex_lock(&fds_lock[i]); @@ -232,198 +215,7 @@ static void destroy(void) pthread_mutex_unlock(&fds_iter_lock); } -int open(const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_open) - _original_open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); - assert(_original_open != NULL); - - if((fd = _original_open(pathname, flags, mode)) != -1) { - DEBUG("open(pathname=%s, flags=0x%x, mode=0%o) = %d\n", - pathname, flags, mode, fd); - store_pageinfo(fd); - } - return fd; -} - -int open64(const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_open64) - _original_open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); - assert(_original_open64 != NULL); - - DEBUG("open64(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); - - if((fd = _original_open64(pathname, flags, mode)) != -1) - store_pageinfo(fd); - return fd; -} - -int creat(const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_creat) - _original_creat = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "creat"); - assert(_original_creat != NULL); - - DEBUG("creat(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); - - if((fd = _original_creat(pathname, flags, mode)) != -1) - store_pageinfo(fd); - return fd; -} - -int creat64(const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_creat64) - _original_creat64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "creat64"); - assert(_original_creat64 != NULL); - - DEBUG("creat64(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); - - if((fd = _original_creat64(pathname, flags, mode)) != -1) - store_pageinfo(fd); - return fd; -} - -int openat(int dirfd, const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_openat) - _original_openat = (int (*)(int, const char *, int, mode_t)) dlsym(RTLD_NEXT, "openat"); - assert(_original_openat != NULL); - - DEBUG("openat(dirfd=%d, pathname=%s, flags=0x%x, mode=0%o)\n", dirfd, pathname, flags, mode); - - if((fd = _original_openat(dirfd, pathname, flags, mode)) != -1) - store_pageinfo(fd); - return fd; -} - -int openat64(int dirfd, const char *pathname, int flags, mode_t mode) -{ - int fd; - - if(!_original_openat64) - _original_openat64 = (int (*)(int, const char *, int, mode_t)) dlsym(RTLD_NEXT, "openat64"); - assert(_original_openat64 != NULL); - - DEBUG("openat64(dirfd=%d, pathname=%s, flags=0x%x, mode=0%o)\n", dirfd, pathname, flags, mode); - - if((fd = _original_openat64(dirfd, pathname, flags, mode)) != -1) - store_pageinfo(fd); - return fd; -} - -int dup(int oldfd) -{ - int fd; - - if(!_original_dup) - _original_dup = (int (*)(int)) dlsym(RTLD_NEXT, "dup"); - assert(_original_dup != NULL); - - DEBUG("dup(oldfd=%d)\n", oldfd); - - if((fd = _original_dup(oldfd)) != -1) - store_pageinfo(fd); - return fd; -} - -int dup2(int oldfd, int newfd) -{ - int ret; - - /* if newfd is already opened, the kernel will close it directly - * once dup2 is invoked. So now is the last chance to mark the - * pages as "DONTNEED" */ - if(valid_fd(newfd)) - free_unclaimed_pages(newfd, true); - - if(!_original_dup2) - _original_dup2 = (int (*)(int, int)) dlsym(RTLD_NEXT, "dup2"); - assert(_original_dup2 != NULL); - - DEBUG("dup2(oldfd=%d, newfd=%d)\n", oldfd, newfd); - - if((ret = _original_dup2(oldfd, newfd)) != -1) - store_pageinfo(newfd); - return ret; -} - -int close(int fd) -{ - if(!_original_close) - _original_close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); - assert(_original_close != NULL); - - free_unclaimed_pages(fd, true); - - DEBUG("close(%d)\n", fd); - return _original_close(fd); -} - -FILE *fopen(const char *path, const char *mode) -{ - int fd; - FILE *fp = NULL; - - if(!_original_fopen) - _original_fopen = (FILE *(*)(const char *, const char *)) dlsym(RTLD_NEXT, "fopen"); - assert(_original_fopen != NULL); - - DEBUG("fopen(path=%s, mode=%s)\n", path, mode); - - if((fp = _original_fopen(path, mode)) != NULL) - if((fd = fileno(fp)) != -1) - store_pageinfo(fd); - - return fp; -} - -FILE *fopen64(const char *path, const char *mode) -{ - int fd; - FILE *fp; - fp = NULL; - - if(!_original_fopen64) - _original_fopen64 = (FILE *(*)(const char *, const char *)) dlsym(RTLD_NEXT, "fopen64"); - assert(_original_fopen64 != NULL); - - DEBUG("fopen64(path=%s, mode=%s)\n", path, mode); - - if((fp = _original_fopen64(path, mode)) != NULL) - if((fd = fileno(fp)) != -1) - store_pageinfo(fd); - - return fp; -} - -int fclose(FILE *fp) -{ - if(!_original_fclose) - _original_fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); - assert(_original_fclose != NULL); - - if(_original_fclose) { - free_unclaimed_pages(fileno(fp), true); - return _original_fclose(fp); - } - - errno = EFAULT; - return EOF; -} - -static void store_pageinfo(int fd) +void store_pageinfo(int fd) { sigset_t mask, old_mask; @@ -472,7 +264,7 @@ static void store_pageinfo(int fd) return; } -static void free_unclaimed_pages(int fd, bool block_signals) +void free_unclaimed_pages(int fd, bool block_signals) { struct stat st; sigset_t mask, old_mask; diff --git a/nocache.h b/nocache.h new file mode 100644 index 0000000..6853367 --- /dev/null +++ b/nocache.h @@ -0,0 +1,17 @@ +#ifndef NOCACHE_H +#define NOCACHE_H + +#include + +#define DEBUG(...) \ + debug("[nocache] DEBUG: " __VA_ARGS__) + +void debug(const char *fmt, ...); + +extern int nocache_EOF; +int nocache_fileno(FILE *fp); + +void store_pageinfo(int fd); +void free_unclaimed_pages(int fd, bool block_signals); + +#endif diff --git a/pageinfo.c b/pageinfo.c index 12f8b0d..c0de511 100644 --- a/pageinfo.c +++ b/pageinfo.c @@ -9,14 +9,7 @@ #include #include "pageinfo.h" - -extern FILE *debugfp; -#define DEBUG(...) \ - do { \ - if(debugfp != NULL) { \ - fprintf(debugfp, "[nocache] DEBUG: " __VA_ARGS__); \ - } \ - } while(0) +#include "nocache.h" static int insert_into_br_list(struct file_pageinfo *pi, struct byterange **brtail, size_t pos, size_t len); diff --git a/wrappers.c b/wrappers.c new file mode 100644 index 0000000..638c588 --- /dev/null +++ b/wrappers.c @@ -0,0 +1,232 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +typedef struct FILE FILE; + +#include "wrappers.h" +#include "pageinfo.h" +#include "fcntl_helpers.h" +#include "nocache.h" + +int open(const char *pathname, int flags, mode_t mode); +int open64(const char *pathname, int flags, mode_t mode); +int creat(const char *pathname, int flags, mode_t mode); +int creat64(const char *pathname, int flags, mode_t mode); +int openat(int dirfd, const char *pathname, int flags, mode_t mode); +int openat64(int dirfd, const char *pathname, int flags, mode_t mode); +int dup(int oldfd); +int dup2(int oldfd, int newfd); +int close(int fd); +FILE *fopen(const char *path, const char *mode); +FILE *fopen64(const char *path, const char *mode); +int fclose(FILE *fp); + +int (*_original_open)(const char *pathname, int flags, mode_t mode); +int (*_original_open64)(const char *pathname, int flags, mode_t mode); +int (*_original_creat)(const char *pathname, int flags, mode_t mode); +int (*_original_creat64)(const char *pathname, int flags, mode_t mode); +int (*_original_openat)(int dirfd, const char *pathname, int flags, mode_t mode); +int (*_original_openat64)(int dirfd, const char *pathname, int flags, mode_t mode); +int (*_original_dup)(int fd); +int (*_original_dup2)(int newfd, int oldfd); +int (*_original_close)(int fd); +FILE *(*_original_fopen)(const char *path, const char *mode); +FILE *(*_original_fopen64)(const char *path, const char *mode); +int (*_original_fclose)(FILE *fp); + +int open(const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_open) + _original_open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open"); + assert(_original_open != NULL); + + if((fd = _original_open(pathname, flags, mode)) != -1) { + DEBUG("open(pathname=%s, flags=0x%x, mode=0%o) = %d\n", + pathname, flags, mode, fd); + store_pageinfo(fd); + } + return fd; +} + +int open64(const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_open64) + _original_open64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "open64"); + assert(_original_open64 != NULL); + + DEBUG("open64(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); + + if((fd = _original_open64(pathname, flags, mode)) != -1) + store_pageinfo(fd); + return fd; +} + +int creat(const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_creat) + _original_creat = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "creat"); + assert(_original_creat != NULL); + + DEBUG("creat(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); + + if((fd = _original_creat(pathname, flags, mode)) != -1) + store_pageinfo(fd); + return fd; +} + +int creat64(const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_creat64) + _original_creat64 = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT, "creat64"); + assert(_original_creat64 != NULL); + + DEBUG("creat64(pathname=%s, flags=0x%x, mode=0%o)\n", pathname, flags, mode); + + if((fd = _original_creat64(pathname, flags, mode)) != -1) + store_pageinfo(fd); + return fd; +} + +int openat(int dirfd, const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_openat) + _original_openat = (int (*)(int, const char *, int, mode_t)) dlsym(RTLD_NEXT, "openat"); + assert(_original_openat != NULL); + + DEBUG("openat(dirfd=%d, pathname=%s, flags=0x%x, mode=0%o)\n", dirfd, pathname, flags, mode); + + if((fd = _original_openat(dirfd, pathname, flags, mode)) != -1) + store_pageinfo(fd); + return fd; +} + +int openat64(int dirfd, const char *pathname, int flags, mode_t mode) +{ + int fd; + + if(!_original_openat64) + _original_openat64 = (int (*)(int, const char *, int, mode_t)) dlsym(RTLD_NEXT, "openat64"); + assert(_original_openat64 != NULL); + + DEBUG("openat64(dirfd=%d, pathname=%s, flags=0x%x, mode=0%o)\n", dirfd, pathname, flags, mode); + + if((fd = _original_openat64(dirfd, pathname, flags, mode)) != -1) + store_pageinfo(fd); + return fd; +} + +int dup(int oldfd) +{ + int fd; + + if(!_original_dup) + _original_dup = (int (*)(int)) dlsym(RTLD_NEXT, "dup"); + assert(_original_dup != NULL); + + DEBUG("dup(oldfd=%d)\n", oldfd); + + if((fd = _original_dup(oldfd)) != -1) + store_pageinfo(fd); + return fd; +} + +int dup2(int oldfd, int newfd) +{ + int ret; + + /* if newfd is already opened, the kernel will close it directly + * once dup2 is invoked. So now is the last chance to mark the + * pages as "DONTNEED" */ + if(valid_fd(newfd)) + free_unclaimed_pages(newfd, true); + + if(!_original_dup2) + _original_dup2 = (int (*)(int, int)) dlsym(RTLD_NEXT, "dup2"); + assert(_original_dup2 != NULL); + + DEBUG("dup2(oldfd=%d, newfd=%d)\n", oldfd, newfd); + + if((ret = _original_dup2(oldfd, newfd)) != -1) + store_pageinfo(newfd); + return ret; +} + +int close(int fd) +{ + if(!_original_close) + _original_close = (int (*)(int)) dlsym(RTLD_NEXT, "close"); + assert(_original_close != NULL); + + free_unclaimed_pages(fd, true); + + DEBUG("close(%d)\n", fd); + return _original_close(fd); +} + +FILE *fopen(const char *path, const char *mode) +{ + int fd; + FILE *fp = NULL; + + if(!_original_fopen) + _original_fopen = (FILE *(*)(const char *, const char *)) dlsym(RTLD_NEXT, "fopen"); + assert(_original_fopen != NULL); + + DEBUG("fopen(path=%s, mode=%s)\n", path, mode); + + if((fp = _original_fopen(path, mode)) != NULL) + if((fd = nocache_fileno(fp)) != -1) + store_pageinfo(fd); + + return fp; +} + +FILE *fopen64(const char *path, const char *mode) +{ + int fd; + FILE *fp; + fp = NULL; + + if(!_original_fopen64) + _original_fopen64 = (FILE *(*)(const char *, const char *)) dlsym(RTLD_NEXT, "fopen64"); + assert(_original_fopen64 != NULL); + + DEBUG("fopen64(path=%s, mode=%s)\n", path, mode); + + if((fp = _original_fopen64(path, mode)) != NULL) + if((fd = nocache_fileno(fp)) != -1) + store_pageinfo(fd); + + return fp; +} + +int fclose(FILE *fp) +{ + if(!_original_fclose) + _original_fclose = (int (*)(FILE *)) dlsym(RTLD_NEXT, "fclose"); + assert(_original_fclose != NULL); + + if(_original_fclose) { + free_unclaimed_pages(nocache_fileno(fp), true); + return _original_fclose(fp); + } + + errno = EFAULT; + return nocache_EOF; +} + +/* vim:set et sw=4 ts=4: */ diff --git a/wrappers.h b/wrappers.h new file mode 100644 index 0000000..dc66bfd --- /dev/null +++ b/wrappers.h @@ -0,0 +1,17 @@ +#ifndef NOCACHE_WRAPPERS_H +#define NOCACHE_WRAPPERS_H + +extern int (*_original_open)(const char *pathname, int flags, mode_t mode); +extern int (*_original_open64)(const char *pathname, int flags, mode_t mode); +extern int (*_original_creat)(const char *pathname, int flags, mode_t mode); +extern int (*_original_creat64)(const char *pathname, int flags, mode_t mode); +extern int (*_original_openat)(int dirfd, const char *pathname, int flags, mode_t mode); +extern int (*_original_openat64)(int dirfd, const char *pathname, int flags, mode_t mode); +extern int (*_original_dup)(int fd); +extern int (*_original_dup2)(int newfd, int oldfd); +extern int (*_original_close)(int fd); +extern FILE *(*_original_fopen)(const char *path, const char *mode); +extern FILE *(*_original_fopen64)(const char *path, const char *mode); +extern int (*_original_fclose)(FILE *fp); + +#endif