2 * Copyright (c) 2000-2003 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 unsigned char *valid; /* Bit-vector array showing which blocks have been written */
22 int nvalid; /* number of bytes in valid array */
23 #define SETBIT(ARRAY, N) ((ARRAY)[(N)/8] |= (1 << ((N)%8)))
24 #define BITVAL(ARRAY, N) ((ARRAY)[(N)/8] & (1 << ((N)%8)))
27 unsigned int blocksize;
37 __uint64_t fileoffset;
39 struct fsxattr rtattr;
41 #define READ_XFER 10 /* block to read at a time when checking */
43 void usage(char *progname);
45 void writeblks(char *fname, int fd);
47 void dumpblock(int *buffer, __uint64_t offset, int blocksize);
53 "usage: %s [-l filesize] [-b blocksize] [-c count]"
54 " [-o write offset] [-s seed] [-x extentsize]"
55 " [-w] [-v] [-d] [-r] [-a] [-p] filename\n",
61 main(int argc, char *argv[])
63 int seed, ch, fd, oflags;
64 char *filename = NULL;
67 filesize = ((__uint64_t)256)*1024*1024;
69 count = filesize/blocksize;
74 while ((ch = getopt(argc, argv, "b:l:s:c:o:x:vwdrapt")) != EOF) {
76 case 'b': blocksize = atoi(optarg); break;
77 case 'l': filesize = strtoull(optarg, NULL, 16); break;
78 case 's': seed = atoi(optarg); break;
79 case 'c': count = atoi(optarg); break;
80 case 'o': fileoffset = strtoull(optarg, NULL, 16); break;
81 case 'x': extsize = atoi(optarg); break;
82 case 'v': verbose++; break;
83 case 'w': wsync++; break;
84 case 'd': direct++; break;
85 case 'r': rt++; break;
86 case 'a': alloconly++; break;
87 case 'p': preserve++; break;
88 case 't': test++; preserve++; break;
89 default: usage(argv[0]); break;
93 filename = argv[optind];
96 if ((filesize % blocksize) != 0) {
97 filesize -= filesize % blocksize;
98 printf("filesize not a multiple of blocksize, reducing filesize to %llu\n",
99 (unsigned long long)filesize);
101 if ((fileoffset % blocksize) != 0) {
102 fileoffset -= fileoffset % blocksize;
103 printf("fileoffset not a multiple of blocksize, reducing fileoffset to %llu\n",
104 (unsigned long long)fileoffset);
106 if (count > (filesize/blocksize)) {
107 count = (filesize/blocksize);
108 printf("count of blocks written is too large, setting to %d\n",
110 } else if (count < 1) {
112 printf("count of blocks written is too small, setting to %d\n",
115 printf("randholes: Seed = %d (use \"-s %d\" to re-execute this test)\n", seed, seed);
118 printf("randholes: blocksize=%d, filesize=%llu, seed=%d\n"
119 "randholes: count=%d, offset=%llu, extsize=%d\n",
120 blocksize, (unsigned long long)filesize, seed,
121 count, (unsigned long long)fileoffset, extsize);
122 printf("randholes: verbose=%d, wsync=%d, direct=%d, rt=%d, alloconly=%d, preserve=%d, test=%d\n",
123 verbose, wsync, direct, rt, alloconly, preserve, test);
126 * Open the file, write rand block in random places, read them all
127 * back to check for correctness, then close the file.
129 nvalid = (filesize / blocksize) / 8 + 1;
130 if ((valid = (unsigned char *)calloc(1, (unsigned)nvalid)) == NULL) {
137 oflags=test?(O_RDONLY):(O_RDWR | O_CREAT);
138 oflags |= (preserve ? 0 : O_TRUNC) |
139 (wsync ? O_SYNC : 0) |
140 (direct ? O_DIRECT : 0);
142 if ((fd = open(filename, oflags, 0666)) < 0) {
148 #ifdef XFS_IOC_FSGETXATTR
149 if (xfsctl(filename, fd, XFS_IOC_FSGETXATTR, &rtattr) < 0) {
150 perror("xfsctl(XFS_IOC_FSGETXATTR)");
153 if ((rtattr.fsx_xflags & XFS_XFLAG_REALTIME) == 0 ||
154 (extsize && rtattr.fsx_extsize != extsize * blocksize)) {
155 rtattr.fsx_xflags |= XFS_XFLAG_REALTIME;
157 rtattr.fsx_extsize = extsize * blocksize;
158 if (xfsctl(filename, fd, XFS_IOC_FSSETXATTR, &rtattr) < 0) {
159 perror("xfsctl(XFS_IOC_FSSETXATTR)");
165 if (fcntl(fd, F_FSGETXATTR, &rtattr) < 0) {
166 perror("fcntl(F_FSGETXATTR)");
169 if ((rtattr.fsx_xflags & XFS_XFLAG_REALTIME) == 0 ||
170 (extsize && rtattr.fsx_extsize != extsize * blocksize)) {
171 rtattr.fsx_xflags |= XFS_XFLAG_REALTIME;
173 rtattr.fsx_extsize = extsize * blocksize;
174 if (fcntl(fd, F_FSSETXATTR, &rtattr) < 0) {
175 perror("fcntl(F_FSSETXATTR)");
186 #ifdef XFS_IOC_DIOINFO
187 if (xfsctl(filename, fd, XFS_IOC_DIOINFO, &diob) < 0) {
188 perror("xfsctl(XFS_IOC_FIOINFO)");
193 if (fcntl(fd, F_DIOINFO, &diob) < 0) {
194 perror("fcntl(F_FIOINFO)");
201 if (blocksize % diob.d_miniosz) {
203 "blocksize %d must be a multiple of %d for direct I/O\n",
209 printf(test?"write (skipped)\n":"write\n");
210 writeblks(filename, fd);
211 printf("readback\n");
220 printf("randholes: %d errors found during readback\n", r);
223 printf("randholes: ok\n");
229 writeblks(char *fname, int fd)
237 buffer = memalign(diob.d_mem, blocksize);
239 buffer = malloc(blocksize);
240 if (buffer == NULL) {
244 memset(buffer, 0, blocksize);
246 for ( ; count > 0; count--) {
247 if (verbose && ((count % 100) == 0)) {
252 offset = (__uint64_t)block * blocksize;
257 fl.l_len = blocksize;
260 #ifdef XFS_IOC_RESVSP64
261 if (xfsctl(fname, fd, XFS_IOC_RESVSP64, &fl) < 0) {
262 perror("xfsctl(XFS_IOC_RESVSP64)");
267 if (fcntl(fd, F_RESVSP64, &fl) < 0) {
268 perror("fcntl(F_RESVSP64)");
277 SETBIT(valid, block);
279 if (lseek64(fd, fileoffset + offset, SEEK_SET) < 0) {
284 *(__uint64_t *)buffer = *(__uint64_t *)(buffer+256) =
287 if (write(fd, buffer, blocksize) < blocksize) {
292 if (test && verbose>1) printf("NOT ");
294 printf("writing data at offset=%llx, value 0x%llx and 0x%llx\n",
295 (unsigned long long)(fileoffset + offset),
296 *(unsigned long long *)buffer,
297 *(unsigned long long *)(buffer+256));
307 unsigned long offset;
309 unsigned int xfer, block, i;
314 xfer = READ_XFER*blocksize;
316 buffer = memalign(diob.d_mem, xfer);
318 buffer = malloc(xfer);
319 if (buffer == NULL) {
323 memset(buffer, 0, xfer);
327 if (lseek64(fd, fileoffset, SEEK_SET) < 0) {
331 for (offset = 0, block = 0; offset < filesize; offset += xfer) {
332 if ((i = read(fd, buffer, xfer) < xfer)) {
338 for (tmp = buffer, i = 0; i < READ_XFER; i++, block++, tmp += blocksize) {
339 if (verbose && ((block % 100) == 0)) {
343 if (BITVAL(valid, block) == 0) {
344 if ((*(__uint64_t *)tmp != 0LL) ||
345 (*(__uint64_t *)(tmp+256) != 0LL)) {
346 printf("mismatched data at offset=%llx, expected 0x%llx, got 0x%llx and 0x%llx\n",
347 (unsigned long long)fileoffset + block * blocksize,
349 *(unsigned long long *)tmp,
350 *(unsigned long long *)(tmp+256));
354 if ( (*(__uint64_t *)tmp !=
355 fileoffset + block * blocksize) ||
356 (*(__uint64_t *)(tmp+256) !=
357 fileoffset + block * blocksize) ) {
358 printf("mismatched data at offset=%llx, "
359 "expected 0x%llx, got 0x%llx and 0x%llx\n",
360 (unsigned long long)fileoffset + block * blocksize,
361 (unsigned long long)fileoffset + block * blocksize,
362 *(unsigned long long *)tmp,
363 *(unsigned long long *)(tmp+256));
368 printf("block %d blocksize %d\n", block,
370 dumpblock((int *)tmp,
371 fileoffset + block * blocksize,
386 int block, numblocks;
388 numblocks = filesize / blocksize;
389 block = random() % numblocks;
390 if (BITVAL(valid, block) == 0)
393 for ( ; BITVAL(valid, block) != 0; block++) {
394 if (block == (numblocks-1))
398 printf("returning block -1\n");
403 dumpblock(int *buffer, __uint64_t offset, int blocksize)
407 for (i = 0; i < (blocksize / 16); i++) {
408 printf("%llx: 0x%08x 0x%08x 0x%08x 0x%08x\n",
409 (unsigned long long)offset, *buffer, *(buffer + 1), *(buffer + 2),