Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Sep 2000 17:05:39 +0400
From:      kmv@express.ru
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/21222: wrong behavior of concurrent mmap()s on NFS files
Message-ID:  <E13Ypkp-000NHB-00@mv.kmost.express.ru>

next in thread | raw e-mail | index | archive | help

>Number:         21222
>Category:       kern
>Synopsis:       wrong behavior of concurrent mmap()s on NFS files
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 12 06:10:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Maxim Katargin
>Release:        FreeBSD 4.0-RELEASE i386
>Organization:
>Environment:

    client  : FreeBSD 4.0-RELEASE i386,
    servers : 3.5-STABLE FreeBSD i386, 4.0-STABLE FreeBSD i386

	

>Description:

    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.

>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);
}
---------------------------------

>Fix:

	
    Unknown.


>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E13Ypkp-000NHB-00>