| // SPDX-License-Identifier: GPL-2.0+ | |
| /* | |
| * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. | |
| */ | |
| #include "global.h" | |
| int | |
| main(int argc, char **argv) | |
| { | |
| int c, i, j, n, err = 0; | |
| int writefd, readfd; | |
| long iterations = 100; | |
| long psize, bsize, leaksize = 32 * 1024 * 1024; | |
| char *filename; | |
| char *readbuffer, *writebuffer; | |
| off64_t resvsize; | |
| xfs_flock64_t resvsp; | |
| psize = bsize = getpagesize(); | |
| resvsize = bsize * (off64_t) 10000; | |
| while ((c = getopt(argc, argv, "b:i:l:s:")) != EOF) { | |
| switch(c) { | |
| case 'b': | |
| bsize = atol(optarg); | |
| break; | |
| case 'i': | |
| iterations = atol(optarg); | |
| break; | |
| case 'l': | |
| leaksize = atol(optarg); | |
| break; | |
| case 's': | |
| resvsize = (off64_t) atoll(optarg); | |
| break; | |
| default: | |
| err++; | |
| break; | |
| } | |
| } | |
| if (optind > argc + 1) | |
| err++; | |
| if (err) { | |
| printf("Usage: %s [-b blksize] [-l leaksize] [-r resvsize]\n", | |
| argv[0]); | |
| exit(0); | |
| } | |
| filename = argv[optind]; | |
| readbuffer = memalign(psize, bsize); | |
| writebuffer = memalign(psize, bsize); | |
| if (!readbuffer || !writebuffer) { | |
| perror("open"); | |
| exit(1); | |
| } | |
| memset(writebuffer, 'A', bsize); | |
| unlink(filename); | |
| writefd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); | |
| if (writefd < 0) { | |
| perror("open"); | |
| exit(1); | |
| } | |
| readfd = open(filename, O_RDONLY); | |
| if (readfd < 0) { | |
| perror("open"); | |
| exit(1); | |
| } | |
| /* preallocate file space */ | |
| resvsp.l_whence = 0; | |
| resvsp.l_start = 0; | |
| resvsp.l_len = resvsize; | |
| if (xfsctl(filename, writefd, XFS_IOC_RESVSP64, &resvsp) < 0) { | |
| fprintf(stdout, "attempt to reserve %lld bytes for %s " | |
| "using %s failed: %s (%d)\n", | |
| (long long int)resvsize, filename, "XFS_IOC_RESVSP64", | |
| strerror(errno), errno); | |
| } else { | |
| fprintf(stdout, "reserved %lld bytes for %s using %s\n", | |
| (long long int)resvsize, filename, "XFS_IOC_RESVSP64"); | |
| } | |
| /* Space is now preallocated, start IO -- | |
| * write at current offset, pressurize, seek to zero on reader | |
| * and read up to current write offset. | |
| */ | |
| n = 0; | |
| while (++n < iterations) { | |
| char *p; | |
| int numerrors; | |
| if (write(writefd, writebuffer, bsize) < 0) { | |
| perror("write"); | |
| exit(1); | |
| } | |
| /* Apply some memory pressure | |
| * (allocate another chunk and touch all pages) | |
| */ | |
| for (i = 0; i < (leaksize / psize); i++) { | |
| p = malloc(psize); | |
| if (p) | |
| p[7] = '7'; | |
| } | |
| sleep(1); | |
| lseek(readfd, SEEK_SET, 0); | |
| numerrors = 0; | |
| for (j = 0; j < n; j++) { | |
| if (read(readfd, readbuffer, bsize) < 0) { | |
| perror("read"); | |
| exit(1); | |
| } | |
| for (i = 0; i < bsize; i++) { | |
| if (readbuffer[i] != 'A') { | |
| fprintf(stderr, | |
| "errors detected in file, pos: %d (%lld+%d), nwrites: %d [val=0x%x].\n", | |
| j, (long long)j * 4096, | |
| i, n, readbuffer[i]); | |
| numerrors++; | |
| break; | |
| } | |
| } | |
| } | |
| if (numerrors > 10) { | |
| exit(1); | |
| } else if (numerrors) { | |
| fprintf(stdout, "\n"); | |
| } | |
| } | |
| return(0); | |
| } |