> Peter Dufault <[EMAIL PROTECTED]> writes:
> > > > Do an msync with MS_SYNC someplace.  Also, use MAP_NOSYNC in
> > > > mmap until 4.3 when Matt Dillon plans to make that the default behavior.
> > > Ahh, no.  That's the other way around - I do not *want* it to hit the
> > > disk, but would like to *know* when it nevertheless does.
> > OK, doing a stat and checking the mtime should give you
> > the info at the expense of polling, I can't think of another way.
> 
> Won't help. You'll get the same mtime no matter whether the file is
> actually written to disk or not.

No, the spec says:

If there was no such call [to msync] these fields [st_ctime and
st_mtime] may be marked for update at any time after a write
reference if the underlying file is modified as a result.

I wrote a program (attached) to verify it.  Here's the output:

>   mapped at 08:34:04.206204 modification time 08:34:04.000000000
> modified at 08:34:05.210740 modification time 08:34:04.000000000
> unmapped at 08:34:06.220744 modification time 08:34:04.000000000
> remapped at 08:34:07.230750 modification time 08:34:04.000000000
>    msync at 08:34:08.247007 modification time 08:34:08.000000000


Peter

--
Peter Dufault ([EMAIL PROTECTED])   Realtime development, Machine control,
HD Associates, Inc.               Fail-Safe systems, Agency approval
#include <unistd.h>

#include <sys/mman.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef MAP_NOSYNC
#define MAP_NOSYNC 0
#endif

static const char *name = "mapped_file";

static void
put_tv(FILE *f, struct timeval *pTv) {
        struct tm tm;
        struct timeval tv;

        if (pTv == 0) {
                gettimeofday(&tv, 0);
                pTv = &tv;
        }

        localtime_r(&pTv->tv_sec, &tm);

        fprintf(f, "%02d:%02d:%02d.%06ld",
        tm.tm_hour, tm.tm_min, tm.tm_sec, pTv->tv_usec);
}

static void
put_ts(FILE *f, struct timespec *pTs) {
        struct tm tm;

        localtime_r(&pTs->tv_sec, &tm);

        fprintf(f, "%02d:%02d:%02d.%09ld",
        tm.tm_hour, tm.tm_min, tm.tm_sec, pTs->tv_nsec);
}


static void quit_if(long code, long value, const char *s)
{
        if (code == value) {
                perror(s);
                exit(1);
        }
}

static void
status(FILE *f, const char *p, const int fd)
{
        struct stat st;

        fstat(fd, &st);

        fprintf(f, "%12s ", p);
        put_tv(f, 0);
        fprintf(f, " modification time ");
        put_ts(f, &st.st_mtimespec);

        putchar('\n');
}

int main(int ac, char *av[]) {
        void *p;
        long pagesize;
        int i, fd;
        void *buff;

        pagesize = sysconf(_SC_PAGESIZE);

        (void)unlink(name);

        errno = 0;
        quit_if((fd = open(name, O_RDWR|O_CREAT, 0666)), -1, "open");

        buff = calloc(1, pagesize);

        quit_if((long)(p = mmap(0, 10*pagesize,
                PROT_READ|PROT_WRITE, MAP_NOSYNC|MAP_SHARED, fd, (off_t)0)),
                (long)MAP_FAILED, "mmap");



        for (i = 0; i < 10; i++) {
                write(fd, buff, pagesize);
        }

        status(stdout, "mapped at", fd);

        sleep(1);

        *(long *)p = -1;

        status(stdout, "modified at", fd);

        sleep(1);

        munmap(p, 10*pagesize);
        status(stdout, "unmapped at", fd);

        sleep(1);

        quit_if((long)(p = mmap(0, 10*pagesize,
                PROT_READ|PROT_WRITE, MAP_NOSYNC|MAP_SHARED, fd, (off_t)0)),
                (long)MAP_FAILED, "mmap");

        status(stdout, "remapped at", fd);

        sleep(1);

        quit_if(msync(p, 10*pagesize, MS_SYNC), -1, "msync");

        status(stdout, "msync at", fd);

        close(fd);
        return 0;
}

Reply via email to