1/* 2 * Copyright (c) 2002, Intel Corporation. All rights reserved. 3 * Copyright (c) 2012, Cyril Hrubis <chrubis@suse.cz> 4 * 5 * This file is licensed under the GPL license. For the full content 6 * of this license, see the COPYING file at the top level of this 7 * source tree. 8 * 9 * The st_atime field of the mapped file may be marked for update 10 * at any time between the mmap() call and the corresponding munmap() 11 * call. The initial read or write reference to a mapped region 12 * shall cause the file st_atime field to be marked for update if 13 * it has not already been marked for update. 14 * 15 * Test Steps: 16 * 1. Do stat before mmap() and after munmap(), 17 * also after writing the mapped region. 18 * 2. Compare whether st_atime has been updated. 19 */ 20 21#define _XOPEN_SOURCE 600 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <unistd.h> 26#include <sys/mman.h> 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <sys/wait.h> 30#include <fcntl.h> 31#include <string.h> 32#include <errno.h> 33#include <time.h> 34#include "noatime.h" 35#include "posixtest.h" 36 37int main(void) 38{ 39 char tmpfname[256]; 40 ssize_t size = 1024; 41 char data[size]; 42 void *pa; 43 int fd; 44 45 struct stat stat_buff, stat_buff2; 46 time_t atime1, atime2, atime3; 47 48 char *ch; 49 50 if (mounted_noatime("/tmp") == 1) { 51 printf("UNTESTED: The /tmp is mounted noatime\n"); 52 return PTS_UNTESTED; 53 } 54 55 snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_mmap_13_1_%d", getpid()); 56 unlink(tmpfname); 57 fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR); 58 if (fd == -1) { 59 printf("Error at open(): %s\n", strerror(errno)); 60 return PTS_UNRESOLVED; 61 } 62 63 memset(data, 'a', size); 64 printf("Time before write(): %ld\n", time(NULL)); 65 if (write(fd, data, size) != size) { 66 printf("Error at write(): %s\n", strerror(errno)); 67 unlink(tmpfname); 68 return PTS_UNRESOLVED; 69 } 70 71 if (stat(tmpfname, &stat_buff) == -1) { 72 printf("Error at 1st stat(): %s\n", strerror(errno)); 73 unlink(tmpfname); 74 return PTS_UNRESOLVED; 75 } 76 /* atime1: write */ 77 atime1 = stat_buff.st_atime; 78 79 sleep(1); 80 81 printf("Time before mmap(): %ld\n", time(NULL)); 82 pa = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 83 if (pa == MAP_FAILED) { 84 printf("Error at mmap: %s\n", strerror(errno)); 85 unlink(tmpfname); 86 return PTS_FAIL; 87 } 88 89 if (stat(tmpfname, &stat_buff2) == -1) { 90 printf("Error at 2nd stat(): %s\n", strerror(errno)); 91 unlink(tmpfname); 92 return PTS_UNRESOLVED; 93 } 94 /* for mmap */ 95 atime2 = stat_buff2.st_atime; 96 97 /* Wait a while in case the precision of the sa_time 98 * is not acurate enough to reflect the change 99 */ 100 sleep(1); 101 102 /* write reference to mapped memory */ 103 ch = pa; 104 *ch = 'b'; 105 106 printf("Time before munmap(): %ld\n", time(NULL)); 107 munmap(pa, size); 108 109 /* FIXME: Update the in-core meta data to the disk */ 110 fsync(fd); 111 close(fd); 112 if (stat(tmpfname, &stat_buff) == -1) { 113 printf("Error at 3rd stat(): %s\n", strerror(errno)); 114 unlink(tmpfname); 115 return PTS_UNRESOLVED; 116 } 117 /* atime3: write to memory */ 118 atime3 = stat_buff.st_atime; 119 120 printf("atime1: %d, atime2: %d, atime3: %d\n", 121 (int)atime1, (int)atime2, (int)atime3); 122 if (atime1 != atime3 || atime1 != atime2) { 123 printf("Test PASSED\n"); 124 unlink(tmpfname); 125 return PTS_PASS; 126 } 127 128 printf("Test FAILED: st_atime was not updated properly\n"); 129 unlink(tmpfname); 130 return PTS_FAIL; 131} 132