1 /*
2  * Copyright (c) 2011 Cyril Hrubis <chrubis@suse.cz>
3  *
4  *   This program is free software;  you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  *   the GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program;  if not, write to the Free Software
16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #ifndef LTP_AIODIO_COMMON_SPARSE
20 #define LTP_AIODIO_COMMON_SPARSE
21 
22 /*
23  * This code tries to create dirty free blocks on
24  * the HDD so there is a chance that blocks to be allocated
25  * for a file are filled with something else than zeroes.
26  *
27  * The usefulness of this is IMHO questionable.
28  */
dirty_freeblocks(int size)29 static void dirty_freeblocks(int size)
30 {
31 	int fd;
32 	void *p;
33 	int pg;
34 	char *filename = "dirty_freeblocks";
35 
36 	pg = getpagesize();
37 	size = ((size + pg - 1) / pg) * pg;
38 
39 	fd = open(filename, O_CREAT|O_RDWR|O_EXCL, 0600);
40 
41 	if (fd < 0)
42 		tst_brkm(TBROK|TERRNO, cleanup, "failed to open '%s'", filename);
43 
44 	SAFE_FTRUNCATE(cleanup, fd, size);
45 
46 	p = SAFE_MMAP(cleanup, NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
47 
48 	memset(p, 0xaa, size);
49 	msync(p, size, MS_SYNC);
50 	munmap(p, size);
51 	close(fd);
52 	unlink(filename);
53 }
54 
55 /*
56  * Scale value by kilo, mega, or giga.
57  */
scale_by_kmg(long long value,char scale)58 long long scale_by_kmg(long long value, char scale)
59 {
60 	switch (scale) {
61 	case 'g':
62 	case 'G':
63 		value *= 1024;
64 	case 'm':
65 	case 'M':
66 		value *= 1024;
67 	case 'k':
68 	case 'K':
69 		value *= 1024;
70 		break;
71 	case '\0':
72 		break;
73 	default:
74 		usage();
75 		break;
76 	}
77 	return value;
78 }
79 
check_zero(char * buf,int size)80 char *check_zero(char *buf, int size)
81 {
82 	char *p;
83 
84 	p = buf;
85 
86 	while (size > 0) {
87 		if (*buf != 0) {
88 			fprintf(stderr, "non zero buffer at buf[%d] => 0x%02x,%02x,%02x,%02x\n",
89 				buf - p, (unsigned int)buf[0],
90 				size > 1 ? (unsigned int)buf[1] : 0,
91 				size > 2 ? (unsigned int)buf[2] : 0,
92 				size > 3 ? (unsigned int)buf[3] : 0);
93 			return buf;
94 		}
95 		buf++;
96 		size--;
97 	}
98 
99 	return NULL;
100 }
101 
102 /*
103  * Make sure we read only zeroes,
104  * either there is a hole in the file,
105  * or zeroes were actually written by parent.
106  */
read_sparse(char * filename,int filesize)107 static void read_sparse(char *filename, int filesize)
108 {
109 	int fd;
110 	int  i, j, r;
111 	char buf[4096];
112 
113 	/*
114 	 * Wait for the file to appear.
115 	 */
116 	for (i = 0; i < 10000; i++) {
117 		fd = open(filename, O_RDONLY);
118 
119 		if (fd != -1)
120 			break;
121 
122 		if (debug)
123 			fprintf(stderr, "Child %i waits for '%s' to appear\n",
124 			        getpid(), filename);
125 
126 		usleep(100000);
127 	}
128 
129 	if (fd == -1) {
130 		if (debug)
131 			fprintf(stderr, "Child %i failed to open '%s'\n",
132 			        getpid(), filename);
133 		exit(10);
134 	}
135 
136 	if (debug)
137 		fprintf(stderr, "Child %i has opened '%s' for reading\n",
138 		        getpid(), filename);
139 
140 	for (i = 0; i < 100000000; i++) {
141 		off_t offset = 0;
142 		char *badbuf;
143 
144 		if (debug)
145 			fprintf(stderr, "Child %i loop %i\n", getpid(), i);
146 
147 		lseek(fd, SEEK_SET, 0);
148 		for (j = 0; j < filesize+1; j += sizeof(buf)) {
149 			r = read(fd, buf, sizeof(buf));
150 			if (r > 0) {
151 				if ((badbuf = check_zero(buf, r))) {
152 					fprintf(stderr, "non-zero read at offset %d\n",
153 						offset + badbuf - buf);
154 					exit(10);
155 				}
156 			}
157 			offset += r;
158 		}
159 	}
160 
161 	exit(0);
162 }
163 
164 #endif /* LTP_AIODIO_COMMON_SPARSE */
165