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