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
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/wait.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <time.h>
33
34 #include "noatime.h"
35 #include "posixtest.h"
36 #include "tempfile.h"
37
main(void)38 int main(void)
39 {
40 char tmpfname[PATH_MAX];
41 ssize_t size = 1024;
42 char data[size];
43 void *pa;
44 int fd;
45
46 struct stat stat_buff, stat_buff2;
47 time_t atime1, atime2, atime3;
48
49 char *ch;
50
51 PTS_GET_TMP_FILENAME(tmpfname, "pts_mmap_13_1");
52 if (mounted_noatime(pts_get_tmpdir()) == 1) {
53 printf("UNTESTED: The tmpdir is mounted noatime\n");
54 return PTS_UNTESTED;
55 }
56
57 unlink(tmpfname);
58 fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
59 if (fd == -1) {
60 printf("Error at open(): %s\n", strerror(errno));
61 return PTS_UNRESOLVED;
62 }
63
64 memset(data, 'a', size);
65 printf("Time before write(): %ld\n", time(NULL));
66 if (write(fd, data, size) != size) {
67 printf("Error at write(): %s\n", strerror(errno));
68 unlink(tmpfname);
69 return PTS_UNRESOLVED;
70 }
71
72 if (stat(tmpfname, &stat_buff) == -1) {
73 printf("Error at 1st stat(): %s\n", strerror(errno));
74 unlink(tmpfname);
75 return PTS_UNRESOLVED;
76 }
77 /* atime1: write */
78 atime1 = stat_buff.st_atime;
79
80 sleep(1);
81
82 printf("Time before mmap(): %ld\n", time(NULL));
83 pa = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
84 if (pa == MAP_FAILED) {
85 printf("Error at mmap: %s\n", strerror(errno));
86 unlink(tmpfname);
87 return PTS_FAIL;
88 }
89
90 if (stat(tmpfname, &stat_buff2) == -1) {
91 printf("Error at 2nd stat(): %s\n", strerror(errno));
92 unlink(tmpfname);
93 return PTS_UNRESOLVED;
94 }
95 /* for mmap */
96 atime2 = stat_buff2.st_atime;
97
98 /* Wait a while in case the precision of the sa_time
99 * is not acurate enough to reflect the change
100 */
101 sleep(1);
102
103 /* write reference to mapped memory */
104 ch = pa;
105 *ch = 'b';
106
107 printf("Time before munmap(): %ld\n", time(NULL));
108 munmap(pa, size);
109
110 /* FIXME: Update the in-core meta data to the disk */
111 fsync(fd);
112 close(fd);
113 if (stat(tmpfname, &stat_buff) == -1) {
114 printf("Error at 3rd stat(): %s\n", strerror(errno));
115 unlink(tmpfname);
116 return PTS_UNRESOLVED;
117 }
118 /* atime3: write to memory */
119 atime3 = stat_buff.st_atime;
120
121 printf("atime1: %d, atime2: %d, atime3: %d\n",
122 (int)atime1, (int)atime2, (int)atime3);
123 if (atime1 != atime3 || atime1 != atime2) {
124 printf("Test PASSED\n");
125 unlink(tmpfname);
126 return PTS_PASS;
127 }
128
129 printf("Test FAILED: st_atime was not updated properly\n");
130 unlink(tmpfname);
131 return PTS_FAIL;
132 }
133