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