1 /*
2  *   Copyright (C) 2003,2004 Red Hat, Inc.  All rights reserved.
3  *
4  *   The contents of this file may be used under the terms of the GNU
5  *   General Public License version 2 (the "GPL")
6  *
7  *   Author: Stephen C. Tweedie <sct@redhat.com>
8  *   This program is free software;  you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16  *   the GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program;  if not, write to the Free Software
20  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * Module: .c
23  */
24 
25 /*
26  * Change History:
27  *
28  * 2/2004  Marty Ridgeway (mridge@us.ibm.com) Changes to adapt to LTP
29  *
30  */
31 
32 #define _XOPEN_SOURCE 600
33 #define _GNU_SOURCE
34 #define MAX_ITERATIONS 250
35 
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <sys/mman.h>
43 #include <sys/wait.h>
44 
45 #define BIGSIZE 128*1024*1024
46 #define READSIZE 32*1024*1024
47 #define WRITESIZE 32*1024*1024
48 
49 int pagesize;
50 char *iobuf;
51 int pass = 0;
52 
assert(const char * what,int assertion)53 void assert(const char *what, int assertion)
54 {
55 	if (assertion)
56 		return;
57 	perror(what);
58 	exit(1);
59 }
60 
do_buffered_writes(int fd,int pattern)61 void do_buffered_writes(int fd, int pattern)
62 {
63 	int rc;
64 	int offset;
65 
66 	memset(iobuf, pattern, WRITESIZE);
67 	for (offset = 0; offset + WRITESIZE <= BIGSIZE; offset += WRITESIZE) {
68 		rc = pwrite(fd, iobuf, WRITESIZE, offset);
69 		assert("pwrite", rc >= 0);
70 		if (rc != WRITESIZE) {
71 			fprintf(stderr, "Pass %d: short write (%d out of %d)\n",
72 				pass, rc, WRITESIZE);
73 			exit(1);
74 		}
75 		fsync(fd);
76 	}
77 }
78 
do_direct_reads(char * filename)79 int do_direct_reads(char *filename)
80 {
81 	int fd;
82 	int offset;
83 	int rc, i;
84 	int *p;
85 
86 	fd = open(filename, O_DIRECT | O_RDONLY, 0);
87 	assert("open", fd >= 0);
88 
89 	for (offset = 0; offset + READSIZE <= BIGSIZE; offset += READSIZE) {
90 		rc = pread(fd, iobuf, READSIZE, offset);
91 		assert("pread", rc >= 0);
92 		if (rc != READSIZE) {
93 			fprintf(stderr, "Pass: %d short read (%d out of %d)\n",
94 				pass, rc, READSIZE);
95 			exit(1);
96 		}
97 		for (i = 0, p = (int *)iobuf; i < READSIZE; i += 4) {
98 			if (*p) {
99 				fprintf(stderr,
100 					"Pass: %d Found data (%08x) at offset %d+%d\n",
101 					pass, *p, offset, i);
102 				close(fd);
103 				return 1;
104 			}
105 			p++;
106 		}
107 	}
108 	close(fd);
109 	return 0;
110 }
111 
main(int argc,char * argv[])112 int main(int argc, char *argv[])
113 {
114 	char *filename;
115 	int fd;
116 	int pid;
117 	int err;
118 	int bufsize;
119 
120 	if (argc != 2) {
121 		fprintf(stderr, "Needs a filename as an argument.\n");
122 		exit(1);
123 	}
124 
125 	filename = argv[1];
126 
127 	pagesize = getpagesize();
128 	bufsize = READSIZE;
129 	if (WRITESIZE > READSIZE)
130 		bufsize = WRITESIZE;
131 	err = posix_memalign((void **)&iobuf, pagesize, bufsize);
132 	if (err) {
133 		fprintf(stderr, "Error allocating %d aligned bytes.\n",
134 			bufsize);
135 		exit(1);
136 	}
137 
138 	fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666);
139 	assert("open", fd >= 0);
140 
141 	do {
142 
143 		assert("ftruncate", ftruncate(fd, BIGSIZE) == 0);
144 		fsync(fd);
145 
146 		pid = fork();
147 		assert("fork", pid >= 0);
148 
149 		if (!pid) {
150 			do_buffered_writes(fd, 0);
151 			exit(0);
152 		}
153 
154 		err = do_direct_reads(filename);
155 
156 		wait4(pid, NULL, WNOHANG, 0);
157 
158 		if (err)
159 			break;
160 
161 		/* Fill the file with a known pattern so that the blocks
162 		 * on disk can be detected if they become exposed. */
163 		do_buffered_writes(fd, 1);
164 		fsync(fd);
165 
166 		assert("ftruncate", ftruncate(fd, 0) == 0);
167 		fsync(fd);
168 	} while (pass++ < MAX_ITERATIONS);
169 
170 	if (!err) {
171 		fprintf(stdout, "ltp-diorh: Completed %d iterations OK \n",
172 			pass);
173 	}
174 
175 	return err;
176 }
177