Messages in this thread | | | Subject | Re: [PATCH 2/2] updating ctime and mtime at syncing | From | Miklos Szeredi <> | Date | Mon, 14 Jan 2008 12:15:15 +0100 |
| |
> > http://bugzilla.kernel.org/show_bug.cgi?id=2645 > > > > Changes for updating the ctime and mtime fields for memory-mapped files: > > > > 1) new flag triggering update of the inode data; > > 2) new function to update ctime and mtime for block device files; > > 3) new helper function to update ctime and mtime when needed; > > 4) updating time stamps for mapped files in sys_msync() and do_fsync(); > > 5) implementing the feature of auto-updating ctime and mtime. > > How exactly is this done? > > Is this catering for this case: > > 1 page is dirtied through mapping > 2 app calls msync(MS_ASYNC) > 3 page is written again through mapping > 4 app calls msync(MS_ASYNC) > 5 ... > 6 page is written back > > What happens at 4? Do we care about this one at all?
Oh, and here's a test program I wrote, that can be used to check this behavior. It has two options:
-s use MS_SYNC instead of MS_ASYNC -f fork and do the msync on a different mapping
Back then I haven't found a single OS, that fully conformed to all the stupid POSIX rules regarding mmaps and ctime/mtime.
Miklos ----
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/wait.h>
static const char *filename; static int msync_flag = MS_ASYNC; static int msync_fork = 0;
static void print_times(const char *msg) { struct stat stbuf; stat(filename, &stbuf); printf("%s\t%li\t%li\t%li\n", msg, stbuf.st_ctime, stbuf.st_mtime, stbuf.st_atime); }
static void do_msync(void *addr, int len) { int res; if (!msync_fork) { res = msync(addr, len, msync_flag); if (res == -1) { perror("msync"); exit(1); } } else { int pid = fork(); if (pid == -1) { perror("fork"); exit(1); } if (!pid) { int fd = open(filename, O_RDWR); if (fd == -1) { perror("open"); exit(1); } addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { perror("mmap"); exit(1); } res = msync(addr, len, msync_flag); if (res == -1) { perror("msync"); exit(1); } exit(0); } wait(NULL); } }
static void usage(const char *progname) { fprintf(stderr, "usage: %s filename [-sf]\n", progname); exit(1); }
int main(int argc, char *argv[]) { int res; char *addr; int fd;
if (argc < 2) usage(argv[0]);
filename = argv[1]; if (argc > 2) { if (argc > 3) usage(argv[0]); if (strcmp(argv[2], "-s") == 0) msync_flag = MS_SYNC; else if (strcmp(argv[2], "-f") == 0) msync_fork = 1; else if (strcmp(argv[2], "-sf") == 0 || strcmp(argv[2], "-fs") == 0) { msync_flag = MS_SYNC; msync_fork = 1; } else usage(argv[0]); }
fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, 0666); if (fd == -1) { perror(filename); return 1; } print_times("begin"); sleep(1); write(fd, "aaaa\n", 4); print_times("write"); sleep(1); addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { perror("mmap"); return 1; } print_times("mmap"); sleep(1);
addr[1] = 'b'; print_times("b"); sleep(1); do_msync(addr, 4); print_times("msync b"); sleep(1);
addr[2] = 'c'; print_times("c"); sleep(1); do_msync(addr, 4); print_times("msync c"); sleep(1);
addr[3] = 'd'; print_times("d"); sleep(1); res = munmap(addr, 4); if (res == -1) { perror("munmap"); return 1; } print_times("munmap"); sleep(1);
res = close(fd); if (res == -1) { perror("close"); return 1; } print_times("close"); sleep(1); sync(); print_times("sync");
return 0; }
| |