1 /* A general i/o consistency test library. It performs i/o
2 * using functions provided by the client (readblock, dowriteblock)
3 * with a working set size specified by the client. It checks that
4 * blocks that were written have the same contents when later read,
5 * using different access patterns. The assumption is the various
6 * cache layers so exercised are forced into many different states
7 * (reordering, eviction, etc), hopefully triggering bugs if present.
9 * Entry point: dotest()
12 #include <sys/types.h>
13 #include <sys/ioc_memory.h>
21 #include "testcache.h"
29 genblock(int b
, char *blockdata
, int blocksize
, u32_t seed
)
31 u32_t
*p
= (u32_t
*) blockdata
,
32 *plimit
= (u32_t
*) (blockdata
+ blocksize
),
37 for(p
= (u32_t
*) blockdata
; p
< plimit
; p
++) {
44 checkblock(int b
, int blocksize
, u32_t seed
)
46 static char data
[MAXBLOCKSIZE
], expected_data
[MAXBLOCKSIZE
];
49 genblock(b
, expected_data
, blocksize
, seed
);
51 r
= readblock(b
, blocksize
, seed
, data
);
53 if(r
== OK_BLOCK_GONE
) { return 0; }
56 fprintf(stderr
, "readblock failed\n");
60 if(memcmp(expected_data
, data
, blocksize
)) {
61 fprintf(stderr
, "comparison of %d failed\n", b
);
69 writeblock(int b
, int blocksize
, u32_t seed
)
71 static char data
[MAXBLOCKSIZE
];
73 genblock(b
, data
, blocksize
, seed
);
75 if(dowriteblock(b
, blocksize
, seed
, data
) != blocksize
) {
76 fprintf(stderr
, "writeblock of %d failed\n", b
);
84 makepermutation(int nblocks
, int *permutation
)
88 assert(nblocks
> 0 && nblocks
<= MAXBLOCKS
);
90 for(b
= 0; b
< nblocks
; b
++) permutation
[b
] = b
;
92 for(b
= 0; b
< nblocks
-1; b
++) {
93 int s
, other
= b
+ random() % (nblocks
- b
- 1);
94 assert(other
>= b
&& other
< nblocks
);
95 s
= permutation
[other
];
96 permutation
[other
] = permutation
[b
];
104 checkblocks(int nblocks
, int blocksize
, u32_t seed
)
107 int nrandom
= nblocks
* 3;
108 static int perm1
[MAXBLOCKS
];
110 if(!quietflag
) { fprintf(stderr
, "\nverifying "); fflush(stderr
); }
112 makepermutation(nblocks
, perm1
);
114 assert(nblocks
> 0 && nblocks
<= MAXBLOCKS
);
115 assert(blocksize
> 0 && blocksize
<= MAXBLOCKSIZE
);
117 for(b
= 0; b
< nblocks
; b
++) {
118 if(checkblock(b
, blocksize
, seed
)) { return 1; }
121 for(b
= 0; b
< nrandom
; b
++) {
122 if(checkblock(random() % nblocks
, blocksize
, seed
)) { return 1; }
125 for(b
= 0; b
< nblocks
; b
++) {
126 if(checkblock(b
, blocksize
, seed
)) { return 1; }
129 for(b
= 0; b
< nblocks
; b
++) {
130 if(checkblock(perm1
[b
], blocksize
, seed
)) { return 1; }
133 if(!quietflag
) { fprintf(stderr
, "done\n"); }
139 dotest(int blocksize
, int nblocks
, int iterations
)
142 int nrandom
= nblocks
* iterations
;
143 static int perm1
[MAXBLOCKS
], perm2
[MAXBLOCKS
];
144 static int newblock
[MAXBLOCKS
];
145 u32_t seed
= random(), newseed
;
148 assert(nblocks
> 0 && nblocks
<= MAXBLOCKS
);
150 mb
= (int) ((u64_t
) blocksize
* nblocks
/ 1024 / 1024);
152 if(!quietflag
) { fprintf(stderr
, "test: %d * %d = %dMB\n", blocksize
, nblocks
, mb
); }
154 for(b
= 0; b
< nblocks
; b
++) {
155 if(writeblock(b
, blocksize
, seed
) < blocksize
) { return 1; }
156 if(checkblock(b
, blocksize
, seed
)) { return 1; }
157 printprogress("writing sequential", b
, nblocks
);
160 if(checkblocks(nblocks
, blocksize
, seed
)) { return 1; }
162 makepermutation(nblocks
, perm1
);
164 for(b
= 0; b
< nblocks
; b
++) {
165 if(writeblock(perm1
[b
], blocksize
, seed
) < blocksize
) { return 1; }
166 if(checkblock(perm1
[b
], blocksize
, seed
)) { return 1; }
167 printprogress("writing permutation", b
, nblocks
);
170 if(checkblocks(nblocks
, blocksize
, seed
)) { return 1; }
172 for(i
= 0; i
< iterations
; i
++) {
173 makepermutation(nblocks
, perm1
);
174 makepermutation(nblocks
, perm2
);
175 memset(newblock
, 0, sizeof(newblock
));
179 if(!quietflag
) { fprintf(stderr
, "iteration %d/%d\n", i
, iterations
); }
181 for(b
= 0; b
< nblocks
; b
++) {
182 int wr
= perm1
[b
], check
= perm2
[b
];
183 if(writeblock(wr
, blocksize
, newseed
) < blocksize
) { return 1; }
185 if(checkblock(check
, blocksize
, newblock
[check
] ? newseed
: seed
)) { return 1; }
186 printprogress("interleaved permutation read, write", b
, nblocks
);
191 if(checkblocks(nblocks
, blocksize
, seed
)) { return 1; }
196 memset(newblock
, 0, sizeof(newblock
));
198 for(b
= 0; b
< nrandom
; b
++) {
199 int wr
= random() % nblocks
, check
= random() % nblocks
;
200 if(writeblock(wr
, blocksize
, newseed
) < blocksize
) { return 1; }
202 if(checkblock(check
, blocksize
,
203 newblock
[check
] ? newseed
: seed
)) { return 1; }
204 printprogress("1 random verify, 1 random write", b
, nrandom
);
209 if(!quietflag
) { fprintf(stderr
, "\n"); }
216 get_fd_offset(int b
, int blocksize
, u64_t
*file_offset
, int *fd
)
218 u64_t offset
= (u64_t
) b
* blocksize
;
221 filenumber
= offset
/ MB
/ MBPERFILE
;
223 assert(filenumber
>= 0 && filenumber
< MAXFILES
);
224 assert(fds
[filenumber
] > 0);
226 *fd
= fds
[filenumber
];
227 *file_offset
= offset
- (filenumber
* MBPERFILE
* MB
);
234 for(f
= 0; f
< n
; f
++) {
235 char tempfilename
[] = "cachetest.XXXXXXXX";
236 fds
[f
] = mkstemp(tempfilename
);
239 fprintf(stderr
, "mkstemp %d/%d failed\n", f
, n
);
246 void cachequiet(int quiet
)