1 #define _FILE_OFFSET_BITS 64
2 #define _XOPEN_SOURCE 500
13 #include <sys/ioctl.h>
15 #include <sys/param.h>
16 #include <sys/types.h>
22 #include <openssl/rc4.h>
23 #include <openssl/md4.h>
25 static const unsigned char bcache_magic[] = {
26 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
27 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 };
29 unsigned char zero[4096];
33 #define Pread(fd, buf, size, offset) do { \
35 while (_read < size) { \
36 _r = pread(fd, buf, (size) - _read, (offset) + _read); \
43 #define Pwrite(fd, buf, size, offset) do { \
45 while (_write < size) { \
46 _r = pwrite(fd, buf, (size) - _write, offset + _write); \
53 /* Marsaglia polar method
58 static double n = 0 / (double) 0;
67 x = random() / (double) (RAND_MAX / 2) - 1;
68 y = random() / (double) (RAND_MAX / 2) - 1;
73 s = sqrt(-2 * log(s) / s);
78 long getblocks(int fd)
82 if (fstat(fd, &statbuf)) {
86 ret = statbuf.st_size / 512;
87 if (S_ISBLK(statbuf.st_mode))
88 if (ioctl(fd, BLKGETSIZE, &ret)) {
89 perror("ioctl error");
96 unsigned char csum[16];
97 unsigned char oldcsum[16];
104 char logbuf[1 << 21];
114 sprintf(logbuf, "log.%i", abs(random()) % 1000);
115 fd = open(logbuf, O_WRONLY|O_CREAT|O_TRUNC, 0644);
118 perror("Error opening log file");
123 len = klogctl(4, logbuf, 1 << 21);
126 perror("Error reading kernel log");
131 int r = write(fd, logbuf + w, len - w);
133 perror("Error writing log");
140 void aio_loop(int nr)
150 int main(int argc, char **argv)
152 bool walk = false, randsize = false, verbose = false, csum = false, rtest = false, wtest = false;
153 int fd1, fd2 = 0, direct = 0, nbytes = 4096, j, o;
154 unsigned long size, i, offset = 0, done = 0, unique = 0, benchmark = 0;
155 void *buf1 = NULL, *buf2 = NULL;
156 struct pagestuff *pages, *p;
158 time_t last_printed = 0;
162 RC4_set_key(&writedata, 16, bcache_magic);
164 while ((o = getopt(argc, argv, "dnwvscwlb:")) != EOF)
191 benchmark = atol(optarg);
200 if (!rtest && !wtest)
204 printf("Please enter a device to test\n");
208 if (!csum && !benchmark && argc < 2) {
209 printf("Please enter a device to compare against\n");
213 fd1 = open(argv[0], (wtest ? O_RDWR : O_RDONLY)|direct);
214 if (!csum && !benchmark)
215 fd2 = open(argv[1], (wtest ? O_RDWR : O_RDONLY)|direct);
217 if (fd1 == -1 || fd2 == -1) {
218 perror("Error opening device");
222 size = getblocks(fd1);
223 if (!csum && !benchmark)
224 size = MIN(size, getblocks(fd2));
226 size = size / 8 - 16;
227 pages = calloc(size + 16, sizeof(*pages));
228 printf("size %li\n", size);
230 if (posix_memalign(&buf1, 4096, 4096 * 16) ||
231 posix_memalign(&buf2, 4096, 4096 * 16)) {
232 printf("Could not allocate buffers\n");
235 //setvbuf(stdout, NULL, _IONBF, 0);
237 for (i = 0; !benchmark || i < benchmark; i++) {
238 bool writing = (wtest && (i & 1)) || !rtest;
239 nbytes = randsize ? drand48() * 16 + 1 : 1;
243 offset += walk ? normal() * 20 : random();
251 time_t now = time(NULL);
252 if (now - last_printed >= 2) {
257 print: printf("Loop %6li offset %9li sectors %3i, %6lu mb done, %6lu mb unique\n",
258 i, offset >> 9, nbytes >> 9, done >> 11, unique >> 11);
263 Pread(fd1, buf1, nbytes, offset);
264 if (!writing && !csum && !benchmark)
265 Pread(fd2, buf2, nbytes, offset);
267 for (j = 0; j < nbytes; j += 4096) {
268 p = &pages[(offset + j) / 4096];
271 RC4(&writedata, 4096, zero, buf1 + j);
274 MD4(buf1 + j, 4096, &c[0]);
277 (!p->readcount && !p->writecount)) {
278 memcpy(&p->oldcsum[0], &p->csum[0], 16);
279 memcpy(&p->csum[0], c, 16);
280 } else if (memcmp(&p->csum[0], c, 16))
282 } else if (!writing && !benchmark &&
288 if (!p->writecount && !p->readcount)
291 writing ? p->writecount++ : p->readcount++;
294 Pwrite(fd1, buf1, nbytes, offset);
295 if (writing && !csum && !benchmark)
296 Pwrite(fd2, buf2, nbytes, offset);
298 printf("Loop %6li offset %9li sectors %3i, %6lu mb done, %6lu mb unique\n",
299 i, offset >> 9, nbytes >> 9, done >> 11, unique >> 11);
306 printf("Bad read! loop %li offset %li readcount %i writecount %i\n",
307 i, (offset + j) >> 9, p->readcount, p->writecount);
309 if (!memcmp(&p->oldcsum[0], c, 16))
310 printf("Matches previous csum\n");