Linux 1.3.36: 'bforget' is flawed

Michael Elizabeth Chastain (mec@duracef.shout.net)
Sun, 5 Nov 1995 18:52:13 -0600


Hello,

The attached test program demonstrates a problem in the new 'bforget'
function in 'fd/buffer.c'. This program runs without problems on
1.3.35, but causes problems on 1.3.36.

I originally found this problem with a program that creates a dynamic
library on the fly, allows a target process to call 'uselib', and then
immediately unlinks the dynamic library. (This is part of a
trace-and-replay debugger).

>From reading the code, it appears that 'bforget' is an optimized form
of 'brelse' for cases where a buffer has 'b_count == 1'. But buffers
can be shared with non-buffer objects, specifically with memory maps,
and this causes the problem.

I am not experienced with the buffer cache, so my analysis could be
wrong.

Michael Chastain
mec@duracef.shout.net

---

/* * Make Linux 1.3.36 say: 'Aieee... bforget(): shared buffer'. * Warning: file system becomes unstable after running this. * Happens about 3/4 of the time. * * gcc -O2 -static -Wall t-065.c * * This program must be statically linked. * Mess with the buffer size to adapt to your system. * My system: IBM 486 66 MHz SLC/2, 8 mb memory, ext2fs, plain IDE. * * Michael Elizabeth Chastain * mec@duracef.shout.net * Sun 05 Nov 1995 */

#include <sys/types.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h>

static char buf[2 * 1048576];

int main( ) { int fd; char * p; int i; int sum;

for ( i = 0; i < sizeof(buf); ++i ) buf[i] = i;

fd = open( "x-lib", O_RDWR | O_CREAT | O_TRUNC, 0755 ); write( fd, buf, sizeof(buf) ); fsync( fd ); p = mmap( 0, sizeof(buf), PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0 ); close( fd ); unlink( "x-lib" );

sum = 0; for ( i = 0; i < sizeof(buf); i += 0x1000 ) sum += p[i];

munmap( p, sizeof(buf) ); _exit( sum ); }