Bug 21222

Summary: [nfs] wrong behavior of concurrent mmap()s on NFS files
Product: Base System Reporter: kmv <kmv>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-RELEASE   
Hardware: Any   
OS: Any   

Description kmv 2000-09-12 14:10:01 UTC
    The following sequence of moves gets quite different results when performed
on local filesystem and when performed on NFS:
   1. process_1 opens a file read-only, does mmap() call on it (readonly).
   2. process_2 opens the same file read-write, uses ftruncate() on it to
      increase file length, does mmap() call on it (read-write), writes
      certain data into the memory mapped area near the end of the file, does
      munmap() and exits.
   3. process_1 does munmap() and exits.

    If the mmap()-ed file is on local filesystem, everything works just as we
would expect it to: after the mentioned above sequence, the file appeares to be
longer (correctly increased by process_2) and contains the data written by
process_2 near the end of file. But if the mmap()-ed file is on NFS-mounted
filesystem, the result is quite different: the file length appears to be correct
(increased by process_2), but the data, written by the process_2 into the area
near the end of file, seems to be (partially) nullified.
    Experiments show that data loss occures in the area between the the end of
initial file (before ftruncate()) and the nearest 4k-block boundary above.

Fix: 

Unknown.
How-To-Repeat: 
	

    Compile both of the supplied programs. Run first program; it will perform
step (1) from the above sequence and wait for the input. Meanwhile, run the
second program; it will perform step (2). Then, give some input to the first
program, and it will terminate [step (3)].

The first program:
----------------------------
#include <fcntl.h>

#include <sys/types.h>
#include <sys/stat.h>

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

#include <stdio.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

char *filename = "testfile";

int main() {

  int hdl;
  int filesize;
  char *mapedfile;
  struct stat filestat; 

  hdl = open(filename,O_RDONLY);
  if (hdl < 0) {
    perror("Cannot open file");
    exit (1);
  }

  if (fstat(hdl,&filestat) == -1) {
    perror("Cannot get file status");
    exit (1);
  };
  
  filesize = filestat.st_size;

  printf("filename: %s\nfilesize: %d\n",filename,filesize);

  mapedfile = (char *)mmap((caddr_t)0, filesize, PROT_READ, MAP_PRIVATE, hdl, 0); 
  if (mapedfile == MAP_FAILED) {
    perror("Cannot map file");
    exit (1);
  }
  
  write(1,mapedfile,filesize);

  getchar();

  if (munmap(mapedfile, filesize) == -1) {
    perror("Cannot unmap file");
    exit (1);
  }

  close (hdl);
  exit (0);
}
------------------------------ 

The second program:
-----------------------------
#include <fcntl.h>

#include <sys/types.h>
#include <sys/stat.h>

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

#include <stdio.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#define TAIL 256

char *filename = "testfile";

int main() {

  int hdl;
  int filesize, newfilesize;
  char *mapedfile;
  struct stat filestat; 

  hdl = open(filename,O_RDWR);
  if (hdl < 0) {
    perror("Cannot open file");
    exit (1);
  }

  if (fstat(hdl,&filestat) == -1) {
    perror("Cannot get file status");
    exit (1);
  };
  
  filesize    = filestat.st_size;
  newfilesize = filesize + TAIL;

  printf("filename: %s\nfilesize: %d\nnewfilesize: %d\n",filename,filesize,newfilesize);

  if (ftruncate(hdl,newfilesize) == -1) {
    perror("Cannot extend a file");
    exit (1);
  }
  
  mapedfile = (char *)mmap((caddr_t)0, newfilesize, PROT_READ|PROT_WRITE, MAP_SHARED, hdl, 0); 
  if (mapedfile == MAP_FAILED) {
    perror("Cannot map file");
    exit (1);
  }
  
  memset(mapedfile+filesize,'X',TAIL);

  if (munmap(mapedfile, newfilesize) == -1) {
    perror("Cannot unmap file");
    exit (1);
  }

  close (hdl);
  exit (0);
}
---------------------------------
Comment 1 silby freebsd_committer freebsd_triage 2002-01-09 01:59:13 UTC
Responsible Changed
From-To: freebsd-bugs->dillon

Over to Mr. NFS, Dillon
Comment 2 Giorgos Keramidas freebsd_committer freebsd_triage 2003-02-23 02:15:39 UTC
Responsible Changed
From-To: dillon->freebsd-bugs

Back to the free pool.
Comment 3 K. Macy freebsd_committer freebsd_triage 2007-11-16 18:28:07 UTC
State Changed
From-To: open->feedback


This sounds like a bug fsx would catch. Are you still seeing this?
Comment 4 K. Macy freebsd_committer freebsd_triage 2007-11-16 18:29:40 UTC
State Changed
From-To: feedback->closed


This hasn't been seen recently and submitter mail bounces.