/* * Copyright (c) 2000-2004 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Write a bunch of holes to create a bunch of extents. */ #include "global.h" char *progname; __uint64_t num_holes = 1000; __uint64_t curr_holes; int verbose_opt = 0; char *filename; int status_num = 100; int wsync; int preserve; unsigned int blocksize; __uint64_t fileoffset; #define JUMP_SIZE (128 * 1024) #define NUMHOLES_TO_SIZE(i) (i * JUMP_SIZE) #define SIZE_TO_NUMHOLES(s) (s / JUMP_SIZE) void usage(void) { fprintf(stderr, "%s [-b blocksize] [-n num-holes] [-s status-num]" " [-o start-offset] [-vwp] file\n", progname); exit(1); } static int offset_length( __uint64_t offset, __uint64_t length, xfs_flock64_t *segment) { memset(segment, 0, sizeof(*segment)); segment->l_whence = SEEK_SET; segment->l_start = offset; if (segment->l_start < 0) { printf(_("non-numeric offset argument -- %lld\n"), offset); return 0; } segment->l_len = length; if (segment->l_len < 0) { printf(_("non-numeric length argument -- %lld\n"), length); return 0; } return 1; } int main(int argc, char *argv[]) { int c; int fd; int oflags; __uint64_t i; __uint64_t offset; int blocksize = 512; int fill = 0; unsigned char *buffer = NULL; struct stat stat; xfs_flock64_t segment; progname = argv[0]; while ((c = getopt(argc, argv, "b:n:o:ps:vwf")) != -1) { switch (c) { case 'b': blocksize = atoi(optarg); break; case 'n': num_holes = atoll(optarg); break; case 'v': verbose_opt = 1; break; case 'w': wsync = 1; break; case 'p': preserve = 1; break; case 's': status_num = atoi(optarg); break; case 'o': fileoffset = strtoull(optarg, NULL, 16); break; case 'f': fill = 1; break; case '?': usage(); } } if (optind == argc-1) filename = argv[optind]; else usage(); buffer = malloc(4096); if (buffer == NULL) { fprintf(stderr, "%s: blocksize to big to allocate buffer\n", progname); return 1; } oflags = O_RDWR | O_CREAT; oflags |= (preserve ? 0 : O_TRUNC) | (wsync ? O_SYNC : 0); if ((fd = open(filename, oflags, 0666)) < 0) { perror("open"); return 1; } if (fstat(fd, &stat) < 0) { perror("stat"); return 1; } if (preserve) { curr_holes = SIZE_TO_NUMHOLES(stat.st_size); if (num_holes < curr_holes) { /* we need to truncate back */ if (ftruncate(fd, NUMHOLES_TO_SIZE(num_holes)) < 0) { perror("ftruncate"); return 1; } if (verbose_opt) { printf("truncating back to %lld\n", NUMHOLES_TO_SIZE(num_holes)); } return 0; } } else { curr_holes = 0; } if (curr_holes != 0 && verbose_opt) { printf("creating %lld more holes\n", num_holes - curr_holes); } printf("xfsctl alloc space\n"); offset_length(0, NUMHOLES_TO_SIZE(num_holes), &segment); if (xfsctl(filename, fd, XFS_IOC_RESVSP64, &segment) < 0) { perror(" XFS_IOC_RESVSP64"); return 0; } #if 0 /* create holes by seeking and writing */ for (i = curr_holes; i < num_holes; i++) { offset = NUMHOLES_TO_SIZE(i) + fileoffset; if (lseek64(fd, offset, SEEK_SET) < 0) { perror("lseek"); return 1; } if (write(fd, buffer, blocksize) < blocksize) { perror("write"); return 1; } if (verbose_opt && ((i+1) % status_num == 0)) { printf("seeked and wrote %lld times\n", i+1); } } #endif offset = 0; for (i = curr_holes; i < num_holes; i++) { offset = NUMHOLES_TO_SIZE(i) + fileoffset; //printf("unresvsp %lld\n", offset); if (!offset_length(offset, JUMP_SIZE/2, &segment)) return 0; if (xfsctl(filename, fd, XFS_IOC_UNRESVSP64, &segment) < 0) { perror("XFS_IOC_UNRESVSP64"); return 0; } } /* ok fill up file */ if (fill) { int size = 4096; offset = 0; memset(buffer,'B', size); printf("filling in file num_holes %lld size %lld\n",num_holes, NUMHOLES_TO_SIZE(num_holes)); for (i = 0; i < NUMHOLES_TO_SIZE(num_holes) / size ; i++) { if (lseek64(fd, offset, SEEK_SET) < 0) { perror("lseek"); return 1; } //printf("write @ %lld\n",offset); if (write(fd, buffer, size) < size ) { perror("write"); return 1; } offset += size; } } close(fd); return 0; }