Home | History | Annotate | Download | only in ffsb-6.0-rc2
      1 /*
      2  *   Copyright (c) International Business Machines Corp., 2001-2004
      3  *
      4  *   This program is free software;  you can redistribute it and/or modify
      5  *   it under the terms of the GNU General Public License as published by
      6  *   the Free Software Foundation; either version 2 of the License, or
      7  *   (at your option) any later version.
      8  *
      9  *   This program is distributed in the hope that it will be useful,
     10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  *   the GNU General Public License for more details.
     13  *
     14  *   You should have received a copy of the GNU General Public License
     15  *   along with this program;  if not, write to the Free Software
     16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17  */
     18 #define _LARGEFILE64_SOURCE
     19 #include <sys/stat.h>
     20 #include <sys/types.h>
     21 #include <pthread.h>
     22 #include <string.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <assert.h>
     26 #include <errno.h>
     27 
     28 #include "fh.h"
     29 #include "util.h"
     30 #include "ffsb.h"
     31 #include "fileops.h"
     32 #include "ffsb_op.h"
     33 
     34 static void do_stats(struct timeval *start, struct timeval *end,
     35 		     ffsb_thread_t * ft, ffsb_fs_t * fs, syscall_t sys)
     36 {
     37 	struct timeval diff;
     38 	uint32_t value = 0;
     39 
     40 	if (!ft && !fs)
     41 		return;
     42 
     43 	timersub(end, start, &diff);
     44 
     45 	value = 1000000 * diff.tv_sec + diff.tv_usec;
     46 
     47 	if (ft && ft_needs_stats(ft, sys))
     48 		ft_add_stat(ft, sys, value);
     49 	if (fs && fs_needs_stats(fs, sys))
     50 		fs_add_stat(fs, sys, value);
     51 }
     52 
     53 void fop_bench(ffsb_fs_t * fs, unsigned opnum)
     54 {
     55 	fs_set_opdata(fs, fs_get_datafiles(fs), opnum);
     56 }
     57 
     58 void fop_age(ffsb_fs_t * fs, unsigned opnum)
     59 {
     60 	fs_set_opdata(fs, fs_get_agefiles(fs), opnum);
     61 }
     62 
     63 static unsigned readfile_helper(int fd, uint64_t size, uint32_t blocksize,
     64 				char *buf, ffsb_thread_t * ft, ffsb_fs_t * fs)
     65 {
     66 	int iterations, a;
     67 	int last;
     68 
     69 	iterations = size / blocksize;
     70 	last = size % blocksize;
     71 
     72 	for (a = 0; a < iterations; a++)
     73 		fhread(fd, buf, blocksize, ft, fs);
     74 	if (last)
     75 		fhread(fd, buf, last, ft, fs);
     76 	return iterations;
     77 }
     78 
     79 static uint64_t get_random_offset(randdata_t * rd, uint64_t filesize,
     80 				  int aligned)
     81 {
     82 	if (!aligned)
     83 		return getllrandom(rd, filesize);
     84 
     85 	filesize /= 4096;
     86 	return getllrandom(rd, filesize) * 4096;
     87 }
     88 
     89 void ffsb_readfile(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
     90 {
     91 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
     92 	struct ffsb_file *curfile = NULL;
     93 
     94 	int fd;
     95 	uint64_t filesize;
     96 
     97 	char *buf = ft_getbuf(ft);
     98 	int read_random = ft_get_read_random(ft);
     99 	uint64_t read_size = ft_get_read_size(ft);
    100 	uint32_t read_blocksize = ft_get_read_blocksize(ft);
    101 	uint32_t read_skipsize = ft_get_read_skipsize(ft);
    102 	int skip_reads = ft_get_read_skip(ft);
    103 	struct randdata *rd = ft_get_randdata(ft);
    104 
    105 	uint64_t iterations = 0;
    106 
    107 	curfile = choose_file_reader(bf, rd);
    108 	fd = fhopenread(curfile->name, ft, fs);
    109 
    110 	filesize = ffsb_get_filesize(curfile->name);
    111 
    112 	assert(filesize >= read_size);
    113 
    114 	/* Sequential read, starting at a random point */
    115 	if (!read_random) {
    116 		uint64_t range = filesize - read_size;
    117 		uint64_t offset = 0;
    118 		/* Skip or "stride" reads option */
    119 		if (skip_reads) {
    120 			unsigned i, last;
    121 			uint64_t minfilesize;
    122 			iterations = read_size / read_blocksize;
    123 			last = read_size % read_blocksize;
    124 
    125 			/* Double check that the user hasn't specified
    126 			 * a read_size that is too large when combined
    127 			 * with the seeks
    128 			 */
    129 			if (last)
    130 				minfilesize = last + iterations *
    131 				    (read_blocksize + read_skipsize);
    132 			else
    133 				minfilesize = read_blocksize + iterations - 1 *
    134 				    (read_blocksize + read_skipsize);
    135 
    136 			if (minfilesize > filesize) {
    137 				printf("Error: read size %llu bytes too big "
    138 				       "w/ skipsize %u and blocksize %u,"
    139 				       " for file of size %llu bytes\n"
    140 				       " aborting\n\n", read_size,
    141 				       read_skipsize, read_blocksize, filesize);
    142 				printf("minimum file size must be at least "
    143 				       " %llu bytes\n", minfilesize);
    144 				exit(1);
    145 			}
    146 
    147 			for (i = 0; i < iterations; i++) {
    148 				fhread(fd, buf, read_blocksize, ft, fs);
    149 				fhseek(fd, (uint64_t) read_skipsize, SEEK_CUR,
    150 				       ft, fs);
    151 			}
    152 			if (last) {
    153 				fhread(fd, buf, (uint64_t) last, ft, fs);
    154 				iterations++;
    155 			}
    156 		} else {
    157 			/* Regular sequential reads */
    158 			if (range) {
    159 				offset = get_random_offset(rd, range,
    160 							   fs_get_alignio(fs));
    161 				fhseek(fd, offset, SEEK_SET, ft, fs);
    162 			}
    163 			iterations = readfile_helper(fd, read_size,
    164 						     read_blocksize, buf,
    165 						     ft, fs);
    166 		}
    167 	} else {
    168 		/* Randomized read */
    169 		uint64_t range = filesize - read_blocksize;
    170 		int i;
    171 
    172 		iterations = read_size / read_blocksize;
    173 
    174 		for (i = 0; i < iterations; i++) {
    175 			uint64_t offset = get_random_offset(rd, range,
    176 							    fs_get_alignio(fs));
    177 			fhseek(fd, offset, SEEK_SET, ft, fs);
    178 			fhread(fd, buf, read_blocksize, ft, fs);
    179 		}
    180 	}
    181 
    182 	unlock_file_reader(curfile);
    183 	fhclose(fd, ft, fs);
    184 
    185 	ft_incr_op(ft, opnum, iterations, read_size);
    186 	ft_add_readbytes(ft, read_size);
    187 }
    188 
    189 /* Just like ffsb_readfile but we read the whole file from start to
    190  * finish regardless of file size.
    191  */
    192 void ffsb_readall(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    193 {
    194 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    195 	struct ffsb_file *curfile = NULL;
    196 	int fd;
    197 	uint64_t filesize;
    198 
    199 	char *buf = ft_getbuf(ft);
    200 	uint32_t read_blocksize = ft_get_read_blocksize(ft);
    201 	struct randdata *rd = ft_get_randdata(ft);
    202 
    203 	unsigned iterations = 0;
    204 
    205 	curfile = choose_file_reader(bf, rd);
    206 	fd = fhopenread(curfile->name, ft, fs);
    207 
    208 	filesize = ffsb_get_filesize(curfile->name);
    209 	iterations = readfile_helper(fd, filesize, read_blocksize, buf, ft, fs);
    210 
    211 	unlock_file_reader(curfile);
    212 	fhclose(fd, ft, fs);
    213 
    214 	ft_incr_op(ft, opnum, iterations, filesize);
    215 	ft_add_readbytes(ft, filesize);
    216 }
    217 
    218 /* Shared core between ffsb_writefile and ffsb_writefile_fsync.*/
    219 
    220 static unsigned ffsb_writefile_core(ffsb_thread_t * ft, ffsb_fs_t * fs,
    221 				    unsigned opnum, uint64_t * filesize_ret,
    222 				    int fsync_file)
    223 {
    224 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    225 	struct ffsb_file *curfile = NULL;
    226 
    227 	int fd;
    228 	uint64_t filesize;
    229 
    230 	char *buf = ft_getbuf(ft);
    231 	int write_random = ft_get_write_random(ft);
    232 	uint32_t write_size = ft_get_write_size(ft);
    233 	uint32_t write_blocksize = ft_get_write_blocksize(ft);
    234 	struct randdata *rd = ft_get_randdata(ft);
    235 	unsigned iterations = 0;
    236 
    237 	curfile = choose_file_reader(bf, rd);
    238 	fd = fhopenwrite(curfile->name, ft, fs);
    239 
    240 	filesize = ffsb_get_filesize(curfile->name);
    241 
    242 	assert(filesize >= write_size);
    243 
    244 	/* Sequential write, starting at a random point  */
    245 	if (!write_random) {
    246 		uint64_t range = filesize - write_size;
    247 		uint64_t offset = 0;
    248 		if (range) {
    249 			offset = get_random_offset(rd, range,
    250 						   fs_get_alignio(fs));
    251 			fhseek(fd, offset, SEEK_SET, ft, fs);
    252 		}
    253 		iterations = writefile_helper(fd, write_size, write_blocksize,
    254 					      buf, ft, fs);
    255 	} else {
    256 		/* Randomized write */
    257 		uint64_t range = filesize - write_blocksize;
    258 		int i;
    259 		iterations = write_size / write_blocksize;
    260 
    261 		for (i = 0; i < iterations; i++) {
    262 			uint64_t offset = get_random_offset(rd, range,
    263 							    fs_get_alignio(fs));
    264 			fhseek(fd, offset, SEEK_SET, ft, fs);
    265 			fhwrite(fd, buf, write_blocksize, ft, fs);
    266 		}
    267 	}
    268 
    269 	if (fsync_file) {
    270 		if (fsync(fd)) {
    271 			perror("fsync");
    272 			printf("aborting\n");
    273 			exit(1);
    274 		}
    275 	}
    276 	unlock_file_reader(curfile);
    277 	fhclose(fd, ft, fs);
    278 	*filesize_ret = filesize;
    279 	return iterations;
    280 }
    281 
    282 void ffsb_writefile(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    283 {
    284 	unsigned iterations;
    285 	uint64_t filesize;
    286 
    287 	iterations = ffsb_writefile_core(ft, fs, opnum, &filesize, 0);
    288 	ft_incr_op(ft, opnum, iterations, filesize);
    289 	ft_add_writebytes(ft, filesize);
    290 }
    291 
    292 void ffsb_writefile_fsync(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    293 {
    294 	unsigned iterations;
    295 	uint64_t filesize;
    296 
    297 	iterations = ffsb_writefile_core(ft, fs, opnum, &filesize, 1);
    298 	ft_incr_op(ft, opnum, iterations, filesize);
    299 	ft_add_writebytes(ft, filesize);
    300 }
    301 
    302 /* Shared core between ffsb_writeall and ffsb_writeall_fsync.*/
    303 
    304 static unsigned ffsb_writeall_core(ffsb_thread_t * ft, ffsb_fs_t * fs,
    305 				   unsigned opnum, uint64_t * filesize_ret,
    306 				   int fsync_file)
    307 {
    308 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    309 	struct ffsb_file *curfile = NULL;
    310 	int fd;
    311 	uint64_t filesize;
    312 
    313 	char *buf = ft_getbuf(ft);
    314 	uint32_t write_blocksize = ft_get_write_blocksize(ft);
    315 	struct randdata *rd = ft_get_randdata(ft);
    316 
    317 	unsigned iterations = 0;
    318 
    319 	curfile = choose_file_reader(bf, rd);
    320 	fd = fhopenwrite(curfile->name, ft, fs);
    321 
    322 	filesize = ffsb_get_filesize(curfile->name);
    323 	iterations = writefile_helper(fd, filesize, write_blocksize, buf,
    324 				      ft, fs);
    325 	if (fsync_file)
    326 		if (fsync(fd)) {
    327 			perror("fsync");
    328 			printf("aborting\n");
    329 			exit(1);
    330 		}
    331 
    332 	unlock_file_reader(curfile);
    333 	fhclose(fd, ft, fs);
    334 	*filesize_ret = filesize;
    335 	return iterations;
    336 }
    337 
    338 /* Just like ffsb_writefile but we write the whole file from start to
    339  * finish regardless of file size
    340  */
    341 void ffsb_writeall(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    342 {
    343 	unsigned iterations;
    344 	uint64_t filesize;
    345 
    346 	iterations = ffsb_writeall_core(ft, fs, opnum, &filesize, 0);
    347 	ft_incr_op(ft, opnum, iterations, filesize);
    348 	ft_add_writebytes(ft, filesize);
    349 }
    350 
    351 void ffsb_writeall_fsync(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    352 {
    353 	unsigned iterations;
    354 	uint64_t filesize;
    355 
    356 	iterations = ffsb_writeall_core(ft, fs, opnum, &filesize, 1);
    357 	ft_incr_op(ft, opnum, iterations, filesize);
    358 	ft_add_writebytes(ft, filesize);
    359 }
    360 
    361 static unsigned ffsb_appendfile_core(ffsb_thread_t * ft, ffsb_fs_t * fs,
    362 				     unsigned opnum, uint64_t * filesize_ret,
    363 				     int fsync_file)
    364 {
    365 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    366 	struct ffsb_file *curfile;
    367 
    368 	int fd;
    369 
    370 	char *buf = ft_getbuf(ft);
    371 	uint32_t write_size = ft_get_write_size(ft);
    372 	uint32_t write_blocksize = ft_get_write_blocksize(ft);
    373 	struct randdata *rd = ft_get_randdata(ft);
    374 	unsigned iterations = 0;
    375 
    376 	curfile = choose_file_reader(bf, rd);
    377 	fd = fhopenappend(curfile->name, ft, fs);
    378 
    379 	unlock_file_reader(curfile);
    380 
    381 	curfile->size += (uint64_t) write_size;
    382 
    383 	iterations = writefile_helper(fd, write_size, write_blocksize, buf,
    384 				      ft, fs);
    385 	if (fsync_file)
    386 		if (fsync(fd)) {
    387 			perror("fsync");
    388 			printf("aborting\n");
    389 			exit(1);
    390 		}
    391 
    392 	fhclose(fd, ft, fs);
    393 	*filesize_ret = write_size;
    394 	return iterations;
    395 }
    396 
    397 void ffsb_appendfile(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    398 {
    399 	unsigned iterations;
    400 	uint64_t filesize;
    401 
    402 	iterations = ffsb_appendfile_core(ft, fs, opnum, &filesize, 0);
    403 	ft_incr_op(ft, opnum, iterations, filesize);
    404 	ft_add_writebytes(ft, filesize);
    405 }
    406 
    407 void ffsb_appendfile_fsync(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    408 {
    409 	unsigned iterations;
    410 	uint64_t filesize;
    411 
    412 	iterations = ffsb_appendfile_core(ft, fs, opnum, &filesize, 1);
    413 	ft_incr_op(ft, opnum, iterations, filesize);
    414 	ft_add_writebytes(ft, filesize);
    415 }
    416 
    417 static unsigned ffsb_createfile_core(ffsb_thread_t * ft, ffsb_fs_t * fs,
    418 				     unsigned opnum, uint64_t * filesize_ret,
    419 				     int fsync_file)
    420 {
    421 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    422 	struct ffsb_file *newfile = NULL;
    423 
    424 	int fd;
    425 	uint64_t size;
    426 
    427 	char *buf = ft_getbuf(ft);
    428 	uint32_t write_blocksize = ft_get_write_blocksize(ft);
    429 	struct randdata *rd = ft_get_randdata(ft);
    430 	unsigned iterations = 0;
    431 
    432 	if (fs->num_weights) {
    433 		int num = 1 + getrandom(rd, fs->sum_weights);
    434 		int curop = 0;
    435 
    436 		while (fs->size_weights[curop].weight < num) {
    437 			num -= fs->size_weights[curop].weight;
    438 			curop++;
    439 		}
    440 		size = fs->size_weights[curop].size;
    441 	} else {
    442 		uint64_t range =
    443 		    fs_get_max_filesize(fs) - fs_get_min_filesize(fs);
    444 		size = fs_get_min_filesize(fs);
    445 		if (range != 0)
    446 			size += getllrandom(rd, range);
    447 	}
    448 
    449 	newfile = add_file(bf, size, rd);
    450 	fd = fhopencreate(newfile->name, ft, fs);
    451 	iterations = writefile_helper(fd, size, write_blocksize, buf, ft, fs);
    452 
    453 	if (fsync_file)
    454 		if (fsync(fd)) {
    455 			perror("fsync");
    456 			printf("aborting\n");
    457 			exit(1);
    458 		}
    459 
    460 	fhclose(fd, ft, fs);
    461 	unlock_file_writer(newfile);
    462 	*filesize_ret = size;
    463 	return iterations;
    464 }
    465 
    466 void ffsb_createfile(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    467 {
    468 	unsigned iterations;
    469 	uint64_t filesize;
    470 
    471 	iterations = ffsb_createfile_core(ft, fs, opnum, &filesize, 0);
    472 	ft_incr_op(ft, opnum, iterations, filesize);
    473 	ft_add_writebytes(ft, filesize);
    474 }
    475 
    476 void ffsb_createfile_fsync(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    477 {
    478 	unsigned iterations;
    479 	uint64_t filesize;
    480 
    481 	iterations = ffsb_createfile_core(ft, fs, opnum, &filesize, 1);
    482 	ft_incr_op(ft, opnum, iterations, filesize);
    483 	ft_add_writebytes(ft, filesize);
    484 }
    485 
    486 void ffsb_deletefile(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    487 {
    488 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    489 	struct ffsb_file *curfile = NULL;
    490 	randdata_t *rd = ft_get_randdata(ft);
    491 	struct timeval start, end;
    492 	int need_stats = ft_needs_stats(ft, SYS_UNLINK) ||
    493 	    fs_needs_stats(fs, SYS_UNLINK);
    494 
    495 	curfile = choose_file_writer(bf, rd);
    496 	remove_file(bf, curfile);
    497 
    498 	if (need_stats)
    499 		gettimeofday(&start, NULL);
    500 
    501 	if (unlink(curfile->name) == -1) {
    502 		printf("error deleting %s in deletefile\n", curfile->name);
    503 		perror("deletefile");
    504 		exit(0);
    505 	}
    506 
    507 	if (need_stats) {
    508 		gettimeofday(&end, NULL);
    509 		do_stats(&start, &end, ft, fs, SYS_UNLINK);
    510 	}
    511 
    512 	rw_unlock_write(&curfile->lock);
    513 
    514 	ft_incr_op(ft, opnum, 1, 0);
    515 }
    516 
    517 void ffsb_open_close(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    518 {
    519 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    520 	struct ffsb_file *curfile = NULL;
    521 	randdata_t *rd = ft_get_randdata(ft);
    522 	int fd;
    523 
    524 	curfile = choose_file_reader(bf, rd);
    525 	fd = fhopenread(curfile->name, ft, fs);
    526 	fhclose(fd, ft, fs);
    527 	unlock_file_reader(curfile);
    528 	ft_incr_op(ft, opnum, 1, 0);
    529 }
    530 
    531 void ffsb_stat(ffsb_thread_t * ft, ffsb_fs_t * fs, unsigned opnum)
    532 {
    533 	struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum);
    534 	struct ffsb_file *curfile = NULL;
    535 	randdata_t *rd = ft_get_randdata(ft);
    536 
    537 	curfile = choose_file_reader(bf, rd);
    538 	fhstat(curfile->name, ft, fs);
    539 	unlock_file_reader(curfile);
    540 
    541 	ft_incr_op(ft, opnum, 1, 0);
    542 }
    543