mmap with MAP_PRIVATE is useless (was Re: Bug#569505: git-core: 'git add' corrupts repository if the working directory is modified as it runs)
- From
Paolo Bonzini <bonzini@gnu.org>
- Date
- Feb 14, 2010, 01:36 UTC
- Message-ID
- <4B775384.50009@gnu.org>
- In-Reply-To
- <20100212002741.GB9883@progeny.tock>
Show 5 quoted lines
> I tested this with a number of kernel versions from 2.6.27 to 2.6.31. > All of them reproduced this problem. I checked this because strace > shows 'git add' doing a mmap(..., MAP_PRIVATE, ...) of its input file, > so I was wondering if there might have been a recent change in mmap() > behavior in either git or the kernel.
From mmap(2): "it is unspecified whether changes made to the file after the mmap() call are visible in the mapped region".
You may think that doing a dummy "*p = *p" every 4096 bytes `fixes' it (because it causes copy-on-write for every page) but even that does not work because you can get a SIGBUS if the file is truncated while you have it mapped privately (e.g. by fopen ("file", "w") or open with O_TRUNC).
Testcase:
#include <sys/mman.h> #include <fcntl.h> #include <stdio.h>
int
main ()
{
system ("echo foo > file.test");
int f = open ("file.test", O_RDONLY);
char *p = mmap (NULL, 4096, PROT_READ, MAP_PRIVATE, f, 0);
close (f);
printf ("%s", p); // prints "foo\n" f = open ("file.test", O_RDWR | O_CREAT | O_TRUNC, 0666);
write (f, "bar\n", 4); // comment out and next printf SIGSEGVs
printf ("%s", p); // prints "bar\n"
}This means that MAP_PRIVATE is utterly useless.
Paolo