From d803582a32ed50400c57c75764300a7ab6b192e9 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 6 Apr 2015 01:12:40 +0200 Subject: initial commit --- fmlock.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 fmlock.c (limited to 'fmlock.c') diff --git a/fmlock.c b/fmlock.c new file mode 100644 index 0000000..4ea68d0 --- /dev/null +++ b/fmlock.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int heat_the_cache(int fd) +{ + char buf[1024]; + int rv; + do { + retry_read: + rv = read(fd, buf, sizeof(buf)); + if( -1 == rv + && EINTR == errno ) { + goto retry_read; + } + } while( 0 < rv ); + + return rv != 0; +} + +int main(int argc, char *argv[]) +{ + int i, fd_null, n_fileslocked; + fd_set phony_fdset; + char *buf; + + if( 2 > argc ) { + fprintf(stderr, + "Usage:\n%s [filenames]\n", + argv[0] ); + return 1; + } + + n_fileslocked = 0; + for(i = 1; i < argc; ++i) { + char const * const filename = argv[i]; + int fd; + struct stat st; + void *ptr; + + retry_open: + fd = open(filename, O_RDONLY); + if( -1 == fd ) { + if( EINTR == errno ) { + goto retry_open; + } else + { + fprintf(stderr, + "error open('%s'): %s\n", + filename, + strerror(errno) ); + continue; + } + } + + if( -1 == fstat(fd, &st) ) { + fprintf(stderr, + "error fstat(fd['%s']): %s\n", + filename, + strerror(errno) ); + goto finish_file; + } + + ptr = mmap( + NULL, + st.st_size, + PROT_READ, + MAP_SHARED | MAP_LOCKED, + fd, + 0 ); + if( MAP_FAILED == ptr ) { + fprintf(stderr, + "error mmap(fd['%s'], 0..%lld): %s\n", + filename, + (long long)st.st_size, + strerror(errno) ); + goto finish_file; + } + + if( -1 == mlock(ptr, st.st_size) ) { + fprintf(stderr, + "error mlock(ptr[fd['%s']]=%p): %s\n", + filename, + ptr, + strerror(errno) ); + goto finish_file; + } + ++n_fileslocked; + + heat_the_cache(fd); + + finish_file: + close(fd); + } + + if( !n_fileslocked ) { + return 1; + } + + /* At this point the program shall sleep until a terminating + * signal arrives. To do so a nice side effect of the definition + * of /dev/null behavior is used: read on a /dev/null fd always + * return 0, which correspond to EOF which is a "no content + * available for read (yet)" situation for which select waits. + * So by selecting for a read a fd on /dev/null we can put the + * process to sleep. */ + fd_null = open("/dev/null", O_RDONLY); + if( -1 == fd_null ) { + fprintf(stderr, + "error open('/dev/null'): %s\n", + strerror(errno) ); + return 1; + } + FD_ZERO(&phony_fdset); + FD_SET(fd_null, &phony_fdset); + if( -1 == select(fd_null, &phony_fdset, NULL, NULL, NULL) ) { + fprintf(stderr, + "error select(...): %s\n", + strerror(errno) ); + return 1; + } + + return 0; +} -- cgit v1.2.3