Commit 7a2e24ef authored by Julius Plenz's avatar Julius Plenz

Merge branch 'n-times-fadvise'

* n-times-fadvise: Update man pages to reflect "-n" option Only do multi-fadvise if previous call was successful Add explanation of -n flag / NOCACHE_NR_FADVISE env variable Implement "-n <n>" flag for repeated posix_fadvise() There was a trivial-to-solve merge conflict in nocache.c
parents 9e2f973e a30e207a
......@@ -34,6 +34,8 @@ For testing purposes, I included two small tools:
* `cachedel` calls `posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)` on
the file argument. Thus, if the file is not accessed by any other
application, the pages will be eradicated from the fs cache.
Specifying -n <number> will repeat the syscall the given number of
times which can be useful in some circumstances (see below).
* `cachestats` has three modes: In quiet mode (`-q`), the exit status
is 0 (success) if the file is fully cached. In normal mode,
the number of cached vs. not-cached pages is printed. In verbose
......@@ -94,9 +96,17 @@ There are timing issues to consider, as well. If you consider `nocache
cat <file>`, in most (all?) cases the cache will not be restored. For
discussion and possible solutions see <http://lwn.net/Articles/480930/>.
My experience showed that in many cases you could "fix" this by doing
the `posix_fadvise` call *twice*. If you want this behaviour, compile
the library using `make CFLAGS=-DDOUBLEFADVISE`.
the `posix_fadvise` call *twice*. For both tools `nocache` and
`cachedel` you can specify the number using `-n`, like so:
$ nocache -n 2 cat ~/file.mp3
This actually only sets the environment variable `NOCACHE_NR_FADVISE`
to the specified value, and the shared library reads out this value.
If test number 3 in `t/basic.t` fails, then try increasing this number
until it works, e.g.:
$ env NOCACHE_NR_FADVISE=2 make test
Acknowledgements
----------------
......
......@@ -4,6 +4,7 @@
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int exiterr(const char *s)
{
......@@ -13,32 +14,40 @@ int exiterr(const char *s)
int main(int argc, char *argv[])
{
int i, n = 1;
int fd;
char *fn;
struct stat st;
if(argc != 2) {
fprintf(stderr, "usage: %s <file> "
"-- call fadvise(DONTNEED) on file", argv[0]);
if(argc == 4 && !strcmp("-n", argv[1])) {
n = atoi(argv[2]);
fn = argv[3];
} else if(argc != 2) {
fprintf(stderr, "usage: %s [-n <n>] <file> "
"-- call fadvise(DONTNEED) <n> times on file", argv[0]);
exit(1);
} else {
fn = argv[1];
}
fd = open(argv[1], O_RDONLY);
fd = open(fn, O_RDONLY);
if(fd == -1)
exiterr("open");
if(fstat(fd, &st) == -1)
exiterr("fstat");
if(!S_ISREG(st.st_mode)) {
fprintf(stderr, "%s: S_ISREG: not a regular file", argv[1]);
fprintf(stderr, "%s: S_ISREG: not a regular file", fn);
return EXIT_FAILURE;
}
if(st.st_size == 0) {
fprintf(stderr, "%s: file size is 0!\n", argv[1]);
fprintf(stderr, "%s: file size is 0!\n", fn);
return EXIT_FAILURE;
}
if(posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED) == -1)
exiterr("posix_fadvise");
for(i = 0; i < n; i++)
if(posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED) == -1)
exiterr("posix_fadvise");
return EXIT_SUCCESS;
}
......@@ -5,12 +5,12 @@
/* 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)
int fadv_dontneed(int fd, off_t offset, off_t len, int n)
{
#ifdef DOUBLEFADVISE
posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);
#endif
return posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);
int i, ret;
for(i = 0, ret = 0; i < n && ret == 0; i++)
ret = posix_fadvise(fd, offset, len, POSIX_FADV_DONTNEED);
return ret;
}
int fadv_noreuse(int fd, off_t offset, off_t len)
......
#ifndef _FCNTL_HELPERS_H
#define _FCNTL_HELPERS_H
extern int fadv_dontneed(int fd, off_t offset, off_t len);
extern int fadv_dontneed(int fd, off_t offset, off_t len, int n);
extern int fadv_noreuse(int fd, off_t offset, off_t len);
extern int valid_fd(int fd);
extern void sync_if_writable(int fd);
......
......@@ -2,6 +2,10 @@
.SH NAME
cachedel \- drop pagecache for a file
.SH SYNOPSIS
cachedel \fBfile\fR
cachedel [-n <n>] \fBfile\fR
.SH OPTIONS
.TP
\fB\-n <n>\fR "Repeat system call"
Will call posix_fadvise(POSIX_FADV_DONTNEED) \fB<n>\fR in a row.
.SH DESCRIPTION
Call fadvise(DONTNEED) on file
Call posix_fadvise(POSIX_FADV_DONTNEED) on file.
......@@ -2,7 +2,13 @@
.SH NAME
nocache \- don't use Linux page cache on given command
.SH SYNOPSIS
nocache \fBcommand\fR [argument...]
nocache [-n <n>] \fBcommand\fR [argument...]
.SH OPTIONS
.TP
\fB\-n <n>\fR "Set number of fadvise calls"
Execute the `posix_fadvise` system call \fB<n>\fR times in a row.
Depending on your machine, this might give better results (use it if in
your tests `nocache` fails to eradicate pages from cache properly).
.SH DESCRIPTION
The `nocache` tool tries to minimize the effect an application has on
the Linux file system cache. This is done by intercepting the `open`
......
......@@ -8,4 +8,9 @@ else
export LD_PRELOAD="$libnocache"
fi
if [ "$1" = "-n" ]; then
export NOCACHE_NR_FADVISE="$2"
shift 2
fi
exec "$@"
......@@ -63,9 +63,13 @@ static struct fadv_info *fds;
static size_t PAGESIZE;
static pthread_mutex_t lock; /* protects access to fds[] */
static char *env_nr_fadvise = "NOCACHE_NR_FADVISE";
static int nr_fadvise;
static void init(void)
{
int i;
char *s;
char *error;
struct rlimit rlim;
......@@ -93,7 +97,10 @@ static void init(void)
exit(EXIT_FAILURE);
}
if((s = getenv(env_nr_fadvise)) != NULL)
nr_fadvise = atoi(s);
if(nr_fadvise <= 0)
nr_fadvise = 1;
PAGESIZE = getpagesize();
for(i = 0; i < max_fds; i++)
......@@ -308,14 +315,14 @@ static void free_unclaimed_pages(int fd)
while(j < fds[i].nr_pages) {
if(fds[i].info[j] & 1) {
if(start < j)
fadv_dontneed(fd, start*PAGESIZE, (j - start) * PAGESIZE);
fadv_dontneed(fd, start*PAGESIZE, (j - start) * PAGESIZE, nr_fadvise);
start = j + 1;
}
j++;
}
/* forget written contents that go beyond previous file size */
fadv_dontneed(fd, start < j ? start*PAGESIZE : fds[i].size, 0);
fadv_dontneed(fd, start < j ? start*PAGESIZE : fds[i].size, 0, nr_fadvise);
free(fds[i].info);
fds[i].fd = -1;
......
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