2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
35 unsigned char *valid; /* Bit-vector array showing which blocks have been written */
36 int nvalid; /* number of bytes in valid array */
37 #define SETBIT(ARRAY, N) ((ARRAY)[(N)/8] |= (1 << ((N)%8)))
38 #define BITVAL(ARRAY, N) ((ARRAY)[(N)/8] & (1 << ((N)%8)))
41 unsigned int blocksize;
51 __uint64_t fileoffset;
53 struct fsxattr rtattr;
55 #define READ_XFER 10 /* block to read at a time when checking */
57 void usage(char *progname);
59 void writeblks(int fd);
61 void dumpblock(int *buffer, __uint64_t offset, int blocksize);
66 fprintf(stderr, "usage: %s [-l filesize] [-b blocksize] [-c count] [-o write offset] [-s seed] [-x extentsize] [-w] [-v] [-d] [-r] [-a] [-p] filename\n",
72 main(int argc, char *argv[])
74 int seed, ch, fd, oflags;
75 char *filename = NULL;
78 filesize = ((__uint64_t)256)*1024*1024;
80 count = filesize/blocksize;
85 while ((ch = getopt(argc, argv, "b:l:s:c:o:x:vwdrapt")) != EOF) {
87 case 'b': blocksize = atoi(optarg); break;
88 case 'l': filesize = strtoll(optarg, NULL, 16); break;
89 case 's': seed = atoi(optarg); break;
90 case 'c': count = atoi(optarg); break;
91 case 'o': fileoffset = strtoll(optarg, NULL, 16); break;
92 case 'x': extsize = atoi(optarg); break;
93 case 'v': verbose++; break;
94 case 'w': wsync++; break;
95 case 'd': direct++; break;
96 case 'r': rt++; break;
97 case 'a': alloconly++; break;
98 case 'p': preserve++; break;
99 case 't': test++; preserve++; break;
100 default: usage(argv[0]); break;
103 if (optind == argc-1)
104 filename = argv[optind];
107 if ((filesize % blocksize) != 0) {
108 filesize -= filesize % blocksize;
109 printf("filesize not a multiple of blocksize, reducing filesize to %lld\n",
112 if ((fileoffset % blocksize) != 0) {
113 fileoffset -= fileoffset % blocksize;
114 printf("fileoffset not a multiple of blocksize, reducing fileoffset to %lld\n",
117 if (count > (filesize/blocksize)) {
118 count = (filesize/blocksize);
119 printf("count of blocks written is too large, setting to %d\n",
121 } else if (count < 1) {
123 printf("count of blocks written is too small, setting to %d\n",
126 printf("randholes: Seed = %d (use \"-s %d\" to re-execute this test)\n", seed, seed);
129 printf("randholes: blocksize=%d, filesize=%Ld, seed=%d\n"
130 "randholes: count=%d, offset=%Ld, extsize=%d\n",
131 blocksize, filesize, seed, count, fileoffset, extsize);
132 printf("randholes: verbose=%d, wsync=%d, direct=%d, rt=%d, alloconly=%d, preserve=%d, test=%d\n",
133 verbose, wsync, direct, rt, alloconly, preserve, test);
136 * Open the file, write rand block in random places, read them all
137 * back to check for correctness, then close the file.
139 nvalid = (filesize / blocksize) / 8 + 1;
140 if ((valid = (unsigned char *)calloc(1, (unsigned)nvalid)) == NULL) {
147 oflags=test?(O_RDONLY):(O_RDWR | O_CREAT);
148 oflags |= (preserve ? 0 : O_TRUNC) |
149 (wsync ? O_SYNC : 0) |
150 (direct ? O_DIRECT : 0);
152 if ((fd = open(filename, oflags, 0666)) < 0) {
157 if (ioctl(fd, XFS_IOC_FSGETXATTR, &rtattr) < 0) {
158 perror("ioctl(XFS_IOC_FSGETXATTR)");
161 if ((rtattr.fsx_xflags & XFS_XFLAG_REALTIME) == 0 ||
162 (extsize && rtattr.fsx_extsize != extsize * blocksize)) {
163 rtattr.fsx_xflags |= XFS_XFLAG_REALTIME;
165 rtattr.fsx_extsize = extsize * blocksize;
166 if (ioctl(fd, XFS_IOC_FSSETXATTR, &rtattr) < 0) {
167 perror("ioctl(XFS_IOC_FSSETXATTR)");
173 if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
174 perror("ioctl(XFS_IOC_FIOINFO)");
177 if (blocksize % diob.d_miniosz) {
178 fprintf(stderr, "blocksize %d must be a multiple of %d for direct I/O\n", blocksize, diob.d_miniosz);
182 printf(test?"write (skipped)\n":"write\n");
184 printf("readback\n");
193 printf("randholes: %d errors found during readback\n", r);
196 printf("randholes: ok\n");
210 buffer = memalign(diob.d_mem, blocksize);
212 buffer = malloc(blocksize);
213 if (buffer == NULL) {
217 memset(buffer, 0, blocksize);
219 for ( ; count > 0; count--) {
220 if (verbose && ((count % 100) == 0)) {
225 offset = (__uint64_t)block * blocksize;
230 fl.l_len = blocksize;
232 if (ioctl(fd, XFS_IOC_RESVSP64, &fl) < 0) {
233 perror("ioctl(XFS_IOC_RESVSP64)");
238 SETBIT(valid, block);
240 if (lseek64(fd, fileoffset + offset, SEEK_SET) < 0) {
245 *(__uint64_t *)buffer = *(__uint64_t *)(buffer+256) =
248 if (write(fd, buffer, blocksize) < blocksize) {
253 if (test && verbose>1) printf("NOT ");
255 printf("writing data at offset=%llx, value 0x%llx and 0x%llx\n",
257 *(__uint64_t *)buffer, *(__uint64_t *)(buffer+256));
267 unsigned long offset;
269 unsigned int xfer, block, i;
274 xfer = READ_XFER*blocksize;
276 buffer = memalign(diob.d_mem, xfer);
278 buffer = malloc(xfer);
279 if (buffer == NULL) {
283 memset(buffer, 0, xfer);
287 if (lseek64(fd, fileoffset, SEEK_SET) < 0) {
291 for (offset = 0, block = 0; offset < filesize; offset += xfer) {
292 if ((i = read(fd, buffer, xfer) < xfer)) {
298 for (tmp = buffer, i = 0; i < READ_XFER; i++, block++, tmp += blocksize) {
299 if (verbose && ((block % 100) == 0)) {
303 if (BITVAL(valid, block) == 0) {
304 if ((*(__uint64_t *)tmp != 0LL) ||
305 (*(__uint64_t *)(tmp+256) != 0LL)) {
306 printf("mismatched data at offset=%llx, expected 0x%llx, got 0x%llx and 0x%llx\n",
307 fileoffset + block * blocksize,
310 *(__uint64_t *)(tmp+256));
314 if ( (*(__uint64_t *)tmp !=
315 fileoffset + block * blocksize) ||
316 (*(__uint64_t *)(tmp+256) !=
317 fileoffset + block * blocksize) ) {
318 printf("mismatched data at offset=%llx, expected 0x%llx, got 0x%llx and 0x%llx\n",
319 fileoffset + block * blocksize,
320 fileoffset + block * blocksize,
322 *(__uint64_t *)(tmp+256));
327 printf("block %d blocksize %d\n", block,
329 dumpblock((int *)tmp,
330 fileoffset + block * blocksize,
345 int block, numblocks;
347 numblocks = filesize / blocksize;
348 block = random() % numblocks;
349 if (BITVAL(valid, block) == 0)
352 for ( ; BITVAL(valid, block) != 0; block++) {
353 if (block == (numblocks-1))
357 printf("returning block -1\n");
362 dumpblock(int *buffer, __uint64_t offset, int blocksize)
366 for (i = 0; i < (blocksize / 16); i++) {
367 printf("%llx: 0x%08x 0x%08x 0x%08x 0x%08x\n",
368 offset, *buffer, *(buffer + 1), *(buffer + 2),