Bug 24886

Summary: Cant msync memory mapped file onto desk.
Product: Base System Reporter: ikqumei <ikqumei>
Component: i386Assignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description ikqumei 2001-02-06 00:00:01 UTC
I wrote a simple program to demonstrate the problem.  Basically, I use mmap to exchange information between files. After this is done, I try to msync the information back to desk.  The new information does not seem to be saved. The return value from msync is 0, and no error registed through errno.

I used simple text files with this program.

< source code begin >
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>

bool ResizeFile( int fd, int new_sz  );

int main()
{

	int hOldFile=0, hNewFile=0;
	char *ofbuf=NULL, *nfbuf=NULL;
	long new_sz=155, ofsz=133;
	char *ofile="oldf.txt";
	char *nfile="newf.txt";

	hOldFile = open( ofile, O_RDWR );
	hNewFile = open( nfile, O_RDWR );

	if( hOldFile )
		ofbuf = (char*)mmap(NULL, ofsz, PROT_READ|PROT_WRITE, /*MAP_DENYWRITE*/MAP_PRIVATE, hOldFile, 0);

	if ( !ResizeFile( hOldFile, new_sz ) )
	{
	        close(hOldFile);
        	close(hNewFile);
		return 1;
	}

	nfbuf = (char*) mmap(NULL, new_sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, hNewFile, 0);

	for( int i=0; i<new_sz; i++ )
		ofbuf[i] = nfbuf[i];

	if ( msync( ofbuf, /*MPPH.new_sz*/ 0 , MS_SYNC)  )
		perror( "Error msync ofbuf" );
	munmap( ofbuf, new_sz );
	close(hOldFile);

	if( msync( nfbuf, new_sz, MS_SYNC ) )
		perror( "Error msync nfbuf" );
	munmap( nfbuf, new_sz );
	close(hNewFile);
}


bool SetEndOfFile( int fd )
{
	long int new_size;

	new_size = lseek(fd,0L,SEEK_CUR);
	if( -1 ==  new_size )
		return ( -1 );
	
	if ( write( fd, "\0", 1)   <= 0 )
        	return ( -1 );

 	if( ftruncate(fd, new_size) != -1 )
		   return true;
	return false;
}

bool ResizeFile( int fd, int new_sz  )
{
	if ( new_sz != lseek( fd, new_sz, SEEK_SET ) )
        	return false;
	
	if (!SetEndOfFile(fd) )
        	return false;

	if ( 0 != lseek(fd,0,SEEK_SET))
        	return false;

	return true;
}

How-To-Repeat: I used two text files, 
<oldf.txt, 133bytes>
auto testing: 

Functional spec and Software design spec as guide to features testing.

Generator testing:
command line testing.
<newf.txt, 155bytes>
auto testing: 

Functional spec and Software design spec as guide to features testing.

Generator testing:
command line testing.

Just added a line.
Comment 1 Garrett A. Wollman 2001-02-06 00:50:44 UTC
<<On Mon, 5 Feb 2001 15:58:41 -0800 (PST), ikqumei@computer.org said:

> 		ofbuf = (char*)mmap(NULL, ofsz, PROT_READ|PROT_WRITE, /*MAP_DENYWRITE*/MAP_PRIVATE, hOldFile, 0);

You have specified a private memory mapping.  Modifications made to
such mappings are *never* visible anywhere outside that mapping.  Use
MAP_SHARED to create a mapping which modifies globally-visible state.

-GAWollman
Comment 2 Garrett Wollman freebsd_committer freebsd_triage 2001-02-06 00:51:31 UTC
State Changed
From-To: open->closed

Programmer error.
Comment 3 ikqumei 2001-02-07 08:06:13 UTC
Thank you Garrett for the follow-up.  I tried your suggestion and it did
work.  I just wanted to share with you this bit of information.  I have
originally wrote a similar code for redhat linux 6.2, and it works ok.
However, as I went on to port to FreeBSD, I experienced this problem.   The
man pages confirmed to me your response, so I could conclude that FreeBSD is
more strict that Redhat Linux!?

Thanks again,
Iyad Qumei.

----- Original Message -----
From: "Garrett Wollman" <wollman@khavrinen.lcs.mit.edu>
To: <ikqumei@computer.org>
Cc: <freebsd-gnats-submit@FreeBSD.ORG>
Sent: Monday, February 05, 2001 4:50 PM
Subject: i386/24886: Cant msync memory mapped file onto desk.


> <<On Mon, 5 Feb 2001 15:58:41 -0800 (PST), ikqumei@computer.org said:
>
> > ofbuf = (char*)mmap(NULL, ofsz, PROT_READ|PROT_WRITE,
/*MAP_DENYWRITE*/MAP_PRIVATE, hOldFile, 0);
>
> You have specified a private memory mapping.  Modifications made to
> such mappings are *never* visible anywhere outside that mapping.  Use
> MAP_SHARED to create a mapping which modifies globally-visible state.
>
> -GAWollman
>
>
>
Comment 4 Garrett A. Wollman 2001-02-07 16:07:07 UTC
<<On Wed, 7 Feb 2001 00:06:13 -0800, "Iyad Qumei" <ikqumei@computer.org> said:

> The man pages confirmed to me your response, so I could conclude
> that FreeBSD is more strict that Redhat Linux!?

It's possible that you have found a bug in whatever version of the
Linux kernel you were running.  The POSIX standard states:

	If MAP_PRIVATE is specified, modifications to the mapped data
	by the calling process shall be visible only to the calling
	process and shall not change the underlying object.  It is
	unspecified whether modifications to the underlying object
	done after the MAP_PRIVATE mapping is established are visible
	through the MAP_PRIVATE mapping.

FreeBSD implements this behavior as described.

-GAWollman