use mmap() for files of any size. This should be much more buffer
authorAndrew Tridgell <tridge@samba.org>
Thu, 21 May 1998 05:52:37 +0000 (05:52 +0000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 21 May 1998 05:52:37 +0000 (05:52 +0000)
cache friendly.

syscall.c
util.c

index c655969..a8470e1 100644 (file)
--- 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 89bc75b..efc9daf 100644 (file)
--- 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);
 }