15184Sek110237 /* 25184Sek110237 * CDDL HEADER START 35184Sek110237 * 45184Sek110237 * The contents of this file are subject to the terms of the 55184Sek110237 * Common Development and Distribution License (the "License"). 65184Sek110237 * You may not use this file except in compliance with the License. 75184Sek110237 * 85184Sek110237 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95184Sek110237 * or http://www.opensolaris.org/os/licensing. 105184Sek110237 * See the License for the specific language governing permissions 115184Sek110237 * and limitations under the License. 125184Sek110237 * 135184Sek110237 * When distributing Covered Code, include this CDDL HEADER in each 145184Sek110237 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155184Sek110237 * If applicable, add the following below this CDDL HEADER, with the 165184Sek110237 * fields enclosed by brackets "[]" replaced with your own identifying 175184Sek110237 * information: Portions Copyright [yyyy] [name of copyright owner] 185184Sek110237 * 195184Sek110237 * CDDL HEADER END 205184Sek110237 */ 215184Sek110237 /* 226212Saw148015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235184Sek110237 * Use is subject to license terms. 246613Sek110237 * 256613Sek110237 * Portions Copyright 2008 Denis Cheng 265184Sek110237 */ 275184Sek110237 285184Sek110237 #include <fcntl.h> 295184Sek110237 #include <pthread.h> 305184Sek110237 #include <errno.h> 315184Sek110237 #include <math.h> 325184Sek110237 #include <libgen.h> 335184Sek110237 #include <sys/mman.h> 34*8404SAndrew.W.Wilson@sun.com #include <sys/shm.h> 356613Sek110237 366613Sek110237 #include "filebench.h" 375184Sek110237 #include "fileset.h" 385184Sek110237 #include "gamma_dist.h" 397946SAndrew.W.Wilson@sun.com #include "utils.h" 405184Sek110237 415184Sek110237 /* 425184Sek110237 * File sets, of type fileset_t, are entities which contain 435184Sek110237 * information about collections of files and subdirectories in Filebench. 445184Sek110237 * The fileset, once populated, consists of a tree of fileset entries of 455184Sek110237 * type filesetentry_t which specify files and directories. The fileset 466212Saw148015 * is rooted in a directory specified by fileset_path, and once the populated 475184Sek110237 * fileset has been created, has a tree of directories and files 485184Sek110237 * corresponding to the fileset's filesetentry tree. 496701Saw148015 * 507556SAndrew.W.Wilson@sun.com * Fileset entities are allocated by fileset_define() which is called from 517556SAndrew.W.Wilson@sun.com * parser_gram.y: parser_fileset_define(). The filesetentry tree corrseponding 527556SAndrew.W.Wilson@sun.com * to the eventual directory and file tree to be instantiated on the storage 537946SAndrew.W.Wilson@sun.com * medium is built by fileset_populate(), which is This routine is called 547946SAndrew.W.Wilson@sun.com * from fileset_createset(), which is in turn called by fileset_createset(). 557946SAndrew.W.Wilson@sun.com * After calling fileset_populate(), fileset_createset() will call 567946SAndrew.W.Wilson@sun.com * fileset_create() to pre-allocate designated files and directories. 577556SAndrew.W.Wilson@sun.com * 587556SAndrew.W.Wilson@sun.com * Fileset_createset() is called from parser_gram.y: parser_create_fileset() 597556SAndrew.W.Wilson@sun.com * when a "create fileset" or "run" command is encountered. When the 607556SAndrew.W.Wilson@sun.com * "create fileset" command is used, it is generally paired with 616701Saw148015 * a "create processes" command, and must appear first, in order to 626701Saw148015 * instantiate all the files in the fileset before trying to use them. 635184Sek110237 */ 645184Sek110237 656305Saw148015 static int fileset_checkraw(fileset_t *fileset); 666305Saw148015 677556SAndrew.W.Wilson@sun.com /* maximum parallel allocation control */ 685673Saw148015 #define MAX_PARALLOC_THREADS 32 695673Saw148015 705673Saw148015 /* 715673Saw148015 * returns pointer to file or fileset 725673Saw148015 * string, as appropriate 735673Saw148015 */ 745673Saw148015 static char * 755673Saw148015 fileset_entity_name(fileset_t *fileset) 765673Saw148015 { 775673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) 785673Saw148015 return ("file"); 795673Saw148015 else 805673Saw148015 return ("fileset"); 815673Saw148015 } 825673Saw148015 835184Sek110237 /* 845184Sek110237 * Removes the last file or directory name from a pathname. 855184Sek110237 * Basically removes characters from the end of the path by 865184Sek110237 * setting them to \0 until a forward slash '/' is 875184Sek110237 * encountered. It also removes the forward slash. 885184Sek110237 */ 895184Sek110237 static char * 905184Sek110237 trunc_dirname(char *dir) 915184Sek110237 { 925184Sek110237 char *s = dir + strlen(dir); 935184Sek110237 945184Sek110237 while (s != dir) { 955184Sek110237 int c = *s; 965184Sek110237 975184Sek110237 *s = 0; 985184Sek110237 if (c == '/') 995184Sek110237 break; 1005184Sek110237 s--; 1015184Sek110237 } 1025184Sek110237 return (dir); 1035184Sek110237 } 1045184Sek110237 1055184Sek110237 /* 1065184Sek110237 * Prints a list of allowed options and how to specify them. 1075184Sek110237 */ 1085184Sek110237 void 1095184Sek110237 fileset_usage(void) 1105184Sek110237 { 1115673Saw148015 (void) fprintf(stderr, 1125673Saw148015 "define [file name=<name> | fileset name=<name>],path=<pathname>," 1135673Saw148015 ",entries=<number>\n"); 1145673Saw148015 (void) fprintf(stderr, 1156212Saw148015 " [,filesize=[size]]\n"); 1166212Saw148015 (void) fprintf(stderr, 1175673Saw148015 " [,dirwidth=[width]]\n"); 1185673Saw148015 (void) fprintf(stderr, 1196212Saw148015 " [,dirdepthrv=$random_variable_name]\n"); 1206212Saw148015 (void) fprintf(stderr, 1215673Saw148015 " [,dirgamma=[100-10000]] " 1225184Sek110237 "(Gamma * 1000)\n"); 1235184Sek110237 (void) fprintf(stderr, 1245673Saw148015 " [,sizegamma=[100-10000]] (Gamma * 1000)\n"); 1255184Sek110237 (void) fprintf(stderr, 1265184Sek110237 " [,prealloc=[percent]]\n"); 1275673Saw148015 (void) fprintf(stderr, " [,paralloc]\n"); 1285184Sek110237 (void) fprintf(stderr, " [,reuse]\n"); 1295184Sek110237 (void) fprintf(stderr, "\n"); 1305184Sek110237 } 1315184Sek110237 1325184Sek110237 /* 1335184Sek110237 * Frees up memory mapped file region of supplied size. The 1345184Sek110237 * file descriptor "fd" indicates which memory mapped file. 1357946SAndrew.W.Wilson@sun.com * If successful, returns 0. Otherwise returns -1 if "size" 1367946SAndrew.W.Wilson@sun.com * is zero, or -1 times the number of times msync() failed. 1375184Sek110237 */ 1385184Sek110237 static int 1395184Sek110237 fileset_freemem(int fd, off64_t size) 1405184Sek110237 { 1415184Sek110237 off64_t left; 1425184Sek110237 int ret = 0; 1435184Sek110237 1445184Sek110237 for (left = size; left > 0; left -= MMAP_SIZE) { 1455184Sek110237 off64_t thismapsize; 1465184Sek110237 caddr_t addr; 1475184Sek110237 1485184Sek110237 thismapsize = MIN(MMAP_SIZE, left); 1495184Sek110237 addr = mmap64(0, thismapsize, PROT_READ|PROT_WRITE, 1505184Sek110237 MAP_SHARED, fd, size - left); 1515184Sek110237 ret += msync(addr, thismapsize, MS_INVALIDATE); 1525184Sek110237 (void) munmap(addr, thismapsize); 1535184Sek110237 } 1545184Sek110237 return (ret); 1555184Sek110237 } 1565184Sek110237 1575184Sek110237 /* 1585184Sek110237 * Creates a path string from the filesetentry_t "*entry" 1595184Sek110237 * and all of its parent's path names. The resulting path 1605184Sek110237 * is a concatination of all the individual parent paths. 1615184Sek110237 * Allocates memory for the path string and returns a 1625184Sek110237 * pointer to it. 1635184Sek110237 */ 1645184Sek110237 char * 1655184Sek110237 fileset_resolvepath(filesetentry_t *entry) 1665184Sek110237 { 1675184Sek110237 filesetentry_t *fsep = entry; 1685184Sek110237 char path[MAXPATHLEN]; 1695184Sek110237 char pathtmp[MAXPATHLEN]; 1705184Sek110237 char *s; 1715184Sek110237 1727946SAndrew.W.Wilson@sun.com path[0] = '\0'; 1735184Sek110237 while (fsep->fse_parent) { 1745184Sek110237 (void) strcpy(pathtmp, "/"); 1757946SAndrew.W.Wilson@sun.com (void) fb_strlcat(pathtmp, fsep->fse_path, MAXPATHLEN); 1767946SAndrew.W.Wilson@sun.com (void) fb_strlcat(pathtmp, path, MAXPATHLEN); 1777946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, pathtmp, MAXPATHLEN); 1785184Sek110237 fsep = fsep->fse_parent; 1795184Sek110237 } 1805184Sek110237 1815184Sek110237 s = malloc(strlen(path) + 1); 1827946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(s, path, MAXPATHLEN); 1835184Sek110237 return (s); 1845184Sek110237 } 1855184Sek110237 1865184Sek110237 /* 1875184Sek110237 * Creates multiple nested directories as required by the 1885184Sek110237 * supplied path. Starts at the end of the path, creating 1895184Sek110237 * a list of directories to mkdir, up to the root of the 1905184Sek110237 * path, then mkdirs them one at a time from the root on down. 1915184Sek110237 */ 1925184Sek110237 static int 1935184Sek110237 fileset_mkdir(char *path, int mode) 1945184Sek110237 { 1955184Sek110237 char *p; 1965184Sek110237 char *dirs[65536]; 1975184Sek110237 int i = 0; 1985184Sek110237 1995184Sek110237 if ((p = strdup(path)) == NULL) 2005184Sek110237 goto null_str; 2015184Sek110237 2025184Sek110237 /* 2035184Sek110237 * Fill an array of subdirectory path names until either we 2045184Sek110237 * reach the root or encounter an already existing subdirectory 2055184Sek110237 */ 2065184Sek110237 /* CONSTCOND */ 2075184Sek110237 while (1) { 2085184Sek110237 struct stat64 sb; 2095184Sek110237 2105184Sek110237 if (stat64(p, &sb) == 0) 2115184Sek110237 break; 2125184Sek110237 if (strlen(p) < 3) 2135184Sek110237 break; 2145184Sek110237 if ((dirs[i] = strdup(p)) == NULL) { 2155184Sek110237 free(p); 2165184Sek110237 goto null_str; 2175184Sek110237 } 2185184Sek110237 2195184Sek110237 (void) trunc_dirname(p); 2205184Sek110237 i++; 2215184Sek110237 } 2225184Sek110237 2235184Sek110237 /* Make the directories, from closest to root downwards. */ 2245184Sek110237 for (--i; i >= 0; i--) { 2255184Sek110237 (void) mkdir(dirs[i], mode); 2265184Sek110237 free(dirs[i]); 2275184Sek110237 } 2285184Sek110237 2295184Sek110237 free(p); 2307556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 2315184Sek110237 2325184Sek110237 null_str: 2335184Sek110237 /* clean up */ 2345184Sek110237 for (--i; i >= 0; i--) 2355184Sek110237 free(dirs[i]); 2365184Sek110237 2375184Sek110237 filebench_log(LOG_ERROR, 2385184Sek110237 "Failed to create directory path %s: Out of memory", path); 2397556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 2405184Sek110237 } 2415184Sek110237 2425673Saw148015 /* 2435673Saw148015 * creates the subdirectory tree for a fileset. 2445673Saw148015 */ 2455673Saw148015 static int 2465673Saw148015 fileset_create_subdirs(fileset_t *fileset, char *filesetpath) 2475673Saw148015 { 2485673Saw148015 filesetentry_t *direntry; 2495673Saw148015 char full_path[MAXPATHLEN]; 2505673Saw148015 char *part_path; 2515673Saw148015 2525673Saw148015 /* walk the subdirectory list, enstanciating subdirs */ 2535673Saw148015 direntry = fileset->fs_dirlist; 2545673Saw148015 while (direntry) { 2557946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(full_path, filesetpath, MAXPATHLEN); 2565673Saw148015 part_path = fileset_resolvepath(direntry); 2577946SAndrew.W.Wilson@sun.com (void) fb_strlcat(full_path, part_path, MAXPATHLEN); 2585673Saw148015 free(part_path); 2595673Saw148015 2605673Saw148015 /* now create this portion of the subdirectory tree */ 2617556SAndrew.W.Wilson@sun.com if (fileset_mkdir(full_path, 0755) == FILEBENCH_ERROR) 2627556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 2635673Saw148015 264*8404SAndrew.W.Wilson@sun.com direntry = direntry->fse_nextoftype; 2655673Saw148015 } 2667556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 2675673Saw148015 } 2685673Saw148015 2695673Saw148015 /* 270*8404SAndrew.W.Wilson@sun.com * move filesetentry between exist tree and non-exist tree, source_tree 271*8404SAndrew.W.Wilson@sun.com * to destination tree. 272*8404SAndrew.W.Wilson@sun.com */ 273*8404SAndrew.W.Wilson@sun.com static void 274*8404SAndrew.W.Wilson@sun.com fileset_move_entry(avl_tree_t *src_tree, avl_tree_t *dst_tree, 275*8404SAndrew.W.Wilson@sun.com filesetentry_t *entry) 276*8404SAndrew.W.Wilson@sun.com { 277*8404SAndrew.W.Wilson@sun.com avl_remove(src_tree, entry); 278*8404SAndrew.W.Wilson@sun.com avl_add(dst_tree, entry); 279*8404SAndrew.W.Wilson@sun.com } 280*8404SAndrew.W.Wilson@sun.com 281*8404SAndrew.W.Wilson@sun.com /* 2827946SAndrew.W.Wilson@sun.com * given a fileset entry, determines if the associated leaf directory 2837946SAndrew.W.Wilson@sun.com * needs to be made or not, and if so does the mkdir. 2847946SAndrew.W.Wilson@sun.com */ 2857946SAndrew.W.Wilson@sun.com static int 2867946SAndrew.W.Wilson@sun.com fileset_alloc_leafdir(filesetentry_t *entry) 2877946SAndrew.W.Wilson@sun.com { 2887946SAndrew.W.Wilson@sun.com fileset_t *fileset; 2897946SAndrew.W.Wilson@sun.com char path[MAXPATHLEN]; 2907946SAndrew.W.Wilson@sun.com struct stat64 sb; 2917946SAndrew.W.Wilson@sun.com char *pathtmp; 2927946SAndrew.W.Wilson@sun.com 2937946SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 2947946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 2957946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 2967946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 2977946SAndrew.W.Wilson@sun.com pathtmp = fileset_resolvepath(entry); 2987946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 2997946SAndrew.W.Wilson@sun.com free(pathtmp); 3007946SAndrew.W.Wilson@sun.com 3017946SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); 3027946SAndrew.W.Wilson@sun.com 3037946SAndrew.W.Wilson@sun.com /* see if not reusing and this directory does not exist */ 3047946SAndrew.W.Wilson@sun.com if (!((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0))) { 3057946SAndrew.W.Wilson@sun.com 3067946SAndrew.W.Wilson@sun.com /* No file or not reusing, so create */ 3077946SAndrew.W.Wilson@sun.com if (mkdir(path, 0755) < 0) { 3087946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 3097946SAndrew.W.Wilson@sun.com "Failed to pre-allocate leaf directory %s: %s", 3107946SAndrew.W.Wilson@sun.com path, strerror(errno)); 311*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 3127946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 3137946SAndrew.W.Wilson@sun.com } 3147946SAndrew.W.Wilson@sun.com } 3157946SAndrew.W.Wilson@sun.com 316*8404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 317*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 3187946SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 3197946SAndrew.W.Wilson@sun.com } 3207946SAndrew.W.Wilson@sun.com 3217946SAndrew.W.Wilson@sun.com /* 3225673Saw148015 * given a fileset entry, determines if the associated file 3235673Saw148015 * needs to be allocated or not, and if so does the allocation. 3245673Saw148015 */ 3255673Saw148015 static int 3265673Saw148015 fileset_alloc_file(filesetentry_t *entry) 3275673Saw148015 { 3287946SAndrew.W.Wilson@sun.com fileset_t *fileset; 3295673Saw148015 char path[MAXPATHLEN]; 3305673Saw148015 char *buf; 3315673Saw148015 struct stat64 sb; 3325673Saw148015 char *pathtmp; 3335673Saw148015 off64_t seek; 3345673Saw148015 int fd; 3355673Saw148015 3367946SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 3377946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 3387946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 3397946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 3405673Saw148015 pathtmp = fileset_resolvepath(entry); 3417946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 3427946SAndrew.W.Wilson@sun.com free(pathtmp); 3435673Saw148015 3445673Saw148015 filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); 3455673Saw148015 3465673Saw148015 /* see if reusing and this file exists */ 3475673Saw148015 if ((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0)) { 3485673Saw148015 if ((fd = open64(path, O_RDWR)) < 0) { 3495673Saw148015 filebench_log(LOG_INFO, 3505673Saw148015 "Attempted but failed to Re-use file %s", 3515673Saw148015 path); 352*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 3537556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 3545673Saw148015 } 3555673Saw148015 3565673Saw148015 if (sb.st_size == (off64_t)entry->fse_size) { 3577556SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, 3585673Saw148015 "Re-using file %s", path); 3595673Saw148015 3607946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 3615673Saw148015 (void) fileset_freemem(fd, 3625673Saw148015 entry->fse_size); 3635673Saw148015 364*8404SAndrew.W.Wilson@sun.com (void) close(fd); 3656701Saw148015 366*8404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 367*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 3687556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 3695673Saw148015 3705673Saw148015 } else if (sb.st_size > (off64_t)entry->fse_size) { 3715673Saw148015 /* reuse, but too large */ 372*8404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, 3735673Saw148015 "Truncating & re-using file %s", path); 3745673Saw148015 3756613Sek110237 #ifdef HAVE_FTRUNCATE64 3766613Sek110237 (void) ftruncate64(fd, (off64_t)entry->fse_size); 3776613Sek110237 #else 3786613Sek110237 (void) ftruncate(fd, (off_t)entry->fse_size); 3796613Sek110237 #endif 3805673Saw148015 3817946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 3825673Saw148015 (void) fileset_freemem(fd, 3835673Saw148015 entry->fse_size); 3845673Saw148015 385*8404SAndrew.W.Wilson@sun.com (void) close(fd); 3866701Saw148015 387*8404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 388*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 3897556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 3905673Saw148015 } 3915673Saw148015 } else { 3925673Saw148015 3935673Saw148015 /* No file or not reusing, so create */ 3945673Saw148015 if ((fd = open64(path, O_RDWR | O_CREAT, 0644)) < 0) { 3955673Saw148015 filebench_log(LOG_ERROR, 3965673Saw148015 "Failed to pre-allocate file %s: %s", 3975673Saw148015 path, strerror(errno)); 3985673Saw148015 399*8404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 400*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 4017556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 4025673Saw148015 } 4035673Saw148015 } 4045673Saw148015 405*8404SAndrew.W.Wilson@sun.com if ((buf = (char *)malloc(FILE_ALLOC_BLOCK)) == NULL) { 406*8404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 407*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 4087556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 409*8404SAndrew.W.Wilson@sun.com } 4106701Saw148015 4115673Saw148015 for (seek = 0; seek < entry->fse_size; ) { 4125673Saw148015 off64_t wsize; 4135673Saw148015 int ret = 0; 4145673Saw148015 4155673Saw148015 /* 4165673Saw148015 * Write FILE_ALLOC_BLOCK's worth, 4175673Saw148015 * except on last write 4185673Saw148015 */ 4195673Saw148015 wsize = MIN(entry->fse_size - seek, FILE_ALLOC_BLOCK); 4205673Saw148015 4215673Saw148015 ret = write(fd, buf, wsize); 4225673Saw148015 if (ret != wsize) { 4235673Saw148015 filebench_log(LOG_ERROR, 4245673Saw148015 "Failed to pre-allocate file %s: %s", 4255673Saw148015 path, strerror(errno)); 4265673Saw148015 (void) close(fd); 4275673Saw148015 free(buf); 428*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 4297556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 4305673Saw148015 } 4315673Saw148015 seek += wsize; 4325673Saw148015 } 4335673Saw148015 4347946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 4355673Saw148015 (void) fileset_freemem(fd, entry->fse_size); 4365673Saw148015 4375673Saw148015 (void) close(fd); 4385673Saw148015 4395673Saw148015 free(buf); 4405673Saw148015 441*8404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 442*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 443*8404SAndrew.W.Wilson@sun.com 4445673Saw148015 filebench_log(LOG_DEBUG_IMPL, 4456286Saw148015 "Pre-allocated file %s size %llu", 4466286Saw148015 path, (u_longlong_t)entry->fse_size); 4475673Saw148015 4487556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 4495673Saw148015 } 4505673Saw148015 4515673Saw148015 /* 4525673Saw148015 * given a fileset entry, determines if the associated file 4535673Saw148015 * needs to be allocated or not, and if so does the allocation. 4547556SAndrew.W.Wilson@sun.com * Sets shm_fsparalloc_count to -1 on error. 4555673Saw148015 */ 4565673Saw148015 static void * 4575673Saw148015 fileset_alloc_thread(filesetentry_t *entry) 4585673Saw148015 { 4597556SAndrew.W.Wilson@sun.com if (fileset_alloc_file(entry) == FILEBENCH_ERROR) { 4607556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 4617556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count = -1; 4625673Saw148015 } else { 4637556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 4647556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count--; 4655673Saw148015 } 4665673Saw148015 4677556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal(&filebench_shm->shm_fsparalloc_cv); 4687556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock(&filebench_shm->shm_fsparalloc_lock); 4695673Saw148015 4705673Saw148015 pthread_exit(NULL); 4715673Saw148015 return (NULL); 4725673Saw148015 } 4735673Saw148015 4745184Sek110237 4755184Sek110237 /* 4765184Sek110237 * First creates the parent directories of the file using 4775184Sek110237 * fileset_mkdir(). Then Optionally sets the O_DSYNC flag 4785184Sek110237 * and opens the file with open64(). It unlocks the fileset 4795184Sek110237 * entry lock, sets the DIRECTIO_ON or DIRECTIO_OFF flags 4805184Sek110237 * as requested, and returns the file descriptor integer 4815184Sek110237 * for the opened file. 4825184Sek110237 */ 4835184Sek110237 int 4845184Sek110237 fileset_openfile(fileset_t *fileset, 4857736SAndrew.W.Wilson@sun.com filesetentry_t *entry, int flag, int filemode, int attrs) 4865184Sek110237 { 4875184Sek110237 char path[MAXPATHLEN]; 4885184Sek110237 char dir[MAXPATHLEN]; 4895184Sek110237 char *pathtmp; 4905184Sek110237 struct stat64 sb; 4915184Sek110237 int fd; 4925184Sek110237 int open_attrs = 0; 4935184Sek110237 4947946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 4957946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 4967946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 4975184Sek110237 pathtmp = fileset_resolvepath(entry); 4987946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 4997946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(dir, path, MAXPATHLEN); 5005184Sek110237 free(pathtmp); 5015184Sek110237 (void) trunc_dirname(dir); 5025184Sek110237 5035184Sek110237 /* If we are going to create a file, create the parent dirs */ 5045184Sek110237 if ((flag & O_CREAT) && (stat64(dir, &sb) != 0)) { 5057556SAndrew.W.Wilson@sun.com if (fileset_mkdir(dir, 0755) == FILEBENCH_ERROR) 5067556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 5076701Saw148015 } 5086701Saw148015 5095184Sek110237 if (attrs & FLOW_ATTR_DSYNC) { 5105184Sek110237 #ifdef sun 5115184Sek110237 open_attrs |= O_DSYNC; 5125184Sek110237 #else 5135184Sek110237 open_attrs |= O_FSYNC; 5145184Sek110237 #endif 5155184Sek110237 } 5165184Sek110237 5177736SAndrew.W.Wilson@sun.com if ((fd = open64(path, flag | open_attrs, filemode)) < 0) { 5185184Sek110237 filebench_log(LOG_ERROR, 519*8404SAndrew.W.Wilson@sun.com "Failed to open file %d, %s, with status %x: %s", 520*8404SAndrew.W.Wilson@sun.com entry->fse_index, path, entry->fse_flags, strerror(errno)); 5217556SAndrew.W.Wilson@sun.com 522*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, FALSE, FALSE, 0); 5237556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 5245184Sek110237 } 5257556SAndrew.W.Wilson@sun.com 5267556SAndrew.W.Wilson@sun.com if (flag & O_CREAT) 527*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 1); 5287556SAndrew.W.Wilson@sun.com else 529*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, FALSE, FALSE, 1); 5305184Sek110237 5315184Sek110237 #ifdef sun 5325184Sek110237 if (attrs & FLOW_ATTR_DIRECTIO) 5335184Sek110237 (void) directio(fd, DIRECTIO_ON); 5345184Sek110237 else 5355184Sek110237 (void) directio(fd, DIRECTIO_OFF); 5365184Sek110237 #endif 5375184Sek110237 5385184Sek110237 return (fd); 5395184Sek110237 } 5405184Sek110237 541*8404SAndrew.W.Wilson@sun.com /* 542*8404SAndrew.W.Wilson@sun.com * removes all filesetentries from their respective btrees, and puts them 543*8404SAndrew.W.Wilson@sun.com * on the free list. The supplied argument indicates which free list to 544*8404SAndrew.W.Wilson@sun.com * use. 545*8404SAndrew.W.Wilson@sun.com */ 546*8404SAndrew.W.Wilson@sun.com static void 547*8404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset_t *fileset, int entry_type) 548*8404SAndrew.W.Wilson@sun.com { 549*8404SAndrew.W.Wilson@sun.com filesetentry_t *entry; 550*8404SAndrew.W.Wilson@sun.com 551*8404SAndrew.W.Wilson@sun.com switch (entry_type & FILESET_PICKMASK) { 552*8404SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 553*8404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *)avl_first(&fileset->fs_noex_files); 554*8404SAndrew.W.Wilson@sun.com 555*8404SAndrew.W.Wilson@sun.com /* make sure non-existing files are marked free */ 556*8404SAndrew.W.Wilson@sun.com while (entry) { 557*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 558*8404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 559*8404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_noex_files, 560*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, entry); 561*8404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_noex_files, entry); 562*8404SAndrew.W.Wilson@sun.com } 563*8404SAndrew.W.Wilson@sun.com 564*8404SAndrew.W.Wilson@sun.com /* free up any existing files */ 565*8404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *)avl_first(&fileset->fs_exist_files); 566*8404SAndrew.W.Wilson@sun.com 567*8404SAndrew.W.Wilson@sun.com while (entry) { 568*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 569*8404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 570*8404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_exist_files, 571*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, entry); 572*8404SAndrew.W.Wilson@sun.com 573*8404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_exist_files, entry); 574*8404SAndrew.W.Wilson@sun.com } 575*8404SAndrew.W.Wilson@sun.com 576*8404SAndrew.W.Wilson@sun.com break; 577*8404SAndrew.W.Wilson@sun.com 578*8404SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 579*8404SAndrew.W.Wilson@sun.com /* nothing to reset, as all (sub)dirs always exist */ 580*8404SAndrew.W.Wilson@sun.com break; 581*8404SAndrew.W.Wilson@sun.com 582*8404SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 583*8404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *) 584*8404SAndrew.W.Wilson@sun.com avl_first(&fileset->fs_noex_leaf_dirs); 585*8404SAndrew.W.Wilson@sun.com 586*8404SAndrew.W.Wilson@sun.com /* make sure non-existing leaf dirs are marked free */ 587*8404SAndrew.W.Wilson@sun.com while (entry) { 588*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 589*8404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 590*8404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_noex_leaf_dirs, 591*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, entry); 592*8404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_noex_leaf_dirs, entry); 593*8404SAndrew.W.Wilson@sun.com } 594*8404SAndrew.W.Wilson@sun.com 595*8404SAndrew.W.Wilson@sun.com /* free up any existing leaf dirs */ 596*8404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *) 597*8404SAndrew.W.Wilson@sun.com avl_first(&fileset->fs_exist_leaf_dirs); 598*8404SAndrew.W.Wilson@sun.com 599*8404SAndrew.W.Wilson@sun.com while (entry) { 600*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 601*8404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 602*8404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_exist_leaf_dirs, 603*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, entry); 604*8404SAndrew.W.Wilson@sun.com 605*8404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_exist_leaf_dirs, entry); 606*8404SAndrew.W.Wilson@sun.com } 607*8404SAndrew.W.Wilson@sun.com 608*8404SAndrew.W.Wilson@sun.com break; 609*8404SAndrew.W.Wilson@sun.com } 610*8404SAndrew.W.Wilson@sun.com } 611*8404SAndrew.W.Wilson@sun.com 612*8404SAndrew.W.Wilson@sun.com /* 613*8404SAndrew.W.Wilson@sun.com * find a filesetentry from the fileset using the supplied index 614*8404SAndrew.W.Wilson@sun.com */ 615*8404SAndrew.W.Wilson@sun.com static filesetentry_t * 616*8404SAndrew.W.Wilson@sun.com fileset_find_entry(avl_tree_t *atp, uint_t index) 617*8404SAndrew.W.Wilson@sun.com { 618*8404SAndrew.W.Wilson@sun.com avl_index_t found_loc; 619*8404SAndrew.W.Wilson@sun.com filesetentry_t desired_fse, *found_fse; 620*8404SAndrew.W.Wilson@sun.com 621*8404SAndrew.W.Wilson@sun.com /* find the file with the desired index, if it is in the tree */ 622*8404SAndrew.W.Wilson@sun.com desired_fse.fse_index = index; 623*8404SAndrew.W.Wilson@sun.com found_fse = avl_find(atp, (void *)(&desired_fse), &found_loc); 624*8404SAndrew.W.Wilson@sun.com if (found_fse != NULL) 625*8404SAndrew.W.Wilson@sun.com return (found_fse); 626*8404SAndrew.W.Wilson@sun.com 627*8404SAndrew.W.Wilson@sun.com /* if requested node not found, find next higher node */ 628*8404SAndrew.W.Wilson@sun.com found_fse = avl_nearest(atp, found_loc, AVL_AFTER); 629*8404SAndrew.W.Wilson@sun.com if (found_fse != NULL) 630*8404SAndrew.W.Wilson@sun.com return (found_fse); 631*8404SAndrew.W.Wilson@sun.com 632*8404SAndrew.W.Wilson@sun.com /* might have hit the end, return lowest available index node */ 633*8404SAndrew.W.Wilson@sun.com found_fse = avl_first(atp); 634*8404SAndrew.W.Wilson@sun.com return (found_fse); 635*8404SAndrew.W.Wilson@sun.com } 6365184Sek110237 6375184Sek110237 /* 6385184Sek110237 * Selects a fileset entry from a fileset. If the 6397946SAndrew.W.Wilson@sun.com * FILESET_PICKLEAFDIR flag is set it will pick a leaf directory entry, 6407946SAndrew.W.Wilson@sun.com * if the FILESET_PICKDIR flag is set it will pick a non leaf directory 641*8404SAndrew.W.Wilson@sun.com * entry, otherwise a file entry. The FILESET_PICKUNIQUE 6425184Sek110237 * flag will take an entry off of one of the free (unused) 6435184Sek110237 * lists (file or directory), otherwise the entry will be 6445184Sek110237 * picked off of one of the rotor lists (file or directory). 6455184Sek110237 * The FILESET_PICKEXISTS will insure that only extant 6465184Sek110237 * (FSE_EXISTS) state files are selected, while 6475184Sek110237 * FILESET_PICKNOEXIST insures that only non extant 6485184Sek110237 * (not FSE_EXISTS) state files are selected. 6496391Saw148015 * Note that the selected fileset entry (file) is returned 6507556SAndrew.W.Wilson@sun.com * with its FSE_BUSY flag (in fse_flags) set. 6515184Sek110237 */ 6525184Sek110237 filesetentry_t * 653*8404SAndrew.W.Wilson@sun.com fileset_pick(fileset_t *fileset, int flags, int tid, int index) 6545184Sek110237 { 6555184Sek110237 filesetentry_t *entry = NULL; 656*8404SAndrew.W.Wilson@sun.com filesetentry_t *start_point; 657*8404SAndrew.W.Wilson@sun.com avl_tree_t *atp; 658*8404SAndrew.W.Wilson@sun.com fbint_t max_entries; 6595184Sek110237 6607556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 6617556SAndrew.W.Wilson@sun.com 6627556SAndrew.W.Wilson@sun.com /* see if we have to wait for available files or directories */ 6637946SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 6647946SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 6657946SAndrew.W.Wilson@sun.com if (fileset->fs_filelist == NULL) 6667946SAndrew.W.Wilson@sun.com goto empty; 667*8404SAndrew.W.Wilson@sun.com 6687556SAndrew.W.Wilson@sun.com while (fileset->fs_idle_files == 0) { 6697556SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_files_cv, 6707556SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 6717556SAndrew.W.Wilson@sun.com } 672*8404SAndrew.W.Wilson@sun.com 673*8404SAndrew.W.Wilson@sun.com max_entries = fileset->fs_constentries; 674*8404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 675*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_free_files; 676*8404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKNOEXIST) { 677*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_noex_files; 678*8404SAndrew.W.Wilson@sun.com } else { 679*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_exist_files; 680*8404SAndrew.W.Wilson@sun.com } 6817946SAndrew.W.Wilson@sun.com break; 682*8404SAndrew.W.Wilson@sun.com 6837946SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 6847946SAndrew.W.Wilson@sun.com if (fileset->fs_dirlist == NULL) 6857946SAndrew.W.Wilson@sun.com goto empty; 686*8404SAndrew.W.Wilson@sun.com 6877946SAndrew.W.Wilson@sun.com while (fileset->fs_idle_dirs == 0) { 6887946SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_dirs_cv, 6897946SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 6907946SAndrew.W.Wilson@sun.com } 691*8404SAndrew.W.Wilson@sun.com 692*8404SAndrew.W.Wilson@sun.com max_entries = 1; 693*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_dirs; 6947946SAndrew.W.Wilson@sun.com break; 695*8404SAndrew.W.Wilson@sun.com 6967946SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 6977946SAndrew.W.Wilson@sun.com if (fileset->fs_leafdirlist == NULL) 6987946SAndrew.W.Wilson@sun.com goto empty; 699*8404SAndrew.W.Wilson@sun.com 7007946SAndrew.W.Wilson@sun.com while (fileset->fs_idle_leafdirs == 0) { 7017946SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_leafdirs_cv, 7027946SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 7037946SAndrew.W.Wilson@sun.com } 704*8404SAndrew.W.Wilson@sun.com 705*8404SAndrew.W.Wilson@sun.com max_entries = fileset->fs_constleafdirs; 706*8404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 707*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_free_leaf_dirs; 708*8404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKNOEXIST) { 709*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_noex_leaf_dirs; 710*8404SAndrew.W.Wilson@sun.com } else { 711*8404SAndrew.W.Wilson@sun.com atp = &fileset->fs_exist_leaf_dirs; 712*8404SAndrew.W.Wilson@sun.com } 7137946SAndrew.W.Wilson@sun.com break; 7147556SAndrew.W.Wilson@sun.com } 7155184Sek110237 7166701Saw148015 /* see if asking for impossible */ 717*8404SAndrew.W.Wilson@sun.com if (avl_is_empty(atp)) 718*8404SAndrew.W.Wilson@sun.com goto empty; 719*8404SAndrew.W.Wilson@sun.com 720*8404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 721*8404SAndrew.W.Wilson@sun.com uint64_t index64; 722*8404SAndrew.W.Wilson@sun.com 723*8404SAndrew.W.Wilson@sun.com /* 724*8404SAndrew.W.Wilson@sun.com * pick at random from free list in order to 725*8404SAndrew.W.Wilson@sun.com * distribute initially allocated files more 726*8404SAndrew.W.Wilson@sun.com * randomly on storage media. Use uniform 727*8404SAndrew.W.Wilson@sun.com * random number generator to select index 728*8404SAndrew.W.Wilson@sun.com * if it is not supplied with pick call. 729*8404SAndrew.W.Wilson@sun.com */ 730*8404SAndrew.W.Wilson@sun.com if (index) { 731*8404SAndrew.W.Wilson@sun.com index64 = index; 732*8404SAndrew.W.Wilson@sun.com } else { 733*8404SAndrew.W.Wilson@sun.com if (filebench_randomno64(&index64, max_entries, 1, 734*8404SAndrew.W.Wilson@sun.com NULL) == FILEBENCH_ERROR) 7357946SAndrew.W.Wilson@sun.com return (NULL); 7365184Sek110237 } 7375184Sek110237 738*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, (int)index64); 739*8404SAndrew.W.Wilson@sun.com 740*8404SAndrew.W.Wilson@sun.com if (entry == NULL) 741*8404SAndrew.W.Wilson@sun.com goto empty; 742*8404SAndrew.W.Wilson@sun.com 743*8404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKBYINDEX) { 744*8404SAndrew.W.Wilson@sun.com /* pick by supplied index */ 745*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, index); 746*8404SAndrew.W.Wilson@sun.com 747*8404SAndrew.W.Wilson@sun.com } else { 748*8404SAndrew.W.Wilson@sun.com /* pick in rotation */ 749*8404SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 750*8404SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 751*8404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKNOEXIST) { 752*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 753*8404SAndrew.W.Wilson@sun.com fileset->fs_file_nerotor); 754*8404SAndrew.W.Wilson@sun.com fileset->fs_file_nerotor = 755*8404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 756*8404SAndrew.W.Wilson@sun.com } else { 757*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 758*8404SAndrew.W.Wilson@sun.com fileset->fs_file_exrotor[tid]); 759*8404SAndrew.W.Wilson@sun.com fileset->fs_file_exrotor[tid] = 760*8404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7615184Sek110237 } 762*8404SAndrew.W.Wilson@sun.com break; 763*8404SAndrew.W.Wilson@sun.com 764*8404SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 765*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, fileset->fs_dirrotor); 766*8404SAndrew.W.Wilson@sun.com fileset->fs_dirrotor = entry->fse_index + 1; 767*8404SAndrew.W.Wilson@sun.com break; 768*8404SAndrew.W.Wilson@sun.com 769*8404SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 770*8404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKNOEXIST) { 771*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 772*8404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_nerotor); 773*8404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_nerotor = 774*8404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 775*8404SAndrew.W.Wilson@sun.com } else { 776*8404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 777*8404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_exrotor); 778*8404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_exrotor = 779*8404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7805184Sek110237 } 781*8404SAndrew.W.Wilson@sun.com break; 782*8404SAndrew.W.Wilson@sun.com } 783*8404SAndrew.W.Wilson@sun.com } 784*8404SAndrew.W.Wilson@sun.com 785*8404SAndrew.W.Wilson@sun.com if (entry == NULL) 786*8404SAndrew.W.Wilson@sun.com goto empty; 787*8404SAndrew.W.Wilson@sun.com 788*8404SAndrew.W.Wilson@sun.com /* see if entry in use */ 789*8404SAndrew.W.Wilson@sun.com start_point = entry; 790*8404SAndrew.W.Wilson@sun.com while (entry->fse_flags & FSE_BUSY) { 791*8404SAndrew.W.Wilson@sun.com 792*8404SAndrew.W.Wilson@sun.com /* it is, so try next */ 793*8404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(atp, entry); 794*8404SAndrew.W.Wilson@sun.com if (entry == NULL) 795*8404SAndrew.W.Wilson@sun.com entry = avl_first(atp); 796*8404SAndrew.W.Wilson@sun.com 797*8404SAndrew.W.Wilson@sun.com /* see if we have wrapped around */ 798*8404SAndrew.W.Wilson@sun.com if ((entry == NULL) || (entry == start_point)) { 799*8404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_SCRIPT, 800*8404SAndrew.W.Wilson@sun.com "All %d files are busy", avl_numnodes(atp)); 801*8404SAndrew.W.Wilson@sun.com goto empty; 8025184Sek110237 } 8035184Sek110237 8045184Sek110237 } 8055184Sek110237 8067556SAndrew.W.Wilson@sun.com /* update file or directory idle counts */ 8077946SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 8087946SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 8097946SAndrew.W.Wilson@sun.com fileset->fs_idle_files--; 8107946SAndrew.W.Wilson@sun.com break; 8117946SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 8127556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs--; 8137946SAndrew.W.Wilson@sun.com break; 8147946SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 8157946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs--; 8167946SAndrew.W.Wilson@sun.com break; 8177946SAndrew.W.Wilson@sun.com } 8187556SAndrew.W.Wilson@sun.com 8197556SAndrew.W.Wilson@sun.com /* Indicate that file or directory is now busy */ 8207556SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_BUSY; 8217556SAndrew.W.Wilson@sun.com 8227556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 8235184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "Picked file %s", entry->fse_path); 8245184Sek110237 return (entry); 8255184Sek110237 8265184Sek110237 empty: 827*8404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_SCRIPT, "No file found"); 8287556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 8295184Sek110237 return (NULL); 8305184Sek110237 } 8315184Sek110237 8325184Sek110237 /* 8337556SAndrew.W.Wilson@sun.com * Removes a filesetentry from the "FSE_BUSY" state, signaling any threads 8347556SAndrew.W.Wilson@sun.com * that are waiting for a NOT BUSY filesetentry. Also sets whether it is 8357556SAndrew.W.Wilson@sun.com * existant or not, or leaves that designation alone. 8367556SAndrew.W.Wilson@sun.com */ 8377556SAndrew.W.Wilson@sun.com void 838*8404SAndrew.W.Wilson@sun.com fileset_unbusy(filesetentry_t *entry, int update_exist, 839*8404SAndrew.W.Wilson@sun.com int new_exist_val, int open_cnt_incr) 8407556SAndrew.W.Wilson@sun.com { 8417556SAndrew.W.Wilson@sun.com fileset_t *fileset = NULL; 8427556SAndrew.W.Wilson@sun.com 8437556SAndrew.W.Wilson@sun.com if (entry) 8447556SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 8457556SAndrew.W.Wilson@sun.com 8467556SAndrew.W.Wilson@sun.com if (fileset == NULL) { 8477556SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, "fileset_unbusy: NO FILESET!"); 8487556SAndrew.W.Wilson@sun.com return; 8497556SAndrew.W.Wilson@sun.com } 8507556SAndrew.W.Wilson@sun.com 8517556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 8527556SAndrew.W.Wilson@sun.com 853*8404SAndrew.W.Wilson@sun.com /* modify FSE_EXIST flag and actual dirs/files count, if requested */ 854*8404SAndrew.W.Wilson@sun.com if (update_exist) { 855*8404SAndrew.W.Wilson@sun.com if (new_exist_val == TRUE) { 856*8404SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_FREE) { 857*8404SAndrew.W.Wilson@sun.com 858*8404SAndrew.W.Wilson@sun.com /* asked to set and it was free */ 859*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_EXISTS; 860*8404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_FREE); 861*8404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 862*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 863*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 864*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, 865*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, entry); 866*8404SAndrew.W.Wilson@sun.com break; 867*8404SAndrew.W.Wilson@sun.com 868*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 869*8404SAndrew.W.Wilson@sun.com break; 870*8404SAndrew.W.Wilson@sun.com 871*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 872*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 873*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, 874*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 875*8404SAndrew.W.Wilson@sun.com entry); 876*8404SAndrew.W.Wilson@sun.com break; 877*8404SAndrew.W.Wilson@sun.com } 878*8404SAndrew.W.Wilson@sun.com 879*8404SAndrew.W.Wilson@sun.com } else if (!(entry->fse_flags & FSE_EXISTS)) { 880*8404SAndrew.W.Wilson@sun.com 881*8404SAndrew.W.Wilson@sun.com /* asked to set, and it was clear */ 882*8404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_EXISTS; 883*8404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 884*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 885*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 886*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, 887*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, entry); 888*8404SAndrew.W.Wilson@sun.com break; 889*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 890*8404SAndrew.W.Wilson@sun.com break; 891*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 892*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 893*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 894*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 895*8404SAndrew.W.Wilson@sun.com entry); 896*8404SAndrew.W.Wilson@sun.com break; 897*8404SAndrew.W.Wilson@sun.com } 898*8404SAndrew.W.Wilson@sun.com } 899*8404SAndrew.W.Wilson@sun.com } else { 900*8404SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_FREE) { 901*8404SAndrew.W.Wilson@sun.com /* asked to clear, and it was free */ 902*8404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~(FSE_FREE | FSE_EXISTS)); 903*8404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 904*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 905*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 906*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, 907*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, entry); 908*8404SAndrew.W.Wilson@sun.com break; 909*8404SAndrew.W.Wilson@sun.com 910*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 911*8404SAndrew.W.Wilson@sun.com break; 912*8404SAndrew.W.Wilson@sun.com 913*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 914*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 915*8404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, 916*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 917*8404SAndrew.W.Wilson@sun.com entry); 918*8404SAndrew.W.Wilson@sun.com break; 919*8404SAndrew.W.Wilson@sun.com } 920*8404SAndrew.W.Wilson@sun.com } else if (entry->fse_flags & FSE_EXISTS) { 921*8404SAndrew.W.Wilson@sun.com 922*8404SAndrew.W.Wilson@sun.com /* asked to clear, and it was set */ 923*8404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_EXISTS); 924*8404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 925*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 926*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 927*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, 928*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, entry); 929*8404SAndrew.W.Wilson@sun.com break; 930*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 931*8404SAndrew.W.Wilson@sun.com break; 932*8404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 933*8404SAndrew.W.Wilson@sun.com fileset_move_entry( 934*8404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 935*8404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 936*8404SAndrew.W.Wilson@sun.com entry); 937*8404SAndrew.W.Wilson@sun.com break; 938*8404SAndrew.W.Wilson@sun.com } 939*8404SAndrew.W.Wilson@sun.com } 940*8404SAndrew.W.Wilson@sun.com } 941*8404SAndrew.W.Wilson@sun.com } 942*8404SAndrew.W.Wilson@sun.com 943*8404SAndrew.W.Wilson@sun.com /* update open count */ 944*8404SAndrew.W.Wilson@sun.com entry->fse_open_cnt += open_cnt_incr; 945*8404SAndrew.W.Wilson@sun.com 9467556SAndrew.W.Wilson@sun.com /* increment idle count, clear FSE_BUSY and signal IF it was busy */ 9477556SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_BUSY) { 9487556SAndrew.W.Wilson@sun.com 9497556SAndrew.W.Wilson@sun.com /* unbusy it */ 9507556SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_BUSY); 9517556SAndrew.W.Wilson@sun.com 9527556SAndrew.W.Wilson@sun.com /* release any threads waiting for unbusy */ 9537556SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_THRD_WAITNG) { 9547556SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_THRD_WAITNG); 9557556SAndrew.W.Wilson@sun.com (void) pthread_cond_broadcast( 9567556SAndrew.W.Wilson@sun.com &fileset->fs_thrd_wait_cv); 9577556SAndrew.W.Wilson@sun.com } 9587556SAndrew.W.Wilson@sun.com 9597556SAndrew.W.Wilson@sun.com /* increment idle count and signal waiting threads */ 9607946SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 9617946SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 9627946SAndrew.W.Wilson@sun.com fileset->fs_idle_files++; 9637946SAndrew.W.Wilson@sun.com if (fileset->fs_idle_files == 1) { 9647946SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9657946SAndrew.W.Wilson@sun.com &fileset->fs_idle_files_cv); 9667946SAndrew.W.Wilson@sun.com } 9677946SAndrew.W.Wilson@sun.com break; 968*8404SAndrew.W.Wilson@sun.com 9697946SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 9707556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs++; 9717556SAndrew.W.Wilson@sun.com if (fileset->fs_idle_dirs == 1) { 9727556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9737556SAndrew.W.Wilson@sun.com &fileset->fs_idle_dirs_cv); 9747556SAndrew.W.Wilson@sun.com } 9757946SAndrew.W.Wilson@sun.com break; 976*8404SAndrew.W.Wilson@sun.com 9777946SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 9787946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs++; 9797946SAndrew.W.Wilson@sun.com if (fileset->fs_idle_leafdirs == 1) { 9807556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9817946SAndrew.W.Wilson@sun.com &fileset->fs_idle_leafdirs_cv); 9827556SAndrew.W.Wilson@sun.com } 9837946SAndrew.W.Wilson@sun.com break; 9847556SAndrew.W.Wilson@sun.com } 9857556SAndrew.W.Wilson@sun.com } 9867556SAndrew.W.Wilson@sun.com 9877556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 9887556SAndrew.W.Wilson@sun.com } 9897556SAndrew.W.Wilson@sun.com 9907556SAndrew.W.Wilson@sun.com /* 9915184Sek110237 * Given a fileset "fileset", create the associated files as 9925184Sek110237 * specified in the attributes of the fileset. The fileset is 9936212Saw148015 * rooted in a directory whose pathname is in fileset_path. If the 9945184Sek110237 * directory exists, meaning that there is already a fileset, 9956212Saw148015 * and the fileset_reuse attribute is false, then remove it and all 9965184Sek110237 * its contained files and subdirectories. Next, the routine 9975184Sek110237 * creates a root directory for the fileset. All the file type 9985184Sek110237 * filesetentries are cycled through creating as needed 9995184Sek110237 * their containing subdirectory trees in the filesystem and 10006212Saw148015 * creating actual files for fileset_preallocpercent of them. The 10015184Sek110237 * created files are filled with fse_size bytes of unitialized 10027556SAndrew.W.Wilson@sun.com * data. The routine returns FILEBENCH_ERROR on errors, 10037556SAndrew.W.Wilson@sun.com * FILEBENCH_OK on success. 10045184Sek110237 */ 10055184Sek110237 static int 10065184Sek110237 fileset_create(fileset_t *fileset) 10075184Sek110237 { 10085184Sek110237 filesetentry_t *entry; 10095184Sek110237 char path[MAXPATHLEN]; 10105184Sek110237 struct stat64 sb; 10115184Sek110237 hrtime_t start = gethrtime(); 10126212Saw148015 char *fileset_path; 10136212Saw148015 char *fileset_name; 10146212Saw148015 int randno; 10155184Sek110237 int preallocated = 0; 10167736SAndrew.W.Wilson@sun.com int reusing; 10175184Sek110237 10186212Saw148015 if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) { 10195673Saw148015 filebench_log(LOG_ERROR, "%s path not set", 10205673Saw148015 fileset_entity_name(fileset)); 10217556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 10225184Sek110237 } 10235184Sek110237 10246212Saw148015 if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) { 10256212Saw148015 filebench_log(LOG_ERROR, "%s name not set", 10266212Saw148015 fileset_entity_name(fileset)); 10277556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 10286212Saw148015 } 10296212Saw148015 10305673Saw148015 #ifdef HAVE_RAW_SUPPORT 10315673Saw148015 /* treat raw device as special case */ 10325673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) 10337556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 10345673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 10355673Saw148015 10365184Sek110237 /* XXX Add check to see if there is enough space */ 10375184Sek110237 10387736SAndrew.W.Wilson@sun.com /* set up path to fileset */ 10397946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, fileset_path, MAXPATHLEN); 10407946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 10417946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, fileset_name, MAXPATHLEN); 10427736SAndrew.W.Wilson@sun.com 10437736SAndrew.W.Wilson@sun.com /* if exists and resusing, then don't create new */ 10447736SAndrew.W.Wilson@sun.com if (((stat64(path, &sb) == 0)&& (strlen(path) > 3) && 10457736SAndrew.W.Wilson@sun.com (strlen(avd_get_str(fileset->fs_path)) > 2)) && 10467736SAndrew.W.Wilson@sun.com avd_get_bool(fileset->fs_reuse)) { 10477736SAndrew.W.Wilson@sun.com reusing = 1; 10487736SAndrew.W.Wilson@sun.com } else { 10497736SAndrew.W.Wilson@sun.com reusing = 0; 10507736SAndrew.W.Wilson@sun.com } 10517736SAndrew.W.Wilson@sun.com 10527736SAndrew.W.Wilson@sun.com if (!reusing) { 10537736SAndrew.W.Wilson@sun.com char cmd[MAXPATHLEN]; 10545184Sek110237 10557736SAndrew.W.Wilson@sun.com /* Remove existing */ 10567736SAndrew.W.Wilson@sun.com (void) snprintf(cmd, sizeof (cmd), "rm -rf %s", path); 10577736SAndrew.W.Wilson@sun.com (void) system(cmd); 10587736SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, 10597736SAndrew.W.Wilson@sun.com "Removed any existing %s %s in %llu seconds", 10607736SAndrew.W.Wilson@sun.com fileset_entity_name(fileset), fileset_name, 10617736SAndrew.W.Wilson@sun.com (u_longlong_t)(((gethrtime() - start) / 10627736SAndrew.W.Wilson@sun.com 1000000000) + 1)); 10637736SAndrew.W.Wilson@sun.com } else { 10647736SAndrew.W.Wilson@sun.com /* we are re-using */ 10657736SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, "Re-using %s %s.", 10667736SAndrew.W.Wilson@sun.com fileset_entity_name(fileset), fileset_name); 10675184Sek110237 } 10687736SAndrew.W.Wilson@sun.com 10697736SAndrew.W.Wilson@sun.com /* make the filesets directory tree unless in reuse mode */ 10707736SAndrew.W.Wilson@sun.com if (!reusing && (avd_get_bool(fileset->fs_prealloc))) { 10717946SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, 10727736SAndrew.W.Wilson@sun.com "making tree for filset %s", path); 10735184Sek110237 10747736SAndrew.W.Wilson@sun.com (void) mkdir(path, 0755); 10757736SAndrew.W.Wilson@sun.com 10767736SAndrew.W.Wilson@sun.com if (fileset_create_subdirs(fileset, path) == FILEBENCH_ERROR) 10777736SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 10787736SAndrew.W.Wilson@sun.com } 10795673Saw148015 10805184Sek110237 start = gethrtime(); 10815184Sek110237 10825673Saw148015 filebench_log(LOG_VERBOSE, "Creating %s %s...", 10836212Saw148015 fileset_entity_name(fileset), fileset_name); 10845673Saw148015 10856212Saw148015 randno = ((RAND_MAX * (100 10866212Saw148015 - avd_get_int(fileset->fs_preallocpercent))) / 100); 10876212Saw148015 10887946SAndrew.W.Wilson@sun.com /* alloc any files, as required */ 1089*8404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset, FILESET_PICKFILE); 1090*8404SAndrew.W.Wilson@sun.com while (entry = fileset_pick(fileset, 1091*8404SAndrew.W.Wilson@sun.com FILESET_PICKFREE | FILESET_PICKFILE, 0, 0)) { 10925673Saw148015 pthread_t tid; 10937736SAndrew.W.Wilson@sun.com int newrand; 10945184Sek110237 10957736SAndrew.W.Wilson@sun.com newrand = rand(); 10967736SAndrew.W.Wilson@sun.com 1097*8404SAndrew.W.Wilson@sun.com if (newrand < randno) { 1098*8404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 1099*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 11005184Sek110237 continue; 1101*8404SAndrew.W.Wilson@sun.com } 11025184Sek110237 11035184Sek110237 preallocated++; 11045184Sek110237 11055673Saw148015 if (reusing) 11065673Saw148015 entry->fse_flags |= FSE_REUSING; 11075673Saw148015 else 11085673Saw148015 entry->fse_flags &= (~FSE_REUSING); 11095673Saw148015 11107556SAndrew.W.Wilson@sun.com /* fire off allocation threads for each file if paralloc set */ 11116212Saw148015 if (avd_get_bool(fileset->fs_paralloc)) { 11125184Sek110237 11137556SAndrew.W.Wilson@sun.com /* limit total number of simultaneous allocations */ 11147556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock( 11157556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11167556SAndrew.W.Wilson@sun.com while (filebench_shm->shm_fsparalloc_count 11177556SAndrew.W.Wilson@sun.com >= MAX_PARALLOC_THREADS) { 11185673Saw148015 (void) pthread_cond_wait( 11197556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 11207556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11215673Saw148015 } 11225673Saw148015 11237556SAndrew.W.Wilson@sun.com /* quit if any allocation thread reports and error */ 11247556SAndrew.W.Wilson@sun.com if (filebench_shm->shm_fsparalloc_count < 0) { 11257556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock( 11267556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11277556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11285184Sek110237 } 11295184Sek110237 11307556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count++; 11317556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock( 11327556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11335184Sek110237 11347556SAndrew.W.Wilson@sun.com /* 11357556SAndrew.W.Wilson@sun.com * Fire off a detached allocation thread per file. 11367556SAndrew.W.Wilson@sun.com * The thread will self destruct when it finishes 11377556SAndrew.W.Wilson@sun.com * writing pre-allocation data to the file. 11387556SAndrew.W.Wilson@sun.com */ 11395673Saw148015 if (pthread_create(&tid, NULL, 11405673Saw148015 (void *(*)(void*))fileset_alloc_thread, 11417556SAndrew.W.Wilson@sun.com entry) == 0) { 11427556SAndrew.W.Wilson@sun.com /* 11437556SAndrew.W.Wilson@sun.com * A thread was created; detach it so it can 11447556SAndrew.W.Wilson@sun.com * fully quit when finished. 11457556SAndrew.W.Wilson@sun.com */ 11467556SAndrew.W.Wilson@sun.com (void) pthread_detach(tid); 11477556SAndrew.W.Wilson@sun.com } else { 11485184Sek110237 filebench_log(LOG_ERROR, 11495673Saw148015 "File prealloc thread create failed"); 11505673Saw148015 filebench_shutdown(1); 11515184Sek110237 } 11525184Sek110237 11535673Saw148015 } else { 11547556SAndrew.W.Wilson@sun.com if (fileset_alloc_file(entry) == FILEBENCH_ERROR) 11557556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11565673Saw148015 } 11575673Saw148015 } 11585184Sek110237 11597946SAndrew.W.Wilson@sun.com /* alloc any leaf directories, as required */ 1160*8404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset, FILESET_PICKLEAFDIR); 1161*8404SAndrew.W.Wilson@sun.com while (entry = fileset_pick(fileset, 1162*8404SAndrew.W.Wilson@sun.com FILESET_PICKFREE | FILESET_PICKLEAFDIR, 0, 0)) { 11637946SAndrew.W.Wilson@sun.com 1164*8404SAndrew.W.Wilson@sun.com if (rand() < randno) { 1165*8404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 1166*8404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 11677946SAndrew.W.Wilson@sun.com continue; 1168*8404SAndrew.W.Wilson@sun.com } 11697946SAndrew.W.Wilson@sun.com 11707946SAndrew.W.Wilson@sun.com preallocated++; 11717946SAndrew.W.Wilson@sun.com 11727946SAndrew.W.Wilson@sun.com if (reusing) 11737946SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_REUSING; 11747946SAndrew.W.Wilson@sun.com else 11757946SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_REUSING); 11767946SAndrew.W.Wilson@sun.com 11777946SAndrew.W.Wilson@sun.com if (fileset_alloc_leafdir(entry) == FILEBENCH_ERROR) 11787946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11797946SAndrew.W.Wilson@sun.com } 11807946SAndrew.W.Wilson@sun.com 11815673Saw148015 exit: 11825184Sek110237 filebench_log(LOG_VERBOSE, 11836286Saw148015 "Preallocated %d of %llu of %s %s in %llu seconds", 11845184Sek110237 preallocated, 11856286Saw148015 (u_longlong_t)fileset->fs_constentries, 11866212Saw148015 fileset_entity_name(fileset), fileset_name, 11876286Saw148015 (u_longlong_t)(((gethrtime() - start) / 1000000000) + 1)); 11885184Sek110237 11897556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 11905184Sek110237 } 11915184Sek110237 11925184Sek110237 /* 11935184Sek110237 * Adds an entry to the fileset's file list. Single threaded so 11945184Sek110237 * no locking needed. 11955184Sek110237 */ 11965184Sek110237 static void 11975184Sek110237 fileset_insfilelist(fileset_t *fileset, filesetentry_t *entry) 11985184Sek110237 { 1199*8404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_FILE | FSE_FREE; 1200*8404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_free_files, entry); 1201*8404SAndrew.W.Wilson@sun.com 12025184Sek110237 if (fileset->fs_filelist == NULL) { 12035184Sek110237 fileset->fs_filelist = entry; 1204*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12055184Sek110237 } else { 1206*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_filelist; 12075184Sek110237 fileset->fs_filelist = entry; 12085184Sek110237 } 12095184Sek110237 } 12105184Sek110237 12115184Sek110237 /* 12125184Sek110237 * Adds an entry to the fileset's directory list. Single 12135184Sek110237 * threaded so no locking needed. 12145184Sek110237 */ 12155184Sek110237 static void 12165184Sek110237 fileset_insdirlist(fileset_t *fileset, filesetentry_t *entry) 12175184Sek110237 { 1218*8404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_DIR | FSE_EXISTS; 1219*8404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_dirs, entry); 1220*8404SAndrew.W.Wilson@sun.com 12215184Sek110237 if (fileset->fs_dirlist == NULL) { 12225184Sek110237 fileset->fs_dirlist = entry; 1223*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12245184Sek110237 } else { 1225*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_dirlist; 12265184Sek110237 fileset->fs_dirlist = entry; 12275184Sek110237 } 12285184Sek110237 } 12295184Sek110237 12305184Sek110237 /* 12317946SAndrew.W.Wilson@sun.com * Adds an entry to the fileset's leaf directory list. Single 12327946SAndrew.W.Wilson@sun.com * threaded so no locking needed. 12337946SAndrew.W.Wilson@sun.com */ 12347946SAndrew.W.Wilson@sun.com static void 12357946SAndrew.W.Wilson@sun.com fileset_insleafdirlist(fileset_t *fileset, filesetentry_t *entry) 12367946SAndrew.W.Wilson@sun.com { 1237*8404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_LEAFDIR | FSE_FREE; 1238*8404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_free_leaf_dirs, entry); 1239*8404SAndrew.W.Wilson@sun.com 12407946SAndrew.W.Wilson@sun.com if (fileset->fs_leafdirlist == NULL) { 12417946SAndrew.W.Wilson@sun.com fileset->fs_leafdirlist = entry; 1242*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12437946SAndrew.W.Wilson@sun.com } else { 1244*8404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_leafdirlist; 12457946SAndrew.W.Wilson@sun.com fileset->fs_leafdirlist = entry; 12467946SAndrew.W.Wilson@sun.com } 12477946SAndrew.W.Wilson@sun.com } 12487946SAndrew.W.Wilson@sun.com 12497946SAndrew.W.Wilson@sun.com /* 1250*8404SAndrew.W.Wilson@sun.com * Compares two fileset entries to determine their relative order 1251*8404SAndrew.W.Wilson@sun.com */ 1252*8404SAndrew.W.Wilson@sun.com static int 1253*8404SAndrew.W.Wilson@sun.com fileset_entry_compare(const void *node_1, const void *node_2) 1254*8404SAndrew.W.Wilson@sun.com { 1255*8404SAndrew.W.Wilson@sun.com if (((filesetentry_t *)node_1)->fse_index < 1256*8404SAndrew.W.Wilson@sun.com ((filesetentry_t *)node_2)->fse_index) 1257*8404SAndrew.W.Wilson@sun.com return (-1); 1258*8404SAndrew.W.Wilson@sun.com 1259*8404SAndrew.W.Wilson@sun.com if (((filesetentry_t *)node_1)->fse_index == 1260*8404SAndrew.W.Wilson@sun.com ((filesetentry_t *)node_2)->fse_index) 1261*8404SAndrew.W.Wilson@sun.com return (0); 1262*8404SAndrew.W.Wilson@sun.com 1263*8404SAndrew.W.Wilson@sun.com return (1); 1264*8404SAndrew.W.Wilson@sun.com } 1265*8404SAndrew.W.Wilson@sun.com 1266*8404SAndrew.W.Wilson@sun.com /* 12677946SAndrew.W.Wilson@sun.com * Obtains a filesetentry entity for a file to be placed in a 12685184Sek110237 * (sub)directory of a fileset. The size of the file may be 12696212Saw148015 * specified by fileset_meansize, or calculated from a gamma 12706212Saw148015 * distribution of parameter fileset_sizegamma and of mean size 12716212Saw148015 * fileset_meansize. The filesetentry entity is placed on the file 12725184Sek110237 * list in the specified parent filesetentry entity, which may 12735184Sek110237 * be a directory filesetentry, or the root filesetentry in the 12745184Sek110237 * fileset. It is also placed on the fileset's list of all 12757556SAndrew.W.Wilson@sun.com * contained files. Returns FILEBENCH_OK if successful or FILEBENCH_ERROR 12767556SAndrew.W.Wilson@sun.com * if ipc memory for the path string cannot be allocated. 12775184Sek110237 */ 12785184Sek110237 static int 12795184Sek110237 fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial) 12805184Sek110237 { 12815184Sek110237 char tmpname[16]; 12825184Sek110237 filesetentry_t *entry; 12835184Sek110237 double drand; 1284*8404SAndrew.W.Wilson@sun.com uint_t index; 12855184Sek110237 12865184Sek110237 if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 12875184Sek110237 == NULL) { 12885184Sek110237 filebench_log(LOG_ERROR, 12895184Sek110237 "fileset_populate_file: Can't malloc filesetentry"); 12907556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 12915184Sek110237 } 12925184Sek110237 12937556SAndrew.W.Wilson@sun.com /* Another currently idle file */ 12947556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 1295*8404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_files++; 12967556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 12977556SAndrew.W.Wilson@sun.com 1298*8404SAndrew.W.Wilson@sun.com entry->fse_index = index; 12995184Sek110237 entry->fse_parent = parent; 13005184Sek110237 entry->fse_fileset = fileset; 13015184Sek110237 fileset_insfilelist(fileset, entry); 13025184Sek110237 13035184Sek110237 (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 13045184Sek110237 if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 13055184Sek110237 filebench_log(LOG_ERROR, 13065184Sek110237 "fileset_populate_file: Can't alloc path string"); 13077556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 13085184Sek110237 } 13095184Sek110237 13106212Saw148015 /* see if random variable was supplied for file size */ 13116212Saw148015 if (fileset->fs_meansize == -1) { 13126212Saw148015 entry->fse_size = (off64_t)avd_get_int(fileset->fs_size); 13136212Saw148015 } else { 13146212Saw148015 double gamma; 13155184Sek110237 13166212Saw148015 gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0; 13176212Saw148015 if (gamma > 0) { 13186212Saw148015 drand = gamma_dist_knuth(gamma, 13196212Saw148015 fileset->fs_meansize / gamma); 13206212Saw148015 entry->fse_size = (off64_t)drand; 13216212Saw148015 } else { 13226212Saw148015 entry->fse_size = (off64_t)fileset->fs_meansize; 13236212Saw148015 } 13245184Sek110237 } 13255184Sek110237 13265184Sek110237 fileset->fs_bytes += entry->fse_size; 13275184Sek110237 13285184Sek110237 fileset->fs_realfiles++; 13297556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 13305184Sek110237 } 13315184Sek110237 13325184Sek110237 /* 13337946SAndrew.W.Wilson@sun.com * Obtaines a filesetentry entity for a leaf directory to be placed in a 13347946SAndrew.W.Wilson@sun.com * (sub)directory of a fileset. The leaf directory will always be empty so 13357946SAndrew.W.Wilson@sun.com * it can be created and deleted (mkdir, rmdir) at will. The filesetentry 13367946SAndrew.W.Wilson@sun.com * entity is placed on the leaf directory list in the specified parent 13377946SAndrew.W.Wilson@sun.com * filesetentry entity, which may be a (sub) directory filesetentry, or 13387946SAndrew.W.Wilson@sun.com * the root filesetentry in the fileset. It is also placed on the fileset's 13397946SAndrew.W.Wilson@sun.com * list of all contained leaf directories. Returns FILEBENCH_OK if successful 13407946SAndrew.W.Wilson@sun.com * or FILEBENCH_ERROR if ipc memory cannot be allocated. 13417946SAndrew.W.Wilson@sun.com */ 13427946SAndrew.W.Wilson@sun.com static int 13437946SAndrew.W.Wilson@sun.com fileset_populate_leafdir(fileset_t *fileset, filesetentry_t *parent, int serial) 13447946SAndrew.W.Wilson@sun.com { 13457946SAndrew.W.Wilson@sun.com char tmpname[16]; 13467946SAndrew.W.Wilson@sun.com filesetentry_t *entry; 1347*8404SAndrew.W.Wilson@sun.com uint_t index; 13487946SAndrew.W.Wilson@sun.com 13497946SAndrew.W.Wilson@sun.com if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 13507946SAndrew.W.Wilson@sun.com == NULL) { 13517946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 13527946SAndrew.W.Wilson@sun.com "fileset_populate_file: Can't malloc filesetentry"); 13537946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 13547946SAndrew.W.Wilson@sun.com } 13557946SAndrew.W.Wilson@sun.com 13567946SAndrew.W.Wilson@sun.com /* Another currently idle leaf directory */ 13577946SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 1358*8404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_leafdirs++; 13597946SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 13607946SAndrew.W.Wilson@sun.com 1361*8404SAndrew.W.Wilson@sun.com entry->fse_index = index; 13627946SAndrew.W.Wilson@sun.com entry->fse_parent = parent; 13637946SAndrew.W.Wilson@sun.com entry->fse_fileset = fileset; 13647946SAndrew.W.Wilson@sun.com fileset_insleafdirlist(fileset, entry); 13657946SAndrew.W.Wilson@sun.com 13667946SAndrew.W.Wilson@sun.com (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 13677946SAndrew.W.Wilson@sun.com if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 13687946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 13697946SAndrew.W.Wilson@sun.com "fileset_populate_file: Can't alloc path string"); 13707946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 13717946SAndrew.W.Wilson@sun.com } 13727946SAndrew.W.Wilson@sun.com 13737946SAndrew.W.Wilson@sun.com fileset->fs_realleafdirs++; 13747946SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 13757946SAndrew.W.Wilson@sun.com } 13767946SAndrew.W.Wilson@sun.com 13777946SAndrew.W.Wilson@sun.com /* 13785184Sek110237 * Creates a directory node in a fileset, by obtaining a 13795184Sek110237 * filesetentry entity for the node and initializing it 13805184Sek110237 * according to parameters of the fileset. It determines a 13815184Sek110237 * directory tree depth and directory width, optionally using 13825184Sek110237 * a gamma distribution. If its calculated depth is less then 13835184Sek110237 * its actual depth in the directory tree, it becomes a leaf 13845184Sek110237 * node and files itself with "width" number of file type 13855184Sek110237 * filesetentries, otherwise it files itself with "width" 13865184Sek110237 * number of directory type filesetentries, using recursive 13875184Sek110237 * calls to fileset_populate_subdir. The end result of the 13885184Sek110237 * initial call to this routine is a tree of directories of 13895184Sek110237 * random width and varying depth with sufficient leaf 13905184Sek110237 * directories to contain all required files. 13917556SAndrew.W.Wilson@sun.com * Returns FILEBENCH_OK on success. Returns FILEBENCH_ERROR if ipc path 13927556SAndrew.W.Wilson@sun.com * string memory cannot be allocated and returns the error code (currently 13937556SAndrew.W.Wilson@sun.com * also FILEBENCH_ERROR) from calls to fileset_populate_file or recursive 13945184Sek110237 * calls to fileset_populate_subdir. 13955184Sek110237 */ 13965184Sek110237 static int 13975184Sek110237 fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, 13985184Sek110237 int serial, double depth) 13995184Sek110237 { 14006212Saw148015 double randepth, drand, ranwidth; 14015184Sek110237 int isleaf = 0; 14025184Sek110237 char tmpname[16]; 14035184Sek110237 filesetentry_t *entry; 14045184Sek110237 int i; 1405*8404SAndrew.W.Wilson@sun.com uint_t index; 14065184Sek110237 14075184Sek110237 depth += 1; 14085184Sek110237 14095184Sek110237 /* Create dir node */ 14105184Sek110237 if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 14115184Sek110237 == NULL) { 14125184Sek110237 filebench_log(LOG_ERROR, 14135184Sek110237 "fileset_populate_subdir: Can't malloc filesetentry"); 14147556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14155184Sek110237 } 14165184Sek110237 14177556SAndrew.W.Wilson@sun.com /* another idle directory */ 14187556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 1419*8404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_dirs++; 14207556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 14215184Sek110237 14225184Sek110237 (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 14235184Sek110237 if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 14245184Sek110237 filebench_log(LOG_ERROR, 14255184Sek110237 "fileset_populate_subdir: Can't alloc path string"); 14267556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14275184Sek110237 } 14285184Sek110237 1429*8404SAndrew.W.Wilson@sun.com entry->fse_index = index; 14305184Sek110237 entry->fse_parent = parent; 14317946SAndrew.W.Wilson@sun.com entry->fse_fileset = fileset; 14325184Sek110237 fileset_insdirlist(fileset, entry); 14335184Sek110237 14346212Saw148015 if (fileset->fs_dirdepthrv) { 14356212Saw148015 randepth = (int)avd_get_int(fileset->fs_dirdepthrv); 14365184Sek110237 } else { 14376212Saw148015 double gamma; 14386212Saw148015 14396212Saw148015 gamma = avd_get_int(fileset->fs_dirgamma) / 1000.0; 14406212Saw148015 if (gamma > 0) { 14416212Saw148015 drand = gamma_dist_knuth(gamma, 14426212Saw148015 fileset->fs_meandepth / gamma); 14436212Saw148015 randepth = (int)drand; 14446212Saw148015 } else { 14456212Saw148015 randepth = (int)fileset->fs_meandepth; 14466212Saw148015 } 14475184Sek110237 } 14485184Sek110237 14496212Saw148015 if (fileset->fs_meanwidth == -1) { 14506212Saw148015 ranwidth = avd_get_dbl(fileset->fs_dirwidth); 14516212Saw148015 } else { 14526212Saw148015 double gamma; 14535184Sek110237 14546212Saw148015 gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0; 14556212Saw148015 if (gamma > 0) { 14566212Saw148015 drand = gamma_dist_knuth(gamma, 14576212Saw148015 fileset->fs_meanwidth / gamma); 14586212Saw148015 ranwidth = drand; 14596212Saw148015 } else { 14606212Saw148015 ranwidth = fileset->fs_meanwidth; 14616212Saw148015 } 14625184Sek110237 } 14635184Sek110237 14645184Sek110237 if (randepth == 0) 14655184Sek110237 randepth = 1; 14665184Sek110237 if (ranwidth == 0) 14675184Sek110237 ranwidth = 1; 14685184Sek110237 if (depth >= randepth) 14695184Sek110237 isleaf = 1; 14705184Sek110237 14715184Sek110237 /* 14727946SAndrew.W.Wilson@sun.com * Create directory of random width filled with files according 14737946SAndrew.W.Wilson@sun.com * to distribution, or if root directory, continue until #files required 14745184Sek110237 */ 14756212Saw148015 for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && 14766212Saw148015 (fileset->fs_realfiles < fileset->fs_constentries); 14776212Saw148015 i++) { 14785184Sek110237 int ret = 0; 14795184Sek110237 14805184Sek110237 if (parent && isleaf) 14815184Sek110237 ret = fileset_populate_file(fileset, entry, i); 14825184Sek110237 else 14835184Sek110237 ret = fileset_populate_subdir(fileset, entry, i, depth); 14845184Sek110237 14855184Sek110237 if (ret != 0) 14865184Sek110237 return (ret); 14875184Sek110237 } 14887946SAndrew.W.Wilson@sun.com 14897946SAndrew.W.Wilson@sun.com /* 14907946SAndrew.W.Wilson@sun.com * Create directory of random width filled with leaf directories 14917946SAndrew.W.Wilson@sun.com * according to distribution, or if root directory, continue until 14927946SAndrew.W.Wilson@sun.com * the number of leaf directories required has been generated. 14937946SAndrew.W.Wilson@sun.com */ 14947946SAndrew.W.Wilson@sun.com for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && 14957946SAndrew.W.Wilson@sun.com (fileset->fs_realleafdirs < fileset->fs_constleafdirs); 14967946SAndrew.W.Wilson@sun.com i++) { 14977946SAndrew.W.Wilson@sun.com int ret = 0; 14987946SAndrew.W.Wilson@sun.com 14997946SAndrew.W.Wilson@sun.com if (parent && isleaf) 15007946SAndrew.W.Wilson@sun.com ret = fileset_populate_leafdir(fileset, entry, i); 15017946SAndrew.W.Wilson@sun.com else 15027946SAndrew.W.Wilson@sun.com ret = fileset_populate_subdir(fileset, entry, i, depth); 15037946SAndrew.W.Wilson@sun.com 15047946SAndrew.W.Wilson@sun.com if (ret != 0) 15057946SAndrew.W.Wilson@sun.com return (ret); 15067946SAndrew.W.Wilson@sun.com } 15077946SAndrew.W.Wilson@sun.com 15087556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 15095184Sek110237 } 15105184Sek110237 15115184Sek110237 /* 15125184Sek110237 * Populates a fileset with files and subdirectory entries. Uses 15136212Saw148015 * the supplied fileset_dirwidth and fileset_entries (number of files) to 15146212Saw148015 * calculate the required fileset_meandepth (of subdirectories) and 15156212Saw148015 * initialize the fileset_meanwidth and fileset_meansize variables. Then 15165184Sek110237 * calls fileset_populate_subdir() to do the recursive 15175184Sek110237 * subdirectory entry creation and leaf file entry creation. All 15185184Sek110237 * of the above is skipped if the fileset has already been 15195184Sek110237 * populated. Returns 0 on success, or an error code from the 15205184Sek110237 * call to fileset_populate_subdir if that call fails. 15215184Sek110237 */ 15225184Sek110237 static int 15235184Sek110237 fileset_populate(fileset_t *fileset) 15245184Sek110237 { 1525*8404SAndrew.W.Wilson@sun.com fbint_t entries = avd_get_int(fileset->fs_entries); 1526*8404SAndrew.W.Wilson@sun.com fbint_t leafdirs = avd_get_int(fileset->fs_leafdirs); 15276212Saw148015 int meandirwidth; 15285184Sek110237 int ret; 15295184Sek110237 15305184Sek110237 /* Skip if already populated */ 15315184Sek110237 if (fileset->fs_bytes > 0) 15325184Sek110237 goto exists; 15335184Sek110237 15345673Saw148015 #ifdef HAVE_RAW_SUPPORT 15355673Saw148015 /* check for raw device */ 15365673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) 15377556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 15385673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 15395673Saw148015 15407946SAndrew.W.Wilson@sun.com /* 15417946SAndrew.W.Wilson@sun.com * save value of entries and leaf dirs obtained for later 15427946SAndrew.W.Wilson@sun.com * in case it was random 15437946SAndrew.W.Wilson@sun.com */ 15446212Saw148015 fileset->fs_constentries = entries; 15457946SAndrew.W.Wilson@sun.com fileset->fs_constleafdirs = leafdirs; 15466212Saw148015 15477556SAndrew.W.Wilson@sun.com /* initialize idle files and directories condition variables */ 15487946SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_files_cv, ipc_condattr()); 15497556SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_dirs_cv, ipc_condattr()); 15507946SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_leafdirs_cv, ipc_condattr()); 15517556SAndrew.W.Wilson@sun.com 15527556SAndrew.W.Wilson@sun.com /* no files or dirs idle (or busy) yet */ 15537556SAndrew.W.Wilson@sun.com fileset->fs_idle_files = 0; 15547556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs = 0; 15557946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs = 0; 15567556SAndrew.W.Wilson@sun.com 15577556SAndrew.W.Wilson@sun.com /* initialize locks and other condition variables */ 15587556SAndrew.W.Wilson@sun.com (void) pthread_mutex_init(&fileset->fs_pick_lock, 15597556SAndrew.W.Wilson@sun.com ipc_mutexattr(IPC_MUTEX_NORMAL)); 1560*8404SAndrew.W.Wilson@sun.com (void) pthread_mutex_init(&fileset->fs_histo_lock, 1561*8404SAndrew.W.Wilson@sun.com ipc_mutexattr(IPC_MUTEX_NORMAL)); 15627556SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_thrd_wait_cv, ipc_condattr()); 15637556SAndrew.W.Wilson@sun.com 1564*8404SAndrew.W.Wilson@sun.com /* Initialize avl btrees */ 1565*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_free_files), fileset_entry_compare, 1566*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1567*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_noex_files), fileset_entry_compare, 1568*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1569*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_exist_files), fileset_entry_compare, 1570*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1571*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_free_leaf_dirs), fileset_entry_compare, 1572*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1573*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_noex_leaf_dirs), fileset_entry_compare, 1574*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1575*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_exist_leaf_dirs), fileset_entry_compare, 1576*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1577*8404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_dirs), fileset_entry_compare, 1578*8404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 1579*8404SAndrew.W.Wilson@sun.com 15806212Saw148015 /* is dirwidth a random variable? */ 15816212Saw148015 if (AVD_IS_RANDOM(fileset->fs_dirwidth)) { 15826212Saw148015 meandirwidth = 15836212Saw148015 (int)fileset->fs_dirwidth->avd_val.randptr->rnd_dbl_mean; 15846212Saw148015 fileset->fs_meanwidth = -1; 15856212Saw148015 } else { 15866212Saw148015 meandirwidth = (int)avd_get_int(fileset->fs_dirwidth); 15876212Saw148015 fileset->fs_meanwidth = (double)meandirwidth; 15886212Saw148015 } 15896212Saw148015 15905184Sek110237 /* 15915184Sek110237 * Input params are: 15925184Sek110237 * # of files 15935184Sek110237 * ave # of files per dir 15945184Sek110237 * max size of dir 15955184Sek110237 * # ave size of file 15965184Sek110237 * max size of file 15975184Sek110237 */ 15987946SAndrew.W.Wilson@sun.com fileset->fs_meandepth = log(entries+leafdirs) / log(meandirwidth); 15996212Saw148015 16006212Saw148015 /* Has a random variable been supplied for dirdepth? */ 16016212Saw148015 if (fileset->fs_dirdepthrv) { 16026212Saw148015 /* yes, so set the random variable's mean value to meandepth */ 16036212Saw148015 fileset->fs_dirdepthrv->avd_val.randptr->rnd_dbl_mean = 16046212Saw148015 fileset->fs_meandepth; 16056212Saw148015 } 16066212Saw148015 16076212Saw148015 /* test for random size variable */ 16086212Saw148015 if (AVD_IS_RANDOM(fileset->fs_size)) 16096212Saw148015 fileset->fs_meansize = -1; 16106212Saw148015 else 16116212Saw148015 fileset->fs_meansize = avd_get_int(fileset->fs_size); 16125184Sek110237 16135184Sek110237 if ((ret = fileset_populate_subdir(fileset, NULL, 1, 0)) != 0) 16145184Sek110237 return (ret); 16155184Sek110237 16165184Sek110237 16175184Sek110237 exists: 16185673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) { 16196286Saw148015 filebench_log(LOG_VERBOSE, "File %s: mbytes=%llu", 16206212Saw148015 avd_get_str(fileset->fs_name), 16216286Saw148015 (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); 16225673Saw148015 } else { 16237946SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, "Fileset %s: %d files, %d leafdirs " 16246286Saw148015 "avg dir = %d, avg depth = %.1lf, mbytes=%llu", 16257946SAndrew.W.Wilson@sun.com avd_get_str(fileset->fs_name), entries, leafdirs, 16266212Saw148015 meandirwidth, 16275673Saw148015 fileset->fs_meandepth, 16286286Saw148015 (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); 16295673Saw148015 } 16306701Saw148015 16317556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 16325184Sek110237 } 16335184Sek110237 16345184Sek110237 /* 16356212Saw148015 * Allocates a fileset instance, initializes fileset_dirgamma and 16366212Saw148015 * fileset_sizegamma default values, and sets the fileset name to the 16375184Sek110237 * supplied name string. Puts the allocated fileset on the 16385184Sek110237 * master fileset list and returns a pointer to it. 16396701Saw148015 * 16406701Saw148015 * This routine implements the 'define fileset' calls found in a .f 16416701Saw148015 * workload, such as in the following example: 16426701Saw148015 * define fileset name=drew4ever, entries=$nfiles 16435184Sek110237 */ 16445184Sek110237 fileset_t * 16456212Saw148015 fileset_define(avd_t name) 16465184Sek110237 { 16475184Sek110237 fileset_t *fileset; 16485184Sek110237 16495184Sek110237 if (name == NULL) 16505184Sek110237 return (NULL); 16515184Sek110237 16525184Sek110237 if ((fileset = (fileset_t *)ipc_malloc(FILEBENCH_FILESET)) == NULL) { 16535184Sek110237 filebench_log(LOG_ERROR, 16545184Sek110237 "fileset_define: Can't malloc fileset"); 16555184Sek110237 return (NULL); 16565184Sek110237 } 16575184Sek110237 16586212Saw148015 filebench_log(LOG_DEBUG_IMPL, 16596212Saw148015 "Defining file %s", avd_get_str(name)); 16605184Sek110237 16616391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 16625184Sek110237 16636212Saw148015 fileset->fs_dirgamma = avd_int_alloc(1500); 16646212Saw148015 fileset->fs_sizegamma = avd_int_alloc(1500); 1665*8404SAndrew.W.Wilson@sun.com fileset->fs_histo_id = -1; 16665184Sek110237 16675184Sek110237 /* Add fileset to global list */ 16686391Saw148015 if (filebench_shm->shm_filesetlist == NULL) { 16696391Saw148015 filebench_shm->shm_filesetlist = fileset; 16705184Sek110237 fileset->fs_next = NULL; 16715184Sek110237 } else { 16726391Saw148015 fileset->fs_next = filebench_shm->shm_filesetlist; 16736391Saw148015 filebench_shm->shm_filesetlist = fileset; 16745184Sek110237 } 16755184Sek110237 16766391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 16775184Sek110237 16786212Saw148015 fileset->fs_name = name; 16795184Sek110237 16805184Sek110237 return (fileset); 16815184Sek110237 } 16825184Sek110237 16835184Sek110237 /* 16845184Sek110237 * If supplied with a pointer to a fileset and the fileset's 16856212Saw148015 * fileset_prealloc flag is set, calls fileset_populate() to populate 16865184Sek110237 * the fileset with filesetentries, then calls fileset_create() 16875184Sek110237 * to make actual directories and files for the filesetentries. 16885184Sek110237 * Otherwise, it applies fileset_populate() and fileset_create() 16895184Sek110237 * to all the filesets on the master fileset list. It always 16905184Sek110237 * returns zero (0) if one fileset is populated / created, 16915184Sek110237 * otherwise it returns the sum of returned values from 16925184Sek110237 * fileset_create() and fileset_populate(), which 16935184Sek110237 * will be a negative one (-1) times the number of 16945184Sek110237 * fileset_create() calls which failed. 16955184Sek110237 */ 16965184Sek110237 int 16975184Sek110237 fileset_createset(fileset_t *fileset) 16985184Sek110237 { 16995184Sek110237 fileset_t *list; 17005184Sek110237 int ret = 0; 17015184Sek110237 17025673Saw148015 /* set up for possible parallel allocate */ 17037556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count = 0; 17047556SAndrew.W.Wilson@sun.com (void) pthread_cond_init( 17057556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 17067556SAndrew.W.Wilson@sun.com ipc_condattr()); 17075673Saw148015 17086212Saw148015 if (fileset && avd_get_bool(fileset->fs_prealloc)) { 17095673Saw148015 17106305Saw148015 /* check for raw files */ 17116305Saw148015 if (fileset_checkraw(fileset)) { 17126305Saw148015 filebench_log(LOG_INFO, 17136305Saw148015 "file %s/%s is a RAW device", 17146305Saw148015 avd_get_str(fileset->fs_path), 17156305Saw148015 avd_get_str(fileset->fs_name)); 17167556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 17176305Saw148015 } 17186305Saw148015 17195673Saw148015 filebench_log(LOG_INFO, 17205673Saw148015 "creating/pre-allocating %s %s", 17216212Saw148015 fileset_entity_name(fileset), 17226212Saw148015 avd_get_str(fileset->fs_name)); 17235673Saw148015 17247556SAndrew.W.Wilson@sun.com if ((ret = fileset_populate(fileset)) != FILEBENCH_OK) 17255184Sek110237 return (ret); 17265673Saw148015 17277556SAndrew.W.Wilson@sun.com if ((ret = fileset_create(fileset)) != FILEBENCH_OK) 17285673Saw148015 return (ret); 17295673Saw148015 } else { 17305673Saw148015 17315673Saw148015 filebench_log(LOG_INFO, 17325673Saw148015 "Creating/pre-allocating files and filesets"); 17335673Saw148015 17346391Saw148015 list = filebench_shm->shm_filesetlist; 17355673Saw148015 while (list) { 17366305Saw148015 /* check for raw files */ 17376305Saw148015 if (fileset_checkraw(list)) { 17386305Saw148015 filebench_log(LOG_INFO, 17396305Saw148015 "file %s/%s is a RAW device", 17406305Saw148015 avd_get_str(list->fs_path), 17416305Saw148015 avd_get_str(list->fs_name)); 17426305Saw148015 list = list->fs_next; 17436305Saw148015 continue; 17446305Saw148015 } 17456305Saw148015 17467556SAndrew.W.Wilson@sun.com if ((ret = fileset_populate(list)) != FILEBENCH_OK) 17475673Saw148015 return (ret); 17487556SAndrew.W.Wilson@sun.com 17497556SAndrew.W.Wilson@sun.com if ((ret = fileset_create(list)) != FILEBENCH_OK) 17505673Saw148015 return (ret); 17517556SAndrew.W.Wilson@sun.com 17525673Saw148015 list = list->fs_next; 17535673Saw148015 } 17545184Sek110237 } 17555184Sek110237 17565673Saw148015 /* wait for allocation threads to finish */ 17575673Saw148015 filebench_log(LOG_INFO, 17585673Saw148015 "waiting for fileset pre-allocation to finish"); 17595184Sek110237 17607556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 17617556SAndrew.W.Wilson@sun.com while (filebench_shm->shm_fsparalloc_count > 0) 17627556SAndrew.W.Wilson@sun.com (void) pthread_cond_wait( 17637556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 17647556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 17657556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock(&filebench_shm->shm_fsparalloc_lock); 17665673Saw148015 17677556SAndrew.W.Wilson@sun.com if (filebench_shm->shm_fsparalloc_count < 0) 17687556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 17695673Saw148015 17707556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 17715184Sek110237 } 17725184Sek110237 17735184Sek110237 /* 17745184Sek110237 * Searches through the master fileset list for the named fileset. 17755184Sek110237 * If found, returns pointer to same, otherwise returns NULL. 17765184Sek110237 */ 17775184Sek110237 fileset_t * 17785184Sek110237 fileset_find(char *name) 17795184Sek110237 { 17806391Saw148015 fileset_t *fileset = filebench_shm->shm_filesetlist; 17815184Sek110237 17826391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 17835184Sek110237 17845184Sek110237 while (fileset) { 17856212Saw148015 if (strcmp(name, avd_get_str(fileset->fs_name)) == 0) { 17866391Saw148015 (void) ipc_mutex_unlock( 17876391Saw148015 &filebench_shm->shm_fileset_lock); 17885184Sek110237 return (fileset); 17895184Sek110237 } 17905184Sek110237 fileset = fileset->fs_next; 17915184Sek110237 } 17926391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 17935184Sek110237 17945184Sek110237 return (NULL); 17955184Sek110237 } 17965673Saw148015 17975673Saw148015 /* 17985673Saw148015 * Iterates over all the file sets in the filesetlist, 17995673Saw148015 * executing the supplied command "*cmd()" on them. Also 18005673Saw148015 * indicates to the executed command if it is the first 18015673Saw148015 * time the command has been executed since the current 18025673Saw148015 * call to fileset_iter. 18035673Saw148015 */ 1804*8404SAndrew.W.Wilson@sun.com int 18055673Saw148015 fileset_iter(int (*cmd)(fileset_t *fileset, int first)) 18065673Saw148015 { 18076391Saw148015 fileset_t *fileset = filebench_shm->shm_filesetlist; 18085673Saw148015 int count = 0; 18095673Saw148015 18106391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 18115673Saw148015 18125673Saw148015 while (fileset) { 1813*8404SAndrew.W.Wilson@sun.com if (cmd(fileset, count == 0) == FILEBENCH_ERROR) { 1814*8404SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock( 1815*8404SAndrew.W.Wilson@sun.com &filebench_shm->shm_fileset_lock); 1816*8404SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 1817*8404SAndrew.W.Wilson@sun.com } 18185673Saw148015 fileset = fileset->fs_next; 18195673Saw148015 count++; 18205673Saw148015 } 18215673Saw148015 18226391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 1823*8404SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 18245673Saw148015 } 18255673Saw148015 18265673Saw148015 /* 18275673Saw148015 * Prints information to the filebench log about the file 18285673Saw148015 * object. Also prints a header on the first call. 18295673Saw148015 */ 18305673Saw148015 int 18315673Saw148015 fileset_print(fileset_t *fileset, int first) 18325673Saw148015 { 18336212Saw148015 int pathlength; 18346212Saw148015 char *fileset_path; 18356212Saw148015 char *fileset_name; 18366212Saw148015 static char pad[] = " "; /* 30 spaces */ 18376212Saw148015 18386212Saw148015 if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) { 18396212Saw148015 filebench_log(LOG_ERROR, "%s path not set", 18406212Saw148015 fileset_entity_name(fileset)); 18417556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 18426212Saw148015 } 18436212Saw148015 18446212Saw148015 if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) { 18456212Saw148015 filebench_log(LOG_ERROR, "%s name not set", 18466212Saw148015 fileset_entity_name(fileset)); 18477556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 18486212Saw148015 } 18496212Saw148015 18506212Saw148015 pathlength = strlen(fileset_path) + strlen(fileset_name); 18515673Saw148015 18525673Saw148015 if (pathlength > 29) 18535673Saw148015 pathlength = 29; 18545673Saw148015 18555673Saw148015 if (first) { 18565673Saw148015 filebench_log(LOG_INFO, "File or Fileset name%20s%12s%10s", 18575673Saw148015 "file size", 18585673Saw148015 "dir width", 18595673Saw148015 "entries"); 18605673Saw148015 } 18615673Saw148015 18625673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) { 18635673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) { 18645673Saw148015 filebench_log(LOG_INFO, 18655673Saw148015 "%s/%s%s (Raw Device)", 18666212Saw148015 fileset_path, fileset_name, &pad[pathlength]); 18675673Saw148015 } else { 18685673Saw148015 filebench_log(LOG_INFO, 18696286Saw148015 "%s/%s%s%9llu (Single File)", 18706212Saw148015 fileset_path, fileset_name, &pad[pathlength], 18716286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_size)); 18725673Saw148015 } 18735673Saw148015 } else { 18746286Saw148015 filebench_log(LOG_INFO, "%s/%s%s%9llu%12llu%10llu", 18756212Saw148015 fileset_path, fileset_name, 18765673Saw148015 &pad[pathlength], 18776286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_size), 18786286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_dirwidth), 18796286Saw148015 (u_longlong_t)fileset->fs_constentries); 18805673Saw148015 } 18817556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 18825673Saw148015 } 18837946SAndrew.W.Wilson@sun.com 18845673Saw148015 /* 18855673Saw148015 * checks to see if the path/name pair points to a raw device. If 18865673Saw148015 * so it sets the raw device flag (FILESET_IS_RAW_DEV) and returns 1. 18875673Saw148015 * If RAW is not defined, or it is not a raw device, it clears the 18885673Saw148015 * raw device flag and returns 0. 18895673Saw148015 */ 18905673Saw148015 int 18915673Saw148015 fileset_checkraw(fileset_t *fileset) 18925673Saw148015 { 18935673Saw148015 char path[MAXPATHLEN]; 18945673Saw148015 struct stat64 sb; 18956305Saw148015 char *pathname; 18966305Saw148015 char *setname; 18975673Saw148015 18985673Saw148015 fileset->fs_attrs &= (~FILESET_IS_RAW_DEV); 18995673Saw148015 19005673Saw148015 #ifdef HAVE_RAW_SUPPORT 19015673Saw148015 /* check for raw device */ 19026305Saw148015 if ((pathname = avd_get_str(fileset->fs_path)) == NULL) 19037556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19046305Saw148015 19056305Saw148015 if ((setname = avd_get_str(fileset->fs_name)) == NULL) 19067556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19076305Saw148015 19087946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, pathname, MAXPATHLEN); 19097946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 19107946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, setname, MAXPATHLEN); 19115673Saw148015 if ((stat64(path, &sb) == 0) && 19125673Saw148015 ((sb.st_mode & S_IFMT) == S_IFBLK) && sb.st_rdev) { 19135673Saw148015 fileset->fs_attrs |= FILESET_IS_RAW_DEV; 19146305Saw148015 if (!(fileset->fs_attrs & FILESET_IS_FILE)) { 19156305Saw148015 filebench_log(LOG_ERROR, 19166305Saw148015 "WARNING Fileset %s/%s Cannot be RAW device", 19176305Saw148015 avd_get_str(fileset->fs_path), 19186305Saw148015 avd_get_str(fileset->fs_name)); 19196305Saw148015 filebench_shutdown(1); 19206305Saw148015 } 19216305Saw148015 19225673Saw148015 return (1); 19235673Saw148015 } 19245673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 19255673Saw148015 19267556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19275673Saw148015 } 1928