From 754d120c98d699b5cb9eae20967de0dd949028cd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 21 May 1998 05:52:37 +0000 Subject: [PATCH] use mmap() for files of any size. This should be much more buffer cache friendly. --- syscall.c | 11 +++++++ util.c | 89 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/syscall.c b/syscall.c index c655969e..a8470e14 100644 --- a/syscall.c +++ b/syscall.c @@ -149,6 +149,17 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence) #endif } +#if HAVE_MMAP +void *do_mmap(void *start, int len, int prot, int flags, int fd, OFF_T offset) +{ +#if HAVE_OFF64_T + return mmap64(start, len, prot, flags, fd, offset); +#else + return mmap(start, len, prot, flags, fd, offset); +#endif +} +#endif + char *d_name(struct dirent *di) { #if HAVE_BROKEN_READDIR diff --git a/util.c b/util.c index 89bc75be..efc9dafd 100644 --- a/util.c +++ b/util.c @@ -34,27 +34,28 @@ int num_waiting(int fd) struct map_struct *map_file(int fd,OFF_T len) { - struct map_struct *ret; - ret = (struct map_struct *)malloc(sizeof(*ret)); - if (!ret) out_of_memory("map_file"); - - ret->map = NULL; - ret->fd = fd; - ret->size = len; - ret->p = NULL; - ret->p_size = 0; - ret->p_offset = 0; - ret->p_len = 0; + struct map_struct *ret; + ret = (struct map_struct *)malloc(sizeof(*ret)); + if (!ret) out_of_memory("map_file"); + + ret->map = NULL; + ret->fd = fd; + ret->size = len; + ret->p = NULL; + ret->p_size = 0; + ret->p_offset = 0; + ret->p_len = 0; #ifdef HAVE_MMAP - if (len < MAX_MAP_SIZE) { - ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0); - if (ret->map == (char *)-1) { - ret->map = NULL; - } - } + len = MIN(len, MAX_MAP_SIZE); + ret->map = (char *)do_mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0); + if (ret->map == (char *)-1) { + ret->map = NULL; + } else { + ret->p_len = len; + } #endif - return ret; + return ret; } @@ -62,15 +63,47 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len) { int nread; - if (map->map) - return map->map+offset; - if (len == 0) return NULL; if (len > (map->size-offset)) len = map->size-offset; + if (map->map) { + if (offset >= map->p_offset && + offset+len <= map->p_offset+map->p_len) { + return (map->map + (offset - map->p_offset)); + } + if (munmap(map->map, map->p_len) != 0) { + rprintf(FERROR,"munmap failed : %s\n", strerror(errno)); + exit_cleanup(1); + } + + /* align the mmap region on a nice boundary back a bit from + where it is asked for to allow for some seeking */ + if (offset > 2*CHUNK_SIZE) { + map->p_offset = offset - 2*CHUNK_SIZE; + map->p_offset &= ~((OFF_T)(CHUNK_SIZE-1)); + } else { + map->p_offset = 0; + } + + /* map up to MAX_MAP_SIZE */ + map->p_len = MAX(len, MAX_MAP_SIZE); + map->p_len = MIN(map->p_len, map->size - map->p_offset); + + map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ, + MAP_SHARED,map->fd,map->p_offset); + + if (map->map == (char *)-1) { + map->map = NULL; + map->p_len = 0; + map->p_offset = 0; + } else { + return (map->map + (offset - map->p_offset)); + } + } + if (offset >= map->p_offset && offset+len <= map->p_offset+map->p_len) { return (map->p + (offset - map->p_offset)); @@ -109,11 +142,17 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len) void unmap_file(struct map_struct *map) { #ifdef HAVE_MMAP - if (map->map) - munmap(map->map,map->size); + if (map->map) { + munmap(map->map,map->p_len); + map->map = NULL; + } #endif - if (map->p) free(map->p); - free(map); + if (map->p) { + free(map->p); + map->p = NULL; + } + memset(map, 0, sizeof(*map)); + free(map); } -- 2.34.1