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
main(void)37 int 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