Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Aug 2001 15:14:34 -0700 (PDT)
From:      Kachun Lee <kachun@pathlink.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/29421: Update a file with mmap will cause mtime/ctime changing repeately
Message-ID:  <200108032214.f73MEYU92653@freefall.freebsd.org>

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

>Number:         29421
>Category:       kern
>Synopsis:       Update a file with mmap will cause mtime/ctime changing repeately
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 03 15:20:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Kachun Lee
>Release:        4.2-stable, 4.3-stable
>Organization:
Pathlink Technology
>Environment:
FreeBSD lily.pathlink.com 4.3-STABLE FreeBSD 4.3-STABLE #0: Thu Jul 12 13:55:01 PDT 2001     root@lisa.pathlink.com:/n/obj/n/src.bsd.4.3-releng/src/sys/DVL  i386
>Description:
One of my program that used mtime to detect file changes and updated
an index file using mmap stopped working after 4.2-release. I finally
narrowed it down to that the mmap updates would cause the mtime to
change continously (not delay) even after the file was closed,
unmmap'ed and had no more writing to it. 

I used a small program to create a 16 byte file, mmap it, change few
bytes, close and unmmap the file. Then I used a perl script to poll
the mtime every minute. I tried this on over 12 of our FreeBSD servers.
All the stable after 4.2-release would exhibit this problem.
The 1 4.1.1-stable and 3 4.2-release servers did not have the problem.

An example run with 4.3-stable...

# ./mmapmtime # C program - source include
# ll mmaptest.f
-rw-r--r--  1 root  wheel  16 Aug  3 13:44 mmaptest.f
# ./chkmtime  # perl script - source included
Fri Aug  3 13:44:47 2001
  mtime = Fri Aug  3 13:44:41 2001
  ctime = Fri Aug  3 13:44:41 2001
Fri Aug  3 13:46:47 2001
  mtime = Fri Aug  3 13:45:58 2001
  ctime = Fri Aug  3 13:45:58 2001
Fri Aug  3 13:47:47 2001
  mtime = Fri Aug  3 13:47:17 2001
  ctime = Fri Aug  3 13:47:17 2001
Fri Aug  3 13:48:47 2001
  mtime = Fri Aug  3 13:48:40 2001
  ctime = Fri Aug  3 13:48:40 2001
Fri Aug  3 13:50:47 2001
  mtime = Fri Aug  3 13:50:44 2001
  ctime = Fri Aug  3 13:50:44 2001
Fri Aug  3 13:52:47 2001
  mtime = Fri Aug  3 13:52:38 2001
  ctime = Fri Aug  3 13:52:38 2001
# this would go forever... mtime/ctime changed every 1-2 minutes 

The time between changes could be a few minutes to a few hours (!).
That seems depended on how busy the system was. I built an idle system
and ran the test on it a few days ago. The mtime/ctime of the test
file on that system has not been changed (yet?).

>How-To-Repeat:
/* mmapmtime.c */

#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int debug = 0;
int wait = 0;

void usage (char * prog)
{
        printf("usage: %s [-d]\n", prog);
}

const char testfile [] = "mmaptest.f";

int
main (int argc, char** argv)
{
        char *prog = argv[0];
        int i;
        int fd;
        char* shm;
        struct stat st;
        size_t size;
        int * idx;

        char data [] = {0x64, 0x0f, 0, 0, 0xfa, 0xff, 0xff, 0xff,
                         0xa3, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };


        while ( (i = getopt(argc, argv, "dt:")) != -1 ) {
                switch (i)
                {
                case 'd':
                        debug++;
                        break;

                case 't':
                        wait = atoi(optarg);
                        break;

                default:
                        usage(prog);
                        exit(1);
                }
        }

        unlink(testfile);

        if ( (fd = open(testfile, O_CREAT|O_RDWR, 0644)) == -1 ) {
                perror("open");
                exit(1);
        }

        write(fd, data, sizeof(data));

        if ( fstat(fd, &st) ) {
                perror("stat");
                exit(1);
        }

        size = st.st_size;

        if ( (shm = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0))
                  == (void*) -1 ) {
                perror("mmap");
                exit(1);
        }

        idx = (int *) shm;
        idx[1] = 0x118;
        idx[2] = 0xffffef84;
        idx[3] = 0;

        if (wait)
                sleep(wait);

        munmap(shm, size);

        //
#if 0
        if ( (shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0))
                  == (void*) -1 ) {
                perror("mmap");
                exit(1);
        }

        idx = (int *) shm;
        printf ("%x %x\n", idx[0], idx[1]);

        munmap(shm, size);
#endif

        close(fd);
        exit(1);
}
------------------
#! /usr/bin/perl
# chkmtime

my $file = "mmaptest.f";

my ($ctime, $mtime);

for(;;)
{
        my @stat = stat $file;

        if ($stat[1] <= 0)
        {
                print 'Cannot stat file ', $file, "\n";
                exit 1;
        }

        if ($stat[9] != $mtime || $stat[10] != $ctime)
        {
                print scalar localtime, "\n",
                        '  mtime = ', scalar localtime($stat[9]), "\n",
                        '  ctime = ', scalar localtime($stat[10]), "\n";
                $mtime = $stat[9];
                $ctime = $stat[10];
        }

        sleep(60);
}
>Fix:

>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?200108032214.f73MEYU92653>