TDB on OpenBSD problem.

MCCALL,DON (HP-USA,ex1) don_mccall at hp.com
Fri May 4 17:59:31 GMT 2001


Hi Tridge,
I'm no programmer, and my understanding of mmapped files is slim, but I
noted in the man page of mmap, after a discussion with one of my HP-UX
buddies about buffercache vs page cache on HP-UX:

 The application must ensure correct synchronization when using mmap()
      in conjunction with any other file access method, such as read() and
      write(), standard input/output, and shmat().

So I added a call to msync() right before the call to test() to the test
program, and with this I resolve the inconsistency on the 11.0 box I was
seeing the error on.  Follows is the modified code:
*************************************************************************

/*
  trivial test program to see if file IO and mmap are coherent.
  tridge at samba.org, May 2001
*/

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>

#define SIZE 20000

static void test(char *map, int fd, int line)
{
        unsigned char buf1[SIZE], buf2[SIZE];

        memcpy(buf1, map, SIZE);
        lseek(fd, 0, SEEK_SET);
       read(fd, buf2, SIZE);
        if (memcmp(buf1, buf2, SIZE) != 0) {
                int i;
                for (i=0;i<SIZE;i++) {
                        if (buf1[i] != buf2[i]) {
                                printf("mismatch at %d (%d %d)\n",
                                       i, buf1[i], buf2[i]);
                        }
                }
                printf("not equal on line %d!\n", line);
                exit(1);
        }
}

#ifndef MAP_FILE
#define MAP_FILE 0
#endif

int main(void)
{
        int fd;
        char *map;
        char b = 0;

                printf("Program started\n");
        fd = open("test.dat", O_RDWR|O_CREAT|O_TRUNC, 0600);

        lseek(fd, SIZE-1, SEEK_SET);
        write(fd, &b, 1);

        map = mmap(NULL,SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_FILE, fd,
0);

        map[3000] = 17;
        if (fdatasync(fd) != 0)
        printf("fsync failed!\n");
        if (msync(map,SIZE,MS_SYNC) != 0)
        printf("msync failed!\n");
        test(map, fd, __LINE__);

        lseek(fd, 76, SEEK_SET);
        write(fd, &fd, sizeof(fd));

        test(map, fd, __LINE__);

                printf("Program ended\n");
        return 0;
}

****************************************************************

Does this make sense to you, or are we defeating the purpose?


Hope this helps,
Don
 "Reason, not volume, is the primary
differentiator between a discussion, and an
argument."

-----Original Message-----
From: tridge at samba.org [mailto:tridge at samba.org]
Sent: Friday, May 04, 2001 9:39 AM
To: jeremy at valinux.com; vmn at bom.gov.AU; samba-technical at lists.samba.org
Subject: Re: TDB on OpenBSD problem.


> I think I've just reproduced it using tdbtorture on a OpenBSD vmware
> session. I'm looking into it.

I now have a tiny test program that shows the basic problem. It seems
that on OpenBSD mmap and read are not coherent. I've written to Theo
to ask him about it.

Can those of you seeing the tdb expansion bug please try the following
test program and see if it reports an error.

btw, I think we could make tdb not rely on mmap/read coherence, but
I'd rather first understand whats going on. 

Cheers, Tridge


/*
  trivial test program to see if file IO and mmap are coherent. 
  tridge at samba.org, May 2001
*/

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>

#define SIZE 20000

static void test(char *map, int fd, int line)
{
	unsigned char buf1[SIZE], buf2[SIZE];

	memcpy(buf1, map, SIZE);
	lseek(fd, 0, SEEK_SET);
	read(fd, buf2, SIZE);
	if (memcmp(buf1, buf2, SIZE) != 0) {
		int i;
		for (i=0;i<SIZE;i++) {
			if (buf1[i] != buf2[i]) {
				printf("mismatch at %d (%d %d)\n",
				       i, buf1[i], buf2[i]);
			}
		}
		printf("not equal on line %d!\n", line);
		exit(1);
	}
}

#ifndef MAP_FILE
#define MAP_FILE 0
#endif

int main(void)
{
	int fd;
	char *map;
	char b = 0;

	fd = open("test.dat", O_RDWR|O_CREAT|O_TRUNC, 0600);

	lseek(fd, SIZE-1, SEEK_SET);
	write(fd, &b, 1);

	map = mmap(NULL,SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_FILE, fd,
0);

	map[3000] = 17;
	fsync(fd);
	test(map, fd, __LINE__);

	lseek(fd, 76, SEEK_SET);
	write(fd, &fd, sizeof(fd));
	
	test(map, fd, __LINE__);
	return 0;
}




More information about the samba-technical mailing list