blob: 86b99486167a920a22a87f4c5a4c3d526fbecb34 [file] [log] [blame]
subrata_modakc79a92d2009-04-02 06:50:45 +00001/******************************************************************************/
2/* */
3/* Copyright (s) Ying Han <yinghan@google.com>, 2009 */
4/* */
5/* This program is free software; you can redistribute it and/or modify */
6/* it under the terms of the GNU General Public License as published by */
7/* the Free Software Foundation; either version 2 of the License, or */
8/* (at your option) any later version. */
9/* */
10/* This program is distributed in the hope that it will be useful, */
11/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
13/* the GNU General Public License for more details. */
14/* */
15/* You should have received a copy of the GNU General Public License */
16/* along with this program; if not, write to the Free Software */
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
subrata_modakc79a92d2009-04-02 06:50:45 +000018/* */
19/******************************************************************************/
20/*
21 ftruncate-mmap: pages are lost after writing to mmaped file,
22
23 We triggered the failure during some internal experiment with
24 ftruncate/mmap/write/read sequence. And we found that some pages are
25 "lost" after writing to the mmaped file. which in the following test
26 cases (count >= 0).
Garrett Cooper2c282152010-12-16 00:55:50 -080027
subrata_modakc79a92d2009-04-02 06:50:45 +000028 First we deployed the test cases into group of machines and see about
29 >20% failure rate on average. Then, I did couple of experiment to try
30 to reproduce it on a single machine. what i found is that:
31 1. add a fsync after write the file, i can not reproduce this issue.
32 2. add memory pressure(mmap/mlock) while run the test in infinite
33 loop, the failure is reproduced quickly. ( background flushing ? )
Garrett Cooper2c282152010-12-16 00:55:50 -080034
subrata_modakc79a92d2009-04-02 06:50:45 +000035 The "bad pages" count differs each time from one digit to 4,5 digit
36 for 128M ftruncated file. and what i also found that the bad page
37 number are contiguous for each segment which total bad pages container
38 several segments. ext "1-4, 9-20, 48-50" ( batch flushing ? )
Garrett Cooper2c282152010-12-16 00:55:50 -080039
subrata_modakc79a92d2009-04-02 06:50:45 +000040 (The failure is reproduced based on 2.6.29-rc8, also happened on
41 2.6.18 kernel. . Here is the simple test case to reproduce it with
42 memory pressure. )
43*/
44
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <fcntl.h>
48#include <unistd.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <signal.h>
53
subrata_modakc79a92d2009-04-02 06:50:45 +000054#include "test.h"
subrata_modakc79a92d2009-04-02 06:50:45 +000055
56/* Extern Global Variables */
Caspar Zhangd59a6592013-03-07 14:59:12 +080057extern int tst_count;
subrata_modakc79a92d2009-04-02 06:50:45 +000058
59/* Global Variables */
Wanlong Gao354ebb42012-12-07 10:10:04 +080060char *TCID = "mmap-corruption01"; /* test program identifier. */
61int TST_TOTAL = 1; /* total number of tests in this file. */
subrata_modakc79a92d2009-04-02 06:50:45 +000062
Wanlong Gao354ebb42012-12-07 10:10:04 +080063long kMemSize = 128 << 20;
subrata_modakc79a92d2009-04-02 06:50:45 +000064int kPageSize = 4096;
65
Wanlong Gao354ebb42012-12-07 10:10:04 +080066char *usage = "-h hours -m minutes -s secs\n";
subrata_modakc79a92d2009-04-02 06:50:45 +000067
68int anyfail()
69{
Cyril Hrubis9fa8ad02014-12-16 13:20:49 +010070 tst_brkm(TFAIL, tst_rmdir, "Test failed\n");
subrata_modakc79a92d2009-04-02 06:50:45 +000071}
72
Wanlong Gao354ebb42012-12-07 10:10:04 +080073int main(int argc, char **argv)
74{
75 char *progname;
76 int status;
77 int count = 0;
78 int i, c;
79 char *fname = "test.mmap-corruption";
80 char *mem;
81 unsigned long alarmtime = 0;
82 struct sigaction sa;
83 void finish(int sig);
subrata_modakc79a92d2009-04-02 06:50:45 +000084
Wanlong Gao354ebb42012-12-07 10:10:04 +080085 progname = *argv;
86 while ((c = getopt(argc, argv, ":h:m:s:")) != -1) {
87 switch (c) {
88 case 'h':
89 alarmtime += atoi(optarg) * 60 * 60;
90 break;
91 case 'm':
92 alarmtime += atoi(optarg) * 60;
93 break;
94 case 's':
95 alarmtime += atoi(optarg);
96 break;
97 default:
98 (void)fprintf(stderr, "usage: %s %s\n", progname,
99 usage);
100 anyfail();
101 }
102 }
subrata_modakc79a92d2009-04-02 06:50:45 +0000103
Wanlong Gao354ebb42012-12-07 10:10:04 +0800104 /*
105 * Plan for death by signal. User may have specified
106 * a time limit, in which case set an alarm and catch SIGALRM.
107 * Also catch and cleanup with SIGINT, SIGQUIT, and SIGTERM.
108 */
109 sa.sa_handler = finish;
110 sa.sa_flags = 0;
111 if (sigemptyset(&sa.sa_mask)) {
112 perror("sigempty error");
113 exit(1);
114 }
subrata_modakc79a92d2009-04-02 06:50:45 +0000115
Wanlong Gao354ebb42012-12-07 10:10:04 +0800116 if (sigaction(SIGINT, &sa, 0) == -1) {
117 perror("sigaction error SIGINT");
118 exit(1);
119 }
120 if (alarmtime) {
121 if (sigaction(SIGALRM, &sa, 0) == -1) {
122 perror("sigaction error");
123 exit(1);
124 }
125 (void)alarm(alarmtime);
126 printf("mmap-corruption will run for=> %ld, seconds\n",
127 alarmtime);
128 } else { //Run for 5 secs only
129 if (sigaction(SIGALRM, &sa, 0) == -1) {
130 perror("sigaction error");
131 exit(1);
132 }
133 (void)alarm(5);
134 printf("mmap-corruption will run for=> 5, seconds\n");
135 }
136 /* If we get a SIGQUIT or SIGTERM, clean up and exit immediately. */
137 sa.sa_handler = finish;
138 if (sigaction(SIGQUIT, &sa, 0) == -1) {
139 perror("sigaction error SIGQUIT");
140 exit(1);
141 }
142 if (sigaction(SIGTERM, &sa, 0) == -1) {
143 perror("sigaction error SIGTERM");
144 exit(1);
145 }
subrata_modakc79a92d2009-04-02 06:50:45 +0000146
Wanlong Gao354ebb42012-12-07 10:10:04 +0800147 tst_tmpdir();
148 while (1) {
149 unlink(fname);
150 int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0600);
151 status = ftruncate(fd, kMemSize);
subrata_modakc79a92d2009-04-02 06:50:45 +0000152
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 mem =
154 mmap(0, kMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
155 0);
156 // Fill the memory with 1s.
157 memset(mem, 1, kMemSize);
subrata_modakc79a92d2009-04-02 06:50:45 +0000158
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 for (i = 0; i < kMemSize; i++) {
160 int byte_good = mem[i] != 0;
161 if (!byte_good && ((i % kPageSize) == 0)) {
162 //printf("%d ", i / kPageSize);
163 count++;
164 }
165 }
166 munmap(mem, kMemSize);
167 close(fd);
168 unlink(fname);
169 if (count > 0) {
170 printf("Running %d bad page\n", count);
171 return 1;
172 }
173 count = 0;
174 }
175 return 0;
subrata_modakc79a92d2009-04-02 06:50:45 +0000176}
177
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178void finish(int sig)
179{
180 printf("mmap-corruption PASSED\n");
181 exit(0);
Chris Dearmanec6edca2012-10-17 19:54:01 -0700182}