Messages in this thread | | | Date | Mon, 14 Jan 2008 15:25:44 +0300 | From | "Anton Salikhmetov" <> | Subject | Re: [PATCH 2/2] updating ctime and mtime at syncing |
| |
2008/1/14, Miklos Szeredi <miklos@szeredi.hu>: > > > 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.
Thank you very much for sharing your code.
I'll integrate the MS_ASYNC and fork() test cases into my own unit test.
> > 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; > } > > >
| |