Subject: kern/30811: mmap (?) regression
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <j+nbsd@2005.salmi.ch>
List: netbsd-bugs
Date: 07/22/2005 11:34:00
>Number:         30811
>Category:       kern
>Synopsis:       mmap (?) regression
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jul 22 11:34:00 +0000 2005
>Originator:     Jukka Salmi
>Release:        NetBSD 3.99.7
>Environment:
System: NetBSD moray.salmi.ch 3.99.7 NetBSD 3.99.7 (GENERIC) #0: Fri Jul 22 12:32:24 CEST 2005 jukka@moray.salmi.ch:/opt/temp/jukka/GENERIC i386
Architecture: i386
Machine: i386
>Description:

While building graphics/ImageMagick from pkgsrc on a i386 system I noticed
a problem which I traced it down to the following:

Executing the attached program on a null-mounted filesystem hangs forever.
Executing it on a non-null-mounted filesystem succeeds.

This problem was introduced by this commit:
http://mail-index.netbsd.org/source-changes/2005/07/17/0015.html

>How-To-Repeat:

Execute the attached program on null-mounted and non-null-mounted
filesystems:

$ mount
[...]  
/dev/ccd0a on /ffs type ffs (local)
/ffs on /null type null (local)

Executing it on the ffs works fine:

$ cd /ffs
$ ./a.out
$ echo $?
0

But executing it on the (same but) null-mounted filesystem takes forever:

$ cd /null
$ ./a.out
^C
$ echo $?
130

>Fix:
Unknown.

Workaround: after reverting the four files from the commit posted above
the problem was gone. Diff()ed ident output from the two kernels:

$ diff working non-working | grep '^[<>]'
<      $NetBSD: genfs_vnops.c,v 1.100 2005/07/17 09:13:35 yamt Exp $
>      $NetBSD: genfs_vnops.c,v 1.102 2005/07/17 16:07:19 yamt Exp $
<      $NetBSD: uvm_fault.c,v 1.95 2005/06/27 02:19:48 thorpej Exp $
>      $NetBSD: uvm_fault.c,v 1.96 2005/07/17 12:27:47 yamt Exp $

--- cut here ---

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stddef.h>
#include <memory.h>
#include <string.h>
#include <strings.h>
#include <inttypes.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

int
main ()
{
  char *data, *data2, *data3;
  int i, pagesize;
  int fd;

  pagesize = getpagesize ();

  /* First, make a file with some known garbage in it. */
  data = (char *) malloc (pagesize);
  if (!data)
    exit (1);
  for (i = 0; i < pagesize; ++i)
    *(data + i) = rand ();
  umask (0);
  fd = creat ("conftest.mmap", 0600);
  if (fd < 0)
    exit (1);
  if (write (fd, data, pagesize) != pagesize)
    exit (1);
  close (fd);

  /* Mmap the file as read/write/shared and verify that we see the
  same garbage. */
  fd = open ("conftest.mmap", O_RDWR);
  if (fd < 0)
    exit (1);
  data2 = mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
  if (data2 == 0)
    exit (1);
  for (i = 0; i < pagesize; ++i)
    if (*(data + i) != *(data2 + i))
      exit (1);

  /* Finally, make sure that changes to the mapped area
     percolate back to the file as seen by read().  */
  for (i = 0; i < pagesize; ++i)
    *(data2 + i) = *(data2 + i) + 1;
  data3 = (char *) malloc (pagesize);
  if (!data3)
    exit (1);
  if (read (fd, data3, pagesize) != pagesize)
    exit (1);
  for (i = 0; i < pagesize; ++i)
    if (*(data2 + i) != *(data3 + i))
      exit (1);
  close (fd);
  exit (0);
}