pbchou opened a new issue #7669:
URL: https://github.com/apache/trafficserver/issues/7669
Hi. I would appreciate any second opinions on this issue. I noticed that the
current MaxMind enabled plugins (geoip_acl, header_rewrite, and maxmind_acl)
all use the memory mapped method to open GeoIP DB files using the MaxMind
libraries. The geoip_acl and header_rewrite plugins use the old geopi-api-c
that allows either loading the DB into memory (GEOIP_MEMORY_CACHE) or using a
memory map (GEOIP_MMAP_CACHE). The newer maxmind_acl plugin uses the newer
libmaxminddb that only allows the memory map mode (MMDB_MODE_MMAP).
The potential issue is whether over-writing the DB files on the disk is
visible to the MaxMind libraries. My testing on Linux says that it is although
the Linux man page says that the behavior is unspecified --
<pre>
MAP_PRIVATE
Create a private copy-on-write mapping. Updates to the
mapping are not visible to other processes mapping the
same file, and are not carried through to the underlying
file. It is unspecified whether changes made to the
file after the mmap() call are visible in the mapped region.
</pre>
Since changes are visible -- this can interfere with any in-progress
look-ups when the over-write happens. In addition, if the newer DB file is
larger than the older DB file, then pointers to areas of the file extending
beyond the original file size may be considered by the MaxMind libraries to be
corrupted DB pointers. I think the pointer vs size checking would prevent any
segmentation faults at least. So in general, you would need to close and
re-open the DB files if they are over-written on disk.
So should we --
* consider a documentation update for this issue?
* consider loading the DB files into memory?
* is this an issue on other platforms?
Test program I used on Linux --
<pre>
1. Create data file of "0" of 4096 x 5 size.
while true ; do echo -n "0" ; done | dd if=/dev/stdin of=test-0-05.dat
iflag=fullblock bs=4096 count=5
2. Create date file of "1" of 4096 x 10 size.
while true ; do echo -n "1" ; done | dd if=/dev/stdin of=test-1-10.dat
iflag=fullblock bs=4096 count=10
3. Test with mmap() with PROT_READ MAP_PRIVATE ( used in geoip-api-c ) --
System Page Size: 4096
Trial 00000:
Reached page: 0 address: 0 first-byte: 0
Reached page: 1 address: 4096 first-byte: 0
Reached page: 2 address: 8192 first-byte: 0
Reached page: 3 address: 12288 first-byte: 0
Reached page: 4 address: 16384 first-byte: 0
Length = 20480 last-byte-of-file = 0
Trial 00001:
Reached page: 0 address: 0 first-byte: 0
Reached page: 1 address: 4096 first-byte: 0
Reached page: 2 address: 8192 first-byte: 0
Reached page: 3 address: 12288 first-byte: 0
Reached page: 4 address: 16384 first-byte: 0
Length = 20480 last-byte-of-file = 0
--- replacing test.dat file : 0-file to 1-file ---
Trial 00002:
Reached page: 0 address: 0 first-byte: 1
Reached page: 1 address: 4096 first-byte: 1
Reached page: 2 address: 8192 first-byte: 1
Reached page: 3 address: 12288 first-byte: 1
Reached page: 4 address: 16384 first-byte: 1
Reached page: 5 address: 20480 first-byte:
Reached page: 6 address: 24576 first-byte: h
Reached page: 7 address: 28672 first-byte: �
Segmentation fault (core dumped)
4. Test with mmap() with PROT_READ MAP_SHARED ( used in libmaxminddb ) --
System Page Size: 4096
Trial 00000:
Reached page: 0 address: 0 first-byte: 0
Reached page: 1 address: 4096 first-byte: 0
Reached page: 2 address: 8192 first-byte: 0
Reached page: 3 address: 12288 first-byte: 0
Reached page: 4 address: 16384 first-byte: 0
Length = 20480 last-byte-of-file = 0
Trial 00001:
Reached page: 0 address: 0 first-byte: 0
Reached page: 1 address: 4096 first-byte: 0
Reached page: 2 address: 8192 first-byte: 0
Reached page: 3 address: 12288 first-byte: 0
Reached page: 4 address: 16384 first-byte: 0
Length = 20480 last-byte-of-file = 0
--- replacing test.dat file : 0-file to 1-file ---
Trial 00002:
Reached page: 0 address: 0 first-byte: 1
Reached page: 1 address: 4096 first-byte: 1
Reached page: 2 address: 8192 first-byte: 1
Reached page: 3 address: 12288 first-byte: 1
Reached page: 4 address: 16384 first-byte: 1
Reached page: 5 address: 20480 first-byte:
Reached page: 6 address: 24576 first-byte: h
Reached page: 7 address: 28672 first-byte: �
Segmentation fault (core dumped)
5. Test Program Listing --
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char *addr;
FILE *fd;
int length;
int x;
int count = 0;
int chksum = 0;
system("cp -f test-0-05.dat test.dat");
length = 4096 * 5;
printf("System Page Size: %ld\n", sysconf(_SC_PAGE_SIZE));
fd = fopen("test.dat", "rb");
addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fileno(fd), 0);
while (1) {
if (count == 2) {
system("cp -f test-1-10.dat test.dat");
printf("--- replacing test.dat file : 0-file to 1-file ---\n");
length = 4096 * 10;
sleep(2);
}
printf("Trial %05d:\n", count);
for (x = 0; x < length; x++) {
if (x % 4096 == 0) {
printf("Reached page: %2d address: %6d first-byte: %c\n",
(int)(x / 4096), x, addr[x]);
}
}
printf("Length = %d last-byte-of-file = %c\n", length, addr[length - 1]);
sleep(2);
count++;
}
return 0;
}
</pre>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]