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 /* 228615SAndrew.W.Wilson@sun.com * Copyright 2009 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> 348404SAndrew.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" 408615SAndrew.W.Wilson@sun.com #include "fsplug.h" 415184Sek110237 425184Sek110237 /* 435184Sek110237 * File sets, of type fileset_t, are entities which contain 445184Sek110237 * information about collections of files and subdirectories in Filebench. 455184Sek110237 * The fileset, once populated, consists of a tree of fileset entries of 465184Sek110237 * type filesetentry_t which specify files and directories. The fileset 476212Saw148015 * is rooted in a directory specified by fileset_path, and once the populated 485184Sek110237 * fileset has been created, has a tree of directories and files 495184Sek110237 * corresponding to the fileset's filesetentry tree. 506701Saw148015 * 517556SAndrew.W.Wilson@sun.com * Fileset entities are allocated by fileset_define() which is called from 527556SAndrew.W.Wilson@sun.com * parser_gram.y: parser_fileset_define(). The filesetentry tree corrseponding 537556SAndrew.W.Wilson@sun.com * to the eventual directory and file tree to be instantiated on the storage 547946SAndrew.W.Wilson@sun.com * medium is built by fileset_populate(), which is This routine is called 557946SAndrew.W.Wilson@sun.com * from fileset_createset(), which is in turn called by fileset_createset(). 567946SAndrew.W.Wilson@sun.com * After calling fileset_populate(), fileset_createset() will call 577946SAndrew.W.Wilson@sun.com * fileset_create() to pre-allocate designated files and directories. 587556SAndrew.W.Wilson@sun.com * 597556SAndrew.W.Wilson@sun.com * Fileset_createset() is called from parser_gram.y: parser_create_fileset() 607556SAndrew.W.Wilson@sun.com * when a "create fileset" or "run" command is encountered. When the 617556SAndrew.W.Wilson@sun.com * "create fileset" command is used, it is generally paired with 626701Saw148015 * a "create processes" command, and must appear first, in order to 636701Saw148015 * instantiate all the files in the fileset before trying to use them. 645184Sek110237 */ 655184Sek110237 666305Saw148015 static int fileset_checkraw(fileset_t *fileset); 676305Saw148015 687556SAndrew.W.Wilson@sun.com /* maximum parallel allocation control */ 695673Saw148015 #define MAX_PARALLOC_THREADS 32 705673Saw148015 715673Saw148015 /* 725673Saw148015 * returns pointer to file or fileset 735673Saw148015 * string, as appropriate 745673Saw148015 */ 755673Saw148015 static char * 765673Saw148015 fileset_entity_name(fileset_t *fileset) 775673Saw148015 { 785673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) 795673Saw148015 return ("file"); 805673Saw148015 else 815673Saw148015 return ("fileset"); 825673Saw148015 } 835673Saw148015 845184Sek110237 /* 855184Sek110237 * Removes the last file or directory name from a pathname. 865184Sek110237 * Basically removes characters from the end of the path by 875184Sek110237 * setting them to \0 until a forward slash '/' is 885184Sek110237 * encountered. It also removes the forward slash. 895184Sek110237 */ 905184Sek110237 static char * 915184Sek110237 trunc_dirname(char *dir) 925184Sek110237 { 935184Sek110237 char *s = dir + strlen(dir); 945184Sek110237 955184Sek110237 while (s != dir) { 965184Sek110237 int c = *s; 975184Sek110237 985184Sek110237 *s = 0; 995184Sek110237 if (c == '/') 1005184Sek110237 break; 1015184Sek110237 s--; 1025184Sek110237 } 1035184Sek110237 return (dir); 1045184Sek110237 } 1055184Sek110237 1065184Sek110237 /* 1075184Sek110237 * Prints a list of allowed options and how to specify them. 1085184Sek110237 */ 1095184Sek110237 void 1105184Sek110237 fileset_usage(void) 1115184Sek110237 { 1125673Saw148015 (void) fprintf(stderr, 1135673Saw148015 "define [file name=<name> | fileset name=<name>],path=<pathname>," 1145673Saw148015 ",entries=<number>\n"); 1155673Saw148015 (void) fprintf(stderr, 1166212Saw148015 " [,filesize=[size]]\n"); 1176212Saw148015 (void) fprintf(stderr, 1185673Saw148015 " [,dirwidth=[width]]\n"); 1195673Saw148015 (void) fprintf(stderr, 1206212Saw148015 " [,dirdepthrv=$random_variable_name]\n"); 1216212Saw148015 (void) fprintf(stderr, 1225673Saw148015 " [,dirgamma=[100-10000]] " 1235184Sek110237 "(Gamma * 1000)\n"); 1245184Sek110237 (void) fprintf(stderr, 1255673Saw148015 " [,sizegamma=[100-10000]] (Gamma * 1000)\n"); 1265184Sek110237 (void) fprintf(stderr, 1275184Sek110237 " [,prealloc=[percent]]\n"); 1285673Saw148015 (void) fprintf(stderr, " [,paralloc]\n"); 1295184Sek110237 (void) fprintf(stderr, " [,reuse]\n"); 1305184Sek110237 (void) fprintf(stderr, "\n"); 1315184Sek110237 } 1325184Sek110237 1335184Sek110237 /* 1345184Sek110237 * Creates a path string from the filesetentry_t "*entry" 1355184Sek110237 * and all of its parent's path names. The resulting path 1365184Sek110237 * is a concatination of all the individual parent paths. 1375184Sek110237 * Allocates memory for the path string and returns a 1385184Sek110237 * pointer to it. 1395184Sek110237 */ 1405184Sek110237 char * 1415184Sek110237 fileset_resolvepath(filesetentry_t *entry) 1425184Sek110237 { 1435184Sek110237 filesetentry_t *fsep = entry; 1445184Sek110237 char path[MAXPATHLEN]; 1455184Sek110237 char pathtmp[MAXPATHLEN]; 1465184Sek110237 char *s; 1475184Sek110237 1487946SAndrew.W.Wilson@sun.com path[0] = '\0'; 1495184Sek110237 while (fsep->fse_parent) { 1505184Sek110237 (void) strcpy(pathtmp, "/"); 1517946SAndrew.W.Wilson@sun.com (void) fb_strlcat(pathtmp, fsep->fse_path, MAXPATHLEN); 1527946SAndrew.W.Wilson@sun.com (void) fb_strlcat(pathtmp, path, MAXPATHLEN); 1537946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, pathtmp, MAXPATHLEN); 1545184Sek110237 fsep = fsep->fse_parent; 1555184Sek110237 } 1565184Sek110237 1575184Sek110237 s = malloc(strlen(path) + 1); 1587946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(s, path, MAXPATHLEN); 1595184Sek110237 return (s); 1605184Sek110237 } 1615184Sek110237 1625184Sek110237 /* 1635184Sek110237 * Creates multiple nested directories as required by the 1645184Sek110237 * supplied path. Starts at the end of the path, creating 1655184Sek110237 * a list of directories to mkdir, up to the root of the 1665184Sek110237 * path, then mkdirs them one at a time from the root on down. 1675184Sek110237 */ 1685184Sek110237 static int 1695184Sek110237 fileset_mkdir(char *path, int mode) 1705184Sek110237 { 1715184Sek110237 char *p; 1725184Sek110237 char *dirs[65536]; 1735184Sek110237 int i = 0; 1745184Sek110237 1755184Sek110237 if ((p = strdup(path)) == NULL) 1765184Sek110237 goto null_str; 1775184Sek110237 1785184Sek110237 /* 1795184Sek110237 * Fill an array of subdirectory path names until either we 1805184Sek110237 * reach the root or encounter an already existing subdirectory 1815184Sek110237 */ 1825184Sek110237 /* CONSTCOND */ 1835184Sek110237 while (1) { 1845184Sek110237 struct stat64 sb; 1855184Sek110237 1865184Sek110237 if (stat64(p, &sb) == 0) 1875184Sek110237 break; 1885184Sek110237 if (strlen(p) < 3) 1895184Sek110237 break; 1905184Sek110237 if ((dirs[i] = strdup(p)) == NULL) { 1915184Sek110237 free(p); 1925184Sek110237 goto null_str; 1935184Sek110237 } 1945184Sek110237 1955184Sek110237 (void) trunc_dirname(p); 1965184Sek110237 i++; 1975184Sek110237 } 1985184Sek110237 1995184Sek110237 /* Make the directories, from closest to root downwards. */ 2005184Sek110237 for (--i; i >= 0; i--) { 2018615SAndrew.W.Wilson@sun.com (void) FB_MKDIR(dirs[i], mode); 2025184Sek110237 free(dirs[i]); 2035184Sek110237 } 2045184Sek110237 2055184Sek110237 free(p); 2067556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 2075184Sek110237 2085184Sek110237 null_str: 2095184Sek110237 /* clean up */ 2105184Sek110237 for (--i; i >= 0; i--) 2115184Sek110237 free(dirs[i]); 2125184Sek110237 2135184Sek110237 filebench_log(LOG_ERROR, 2145184Sek110237 "Failed to create directory path %s: Out of memory", path); 2157556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 2165184Sek110237 } 2175184Sek110237 2185673Saw148015 /* 2195673Saw148015 * creates the subdirectory tree for a fileset. 2205673Saw148015 */ 2215673Saw148015 static int 2225673Saw148015 fileset_create_subdirs(fileset_t *fileset, char *filesetpath) 2235673Saw148015 { 2245673Saw148015 filesetentry_t *direntry; 2255673Saw148015 char full_path[MAXPATHLEN]; 2265673Saw148015 char *part_path; 2275673Saw148015 2285673Saw148015 /* walk the subdirectory list, enstanciating subdirs */ 2295673Saw148015 direntry = fileset->fs_dirlist; 2305673Saw148015 while (direntry) { 2317946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(full_path, filesetpath, MAXPATHLEN); 2325673Saw148015 part_path = fileset_resolvepath(direntry); 2337946SAndrew.W.Wilson@sun.com (void) fb_strlcat(full_path, part_path, MAXPATHLEN); 2345673Saw148015 free(part_path); 2355673Saw148015 2365673Saw148015 /* now create this portion of the subdirectory tree */ 2377556SAndrew.W.Wilson@sun.com if (fileset_mkdir(full_path, 0755) == FILEBENCH_ERROR) 2387556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 2395673Saw148015 2408404SAndrew.W.Wilson@sun.com direntry = direntry->fse_nextoftype; 2415673Saw148015 } 2427556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 2435673Saw148015 } 2445673Saw148015 2455673Saw148015 /* 2468404SAndrew.W.Wilson@sun.com * move filesetentry between exist tree and non-exist tree, source_tree 2478404SAndrew.W.Wilson@sun.com * to destination tree. 2488404SAndrew.W.Wilson@sun.com */ 2498404SAndrew.W.Wilson@sun.com static void 2508404SAndrew.W.Wilson@sun.com fileset_move_entry(avl_tree_t *src_tree, avl_tree_t *dst_tree, 2518404SAndrew.W.Wilson@sun.com filesetentry_t *entry) 2528404SAndrew.W.Wilson@sun.com { 2538404SAndrew.W.Wilson@sun.com avl_remove(src_tree, entry); 2548404SAndrew.W.Wilson@sun.com avl_add(dst_tree, entry); 2558404SAndrew.W.Wilson@sun.com } 2568404SAndrew.W.Wilson@sun.com 2578404SAndrew.W.Wilson@sun.com /* 2587946SAndrew.W.Wilson@sun.com * given a fileset entry, determines if the associated leaf directory 2597946SAndrew.W.Wilson@sun.com * needs to be made or not, and if so does the mkdir. 2607946SAndrew.W.Wilson@sun.com */ 2617946SAndrew.W.Wilson@sun.com static int 2627946SAndrew.W.Wilson@sun.com fileset_alloc_leafdir(filesetentry_t *entry) 2637946SAndrew.W.Wilson@sun.com { 2647946SAndrew.W.Wilson@sun.com fileset_t *fileset; 2657946SAndrew.W.Wilson@sun.com char path[MAXPATHLEN]; 2667946SAndrew.W.Wilson@sun.com struct stat64 sb; 2677946SAndrew.W.Wilson@sun.com char *pathtmp; 2687946SAndrew.W.Wilson@sun.com 2697946SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 2707946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 2717946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 2727946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 2737946SAndrew.W.Wilson@sun.com pathtmp = fileset_resolvepath(entry); 2747946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 2757946SAndrew.W.Wilson@sun.com free(pathtmp); 2767946SAndrew.W.Wilson@sun.com 2777946SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); 2787946SAndrew.W.Wilson@sun.com 2797946SAndrew.W.Wilson@sun.com /* see if not reusing and this directory does not exist */ 2807946SAndrew.W.Wilson@sun.com if (!((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0))) { 2817946SAndrew.W.Wilson@sun.com 2827946SAndrew.W.Wilson@sun.com /* No file or not reusing, so create */ 2838615SAndrew.W.Wilson@sun.com if (FB_MKDIR(path, 0755) < 0) { 2847946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 2857946SAndrew.W.Wilson@sun.com "Failed to pre-allocate leaf directory %s: %s", 2867946SAndrew.W.Wilson@sun.com path, strerror(errno)); 2878404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 2887946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 2897946SAndrew.W.Wilson@sun.com } 2907946SAndrew.W.Wilson@sun.com } 2917946SAndrew.W.Wilson@sun.com 2928404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 2938404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 2947946SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 2957946SAndrew.W.Wilson@sun.com } 2967946SAndrew.W.Wilson@sun.com 2977946SAndrew.W.Wilson@sun.com /* 2985673Saw148015 * given a fileset entry, determines if the associated file 2995673Saw148015 * needs to be allocated or not, and if so does the allocation. 3005673Saw148015 */ 3015673Saw148015 static int 3025673Saw148015 fileset_alloc_file(filesetentry_t *entry) 3035673Saw148015 { 3047946SAndrew.W.Wilson@sun.com fileset_t *fileset; 3055673Saw148015 char path[MAXPATHLEN]; 3065673Saw148015 char *buf; 3075673Saw148015 struct stat64 sb; 3085673Saw148015 char *pathtmp; 3095673Saw148015 off64_t seek; 3108615SAndrew.W.Wilson@sun.com fb_fdesc_t fdesc; 3119326SAndrew.W.Wilson@sun.com int trust_tree; 3125673Saw148015 3137946SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 3147946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 3157946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 3167946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 3175673Saw148015 pathtmp = fileset_resolvepath(entry); 3187946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 3197946SAndrew.W.Wilson@sun.com free(pathtmp); 3205673Saw148015 3215673Saw148015 filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); 3225673Saw148015 3235673Saw148015 /* see if reusing and this file exists */ 3249326SAndrew.W.Wilson@sun.com trust_tree = avd_get_bool(fileset->fs_trust_tree); 3259326SAndrew.W.Wilson@sun.com if ((entry->fse_flags & FSE_REUSING) && (trust_tree || 3269326SAndrew.W.Wilson@sun.com (FB_STAT(path, &sb) == 0))) { 3278615SAndrew.W.Wilson@sun.com if (FB_OPEN(&fdesc, path, O_RDWR, 0) == FILEBENCH_ERROR) { 3285673Saw148015 filebench_log(LOG_INFO, 3295673Saw148015 "Attempted but failed to Re-use file %s", 3305673Saw148015 path); 3318404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 3327556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 3335673Saw148015 } 3345673Saw148015 3359326SAndrew.W.Wilson@sun.com if (trust_tree || (sb.st_size == (off64_t)entry->fse_size)) { 3367556SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, 3375673Saw148015 "Re-using file %s", path); 3385673Saw148015 3397946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 3408615SAndrew.W.Wilson@sun.com (void) FB_FREEMEM(&fdesc, entry->fse_size); 3415673Saw148015 3428615SAndrew.W.Wilson@sun.com (void) FB_CLOSE(&fdesc); 3436701Saw148015 3448404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 3458404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 3467556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 3475673Saw148015 3485673Saw148015 } else if (sb.st_size > (off64_t)entry->fse_size) { 3495673Saw148015 /* reuse, but too large */ 3508404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_IMPL, 3515673Saw148015 "Truncating & re-using file %s", path); 3525673Saw148015 3538615SAndrew.W.Wilson@sun.com (void) FB_FTRUNC(&fdesc, (off64_t)entry->fse_size); 3545673Saw148015 3557946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 3568615SAndrew.W.Wilson@sun.com (void) FB_FREEMEM(&fdesc, entry->fse_size); 3575673Saw148015 3588615SAndrew.W.Wilson@sun.com (void) FB_CLOSE(&fdesc); 3596701Saw148015 3608404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 3618404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 3627556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 3635673Saw148015 } 3645673Saw148015 } else { 3655673Saw148015 3665673Saw148015 /* No file or not reusing, so create */ 3678615SAndrew.W.Wilson@sun.com if (FB_OPEN(&fdesc, path, O_RDWR | O_CREAT, 0644) == 3688615SAndrew.W.Wilson@sun.com FILEBENCH_ERROR) { 3695673Saw148015 filebench_log(LOG_ERROR, 3705673Saw148015 "Failed to pre-allocate file %s: %s", 3715673Saw148015 path, strerror(errno)); 3725673Saw148015 3738404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 3748404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 3757556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 3765673Saw148015 } 3775673Saw148015 } 3785673Saw148015 3798404SAndrew.W.Wilson@sun.com if ((buf = (char *)malloc(FILE_ALLOC_BLOCK)) == NULL) { 3808404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 3818404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 3827556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 3838404SAndrew.W.Wilson@sun.com } 3846701Saw148015 3855673Saw148015 for (seek = 0; seek < entry->fse_size; ) { 3865673Saw148015 off64_t wsize; 3875673Saw148015 int ret = 0; 3885673Saw148015 3895673Saw148015 /* 3905673Saw148015 * Write FILE_ALLOC_BLOCK's worth, 3915673Saw148015 * except on last write 3925673Saw148015 */ 3935673Saw148015 wsize = MIN(entry->fse_size - seek, FILE_ALLOC_BLOCK); 3945673Saw148015 3958615SAndrew.W.Wilson@sun.com ret = FB_WRITE(&fdesc, buf, wsize); 3965673Saw148015 if (ret != wsize) { 3975673Saw148015 filebench_log(LOG_ERROR, 3985673Saw148015 "Failed to pre-allocate file %s: %s", 3995673Saw148015 path, strerror(errno)); 4008615SAndrew.W.Wilson@sun.com (void) FB_CLOSE(&fdesc); 4015673Saw148015 free(buf); 4028404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 4037556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 4045673Saw148015 } 4055673Saw148015 seek += wsize; 4065673Saw148015 } 4075673Saw148015 4087946SAndrew.W.Wilson@sun.com if (!avd_get_bool(fileset->fs_cached)) 4098615SAndrew.W.Wilson@sun.com (void) FB_FREEMEM(&fdesc, entry->fse_size); 4105673Saw148015 4118615SAndrew.W.Wilson@sun.com (void) FB_CLOSE(&fdesc); 4125673Saw148015 4135673Saw148015 free(buf); 4145673Saw148015 4158404SAndrew.W.Wilson@sun.com /* unbusy the allocated entry */ 4168404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 0); 4178404SAndrew.W.Wilson@sun.com 4185673Saw148015 filebench_log(LOG_DEBUG_IMPL, 4196286Saw148015 "Pre-allocated file %s size %llu", 4206286Saw148015 path, (u_longlong_t)entry->fse_size); 4215673Saw148015 4227556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 4235673Saw148015 } 4245673Saw148015 4255673Saw148015 /* 4265673Saw148015 * given a fileset entry, determines if the associated file 4275673Saw148015 * needs to be allocated or not, and if so does the allocation. 4287556SAndrew.W.Wilson@sun.com * Sets shm_fsparalloc_count to -1 on error. 4295673Saw148015 */ 4305673Saw148015 static void * 4315673Saw148015 fileset_alloc_thread(filesetentry_t *entry) 4325673Saw148015 { 4337556SAndrew.W.Wilson@sun.com if (fileset_alloc_file(entry) == FILEBENCH_ERROR) { 4347556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 4357556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count = -1; 4365673Saw148015 } else { 4377556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 4387556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count--; 4395673Saw148015 } 4405673Saw148015 4417556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal(&filebench_shm->shm_fsparalloc_cv); 4427556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock(&filebench_shm->shm_fsparalloc_lock); 4435673Saw148015 4445673Saw148015 pthread_exit(NULL); 4455673Saw148015 return (NULL); 4465673Saw148015 } 4475673Saw148015 4485184Sek110237 4495184Sek110237 /* 4505184Sek110237 * First creates the parent directories of the file using 4515184Sek110237 * fileset_mkdir(). Then Optionally sets the O_DSYNC flag 4525184Sek110237 * and opens the file with open64(). It unlocks the fileset 4535184Sek110237 * entry lock, sets the DIRECTIO_ON or DIRECTIO_OFF flags 4545184Sek110237 * as requested, and returns the file descriptor integer 4558615SAndrew.W.Wilson@sun.com * for the opened file in the supplied filebench file descriptor. 4568615SAndrew.W.Wilson@sun.com * Returns FILEBENCH_ERROR on error, and FILEBENCH_OK on success. 4575184Sek110237 */ 4585184Sek110237 int 4598615SAndrew.W.Wilson@sun.com fileset_openfile(fb_fdesc_t *fdesc, fileset_t *fileset, 4607736SAndrew.W.Wilson@sun.com filesetentry_t *entry, int flag, int filemode, int attrs) 4615184Sek110237 { 4625184Sek110237 char path[MAXPATHLEN]; 4635184Sek110237 char dir[MAXPATHLEN]; 4645184Sek110237 char *pathtmp; 4655184Sek110237 struct stat64 sb; 4665184Sek110237 int open_attrs = 0; 4675184Sek110237 4687946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); 4697946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 4707946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); 4715184Sek110237 pathtmp = fileset_resolvepath(entry); 4727946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, pathtmp, MAXPATHLEN); 4737946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(dir, path, MAXPATHLEN); 4745184Sek110237 free(pathtmp); 4755184Sek110237 (void) trunc_dirname(dir); 4765184Sek110237 4775184Sek110237 /* If we are going to create a file, create the parent dirs */ 4785184Sek110237 if ((flag & O_CREAT) && (stat64(dir, &sb) != 0)) { 4797556SAndrew.W.Wilson@sun.com if (fileset_mkdir(dir, 0755) == FILEBENCH_ERROR) 4807556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 4816701Saw148015 } 4826701Saw148015 4835184Sek110237 if (attrs & FLOW_ATTR_DSYNC) { 4845184Sek110237 #ifdef sun 4855184Sek110237 open_attrs |= O_DSYNC; 4865184Sek110237 #else 4875184Sek110237 open_attrs |= O_FSYNC; 4885184Sek110237 #endif 4895184Sek110237 } 4905184Sek110237 4918615SAndrew.W.Wilson@sun.com if (FB_OPEN(fdesc, path, flag | open_attrs, filemode) 4928615SAndrew.W.Wilson@sun.com == FILEBENCH_ERROR) { 4935184Sek110237 filebench_log(LOG_ERROR, 4948404SAndrew.W.Wilson@sun.com "Failed to open file %d, %s, with status %x: %s", 4958404SAndrew.W.Wilson@sun.com entry->fse_index, path, entry->fse_flags, strerror(errno)); 4967556SAndrew.W.Wilson@sun.com 4978404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, FALSE, FALSE, 0); 4987556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 4995184Sek110237 } 5007556SAndrew.W.Wilson@sun.com 5017556SAndrew.W.Wilson@sun.com if (flag & O_CREAT) 5028404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, TRUE, 1); 5037556SAndrew.W.Wilson@sun.com else 5048404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, FALSE, FALSE, 1); 5055184Sek110237 5065184Sek110237 #ifdef sun 5075184Sek110237 if (attrs & FLOW_ATTR_DIRECTIO) 5088615SAndrew.W.Wilson@sun.com (void) directio(fdesc->fd_num, DIRECTIO_ON); 5095184Sek110237 else 5108615SAndrew.W.Wilson@sun.com (void) directio(fdesc->fd_num, DIRECTIO_OFF); 5115184Sek110237 #endif 5125184Sek110237 5138615SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 5145184Sek110237 } 5155184Sek110237 5168404SAndrew.W.Wilson@sun.com /* 5178404SAndrew.W.Wilson@sun.com * removes all filesetentries from their respective btrees, and puts them 5188404SAndrew.W.Wilson@sun.com * on the free list. The supplied argument indicates which free list to 5198404SAndrew.W.Wilson@sun.com * use. 5208404SAndrew.W.Wilson@sun.com */ 5218404SAndrew.W.Wilson@sun.com static void 5228404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset_t *fileset, int entry_type) 5238404SAndrew.W.Wilson@sun.com { 5248404SAndrew.W.Wilson@sun.com filesetentry_t *entry; 5258404SAndrew.W.Wilson@sun.com 5268404SAndrew.W.Wilson@sun.com switch (entry_type & FILESET_PICKMASK) { 5278404SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 5288404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *)avl_first(&fileset->fs_noex_files); 5298404SAndrew.W.Wilson@sun.com 5308404SAndrew.W.Wilson@sun.com /* make sure non-existing files are marked free */ 5318404SAndrew.W.Wilson@sun.com while (entry) { 5328404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 5338404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 5348404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_noex_files, 5358404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, entry); 5368404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_noex_files, entry); 5378404SAndrew.W.Wilson@sun.com } 5388404SAndrew.W.Wilson@sun.com 5398404SAndrew.W.Wilson@sun.com /* free up any existing files */ 5408404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *)avl_first(&fileset->fs_exist_files); 5418404SAndrew.W.Wilson@sun.com 5428404SAndrew.W.Wilson@sun.com while (entry) { 5438404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 5448404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 5458404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_exist_files, 5468404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, entry); 5478404SAndrew.W.Wilson@sun.com 5488404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_exist_files, entry); 5498404SAndrew.W.Wilson@sun.com } 5508404SAndrew.W.Wilson@sun.com 5518404SAndrew.W.Wilson@sun.com break; 5528404SAndrew.W.Wilson@sun.com 5538404SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 5548404SAndrew.W.Wilson@sun.com /* nothing to reset, as all (sub)dirs always exist */ 5558404SAndrew.W.Wilson@sun.com break; 5568404SAndrew.W.Wilson@sun.com 5578404SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 5588404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *) 5598404SAndrew.W.Wilson@sun.com avl_first(&fileset->fs_noex_leaf_dirs); 5608404SAndrew.W.Wilson@sun.com 5618404SAndrew.W.Wilson@sun.com /* make sure non-existing leaf dirs are marked free */ 5628404SAndrew.W.Wilson@sun.com while (entry) { 5638404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 5648404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 5658404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_noex_leaf_dirs, 5668404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, entry); 5678404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_noex_leaf_dirs, entry); 5688404SAndrew.W.Wilson@sun.com } 5698404SAndrew.W.Wilson@sun.com 5708404SAndrew.W.Wilson@sun.com /* free up any existing leaf dirs */ 5718404SAndrew.W.Wilson@sun.com entry = (filesetentry_t *) 5728404SAndrew.W.Wilson@sun.com avl_first(&fileset->fs_exist_leaf_dirs); 5738404SAndrew.W.Wilson@sun.com 5748404SAndrew.W.Wilson@sun.com while (entry) { 5758404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_FREE; 5768404SAndrew.W.Wilson@sun.com entry->fse_open_cnt = 0; 5778404SAndrew.W.Wilson@sun.com fileset_move_entry(&fileset->fs_exist_leaf_dirs, 5788404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, entry); 5798404SAndrew.W.Wilson@sun.com 5808404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(&fileset->fs_exist_leaf_dirs, entry); 5818404SAndrew.W.Wilson@sun.com } 5828404SAndrew.W.Wilson@sun.com 5838404SAndrew.W.Wilson@sun.com break; 5848404SAndrew.W.Wilson@sun.com } 5858404SAndrew.W.Wilson@sun.com } 5868404SAndrew.W.Wilson@sun.com 5878404SAndrew.W.Wilson@sun.com /* 5888404SAndrew.W.Wilson@sun.com * find a filesetentry from the fileset using the supplied index 5898404SAndrew.W.Wilson@sun.com */ 5908404SAndrew.W.Wilson@sun.com static filesetentry_t * 5918404SAndrew.W.Wilson@sun.com fileset_find_entry(avl_tree_t *atp, uint_t index) 5928404SAndrew.W.Wilson@sun.com { 5938404SAndrew.W.Wilson@sun.com avl_index_t found_loc; 5948404SAndrew.W.Wilson@sun.com filesetentry_t desired_fse, *found_fse; 5958404SAndrew.W.Wilson@sun.com 5968404SAndrew.W.Wilson@sun.com /* find the file with the desired index, if it is in the tree */ 5978404SAndrew.W.Wilson@sun.com desired_fse.fse_index = index; 5988404SAndrew.W.Wilson@sun.com found_fse = avl_find(atp, (void *)(&desired_fse), &found_loc); 5998404SAndrew.W.Wilson@sun.com if (found_fse != NULL) 6008404SAndrew.W.Wilson@sun.com return (found_fse); 6018404SAndrew.W.Wilson@sun.com 6028404SAndrew.W.Wilson@sun.com /* if requested node not found, find next higher node */ 6038404SAndrew.W.Wilson@sun.com found_fse = avl_nearest(atp, found_loc, AVL_AFTER); 6048404SAndrew.W.Wilson@sun.com if (found_fse != NULL) 6058404SAndrew.W.Wilson@sun.com return (found_fse); 6068404SAndrew.W.Wilson@sun.com 6078404SAndrew.W.Wilson@sun.com /* might have hit the end, return lowest available index node */ 6088404SAndrew.W.Wilson@sun.com found_fse = avl_first(atp); 6098404SAndrew.W.Wilson@sun.com return (found_fse); 6108404SAndrew.W.Wilson@sun.com } 6115184Sek110237 6125184Sek110237 /* 6135184Sek110237 * Selects a fileset entry from a fileset. If the 6147946SAndrew.W.Wilson@sun.com * FILESET_PICKLEAFDIR flag is set it will pick a leaf directory entry, 6157946SAndrew.W.Wilson@sun.com * if the FILESET_PICKDIR flag is set it will pick a non leaf directory 6168404SAndrew.W.Wilson@sun.com * entry, otherwise a file entry. The FILESET_PICKUNIQUE 6175184Sek110237 * flag will take an entry off of one of the free (unused) 6185184Sek110237 * lists (file or directory), otherwise the entry will be 6195184Sek110237 * picked off of one of the rotor lists (file or directory). 6205184Sek110237 * The FILESET_PICKEXISTS will insure that only extant 6215184Sek110237 * (FSE_EXISTS) state files are selected, while 6225184Sek110237 * FILESET_PICKNOEXIST insures that only non extant 6235184Sek110237 * (not FSE_EXISTS) state files are selected. 6246391Saw148015 * Note that the selected fileset entry (file) is returned 6257556SAndrew.W.Wilson@sun.com * with its FSE_BUSY flag (in fse_flags) set. 6265184Sek110237 */ 6275184Sek110237 filesetentry_t * 6288404SAndrew.W.Wilson@sun.com fileset_pick(fileset_t *fileset, int flags, int tid, int index) 6295184Sek110237 { 6305184Sek110237 filesetentry_t *entry = NULL; 6318404SAndrew.W.Wilson@sun.com filesetentry_t *start_point; 6328404SAndrew.W.Wilson@sun.com avl_tree_t *atp; 6338404SAndrew.W.Wilson@sun.com fbint_t max_entries; 6345184Sek110237 6357556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 6367556SAndrew.W.Wilson@sun.com 6377556SAndrew.W.Wilson@sun.com /* see if we have to wait for available files or directories */ 6387946SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 6397946SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 6407946SAndrew.W.Wilson@sun.com if (fileset->fs_filelist == NULL) 6417946SAndrew.W.Wilson@sun.com goto empty; 6428404SAndrew.W.Wilson@sun.com 6437556SAndrew.W.Wilson@sun.com while (fileset->fs_idle_files == 0) { 6447556SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_files_cv, 6457556SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 6467556SAndrew.W.Wilson@sun.com } 6478404SAndrew.W.Wilson@sun.com 6488404SAndrew.W.Wilson@sun.com max_entries = fileset->fs_constentries; 6498404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 6508404SAndrew.W.Wilson@sun.com atp = &fileset->fs_free_files; 6518404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKNOEXIST) { 6528404SAndrew.W.Wilson@sun.com atp = &fileset->fs_noex_files; 6538404SAndrew.W.Wilson@sun.com } else { 6548404SAndrew.W.Wilson@sun.com atp = &fileset->fs_exist_files; 6558404SAndrew.W.Wilson@sun.com } 6567946SAndrew.W.Wilson@sun.com break; 6578404SAndrew.W.Wilson@sun.com 6587946SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 6597946SAndrew.W.Wilson@sun.com if (fileset->fs_dirlist == NULL) 6607946SAndrew.W.Wilson@sun.com goto empty; 6618404SAndrew.W.Wilson@sun.com 6627946SAndrew.W.Wilson@sun.com while (fileset->fs_idle_dirs == 0) { 6637946SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_dirs_cv, 6647946SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 6657946SAndrew.W.Wilson@sun.com } 6668404SAndrew.W.Wilson@sun.com 6678404SAndrew.W.Wilson@sun.com max_entries = 1; 6688404SAndrew.W.Wilson@sun.com atp = &fileset->fs_dirs; 6697946SAndrew.W.Wilson@sun.com break; 6708404SAndrew.W.Wilson@sun.com 6717946SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 6727946SAndrew.W.Wilson@sun.com if (fileset->fs_leafdirlist == NULL) 6737946SAndrew.W.Wilson@sun.com goto empty; 6748404SAndrew.W.Wilson@sun.com 6757946SAndrew.W.Wilson@sun.com while (fileset->fs_idle_leafdirs == 0) { 6767946SAndrew.W.Wilson@sun.com (void) pthread_cond_wait(&fileset->fs_idle_leafdirs_cv, 6777946SAndrew.W.Wilson@sun.com &fileset->fs_pick_lock); 6787946SAndrew.W.Wilson@sun.com } 6798404SAndrew.W.Wilson@sun.com 6808404SAndrew.W.Wilson@sun.com max_entries = fileset->fs_constleafdirs; 6818404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 6828404SAndrew.W.Wilson@sun.com atp = &fileset->fs_free_leaf_dirs; 6838404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKNOEXIST) { 6848404SAndrew.W.Wilson@sun.com atp = &fileset->fs_noex_leaf_dirs; 6858404SAndrew.W.Wilson@sun.com } else { 6868404SAndrew.W.Wilson@sun.com atp = &fileset->fs_exist_leaf_dirs; 6878404SAndrew.W.Wilson@sun.com } 6887946SAndrew.W.Wilson@sun.com break; 6897556SAndrew.W.Wilson@sun.com } 6905184Sek110237 6916701Saw148015 /* see if asking for impossible */ 6928404SAndrew.W.Wilson@sun.com if (avl_is_empty(atp)) 6938404SAndrew.W.Wilson@sun.com goto empty; 6948404SAndrew.W.Wilson@sun.com 6958404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKUNIQUE) { 6968404SAndrew.W.Wilson@sun.com uint64_t index64; 6978404SAndrew.W.Wilson@sun.com 6988404SAndrew.W.Wilson@sun.com /* 6998404SAndrew.W.Wilson@sun.com * pick at random from free list in order to 7008404SAndrew.W.Wilson@sun.com * distribute initially allocated files more 7018404SAndrew.W.Wilson@sun.com * randomly on storage media. Use uniform 7028404SAndrew.W.Wilson@sun.com * random number generator to select index 7038404SAndrew.W.Wilson@sun.com * if it is not supplied with pick call. 7048404SAndrew.W.Wilson@sun.com */ 7058404SAndrew.W.Wilson@sun.com if (index) { 7068404SAndrew.W.Wilson@sun.com index64 = index; 7078404SAndrew.W.Wilson@sun.com } else { 7088404SAndrew.W.Wilson@sun.com if (filebench_randomno64(&index64, max_entries, 1, 7098404SAndrew.W.Wilson@sun.com NULL) == FILEBENCH_ERROR) 7107946SAndrew.W.Wilson@sun.com return (NULL); 7115184Sek110237 } 7125184Sek110237 7138404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, (int)index64); 7148404SAndrew.W.Wilson@sun.com 7158404SAndrew.W.Wilson@sun.com if (entry == NULL) 7168404SAndrew.W.Wilson@sun.com goto empty; 7178404SAndrew.W.Wilson@sun.com 7188404SAndrew.W.Wilson@sun.com } else if (flags & FILESET_PICKBYINDEX) { 7198404SAndrew.W.Wilson@sun.com /* pick by supplied index */ 7208404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, index); 7218404SAndrew.W.Wilson@sun.com 7228404SAndrew.W.Wilson@sun.com } else { 7238404SAndrew.W.Wilson@sun.com /* pick in rotation */ 7248404SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 7258404SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 7268404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKNOEXIST) { 7278404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 7288404SAndrew.W.Wilson@sun.com fileset->fs_file_nerotor); 7298404SAndrew.W.Wilson@sun.com fileset->fs_file_nerotor = 7308404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7318404SAndrew.W.Wilson@sun.com } else { 7328404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 7338404SAndrew.W.Wilson@sun.com fileset->fs_file_exrotor[tid]); 7348404SAndrew.W.Wilson@sun.com fileset->fs_file_exrotor[tid] = 7358404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7365184Sek110237 } 7378404SAndrew.W.Wilson@sun.com break; 7388404SAndrew.W.Wilson@sun.com 7398404SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 7408404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, fileset->fs_dirrotor); 7418404SAndrew.W.Wilson@sun.com fileset->fs_dirrotor = entry->fse_index + 1; 7428404SAndrew.W.Wilson@sun.com break; 7438404SAndrew.W.Wilson@sun.com 7448404SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 7458404SAndrew.W.Wilson@sun.com if (flags & FILESET_PICKNOEXIST) { 7468404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 7478404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_nerotor); 7488404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_nerotor = 7498404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7508404SAndrew.W.Wilson@sun.com } else { 7518404SAndrew.W.Wilson@sun.com entry = fileset_find_entry(atp, 7528404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_exrotor); 7538404SAndrew.W.Wilson@sun.com fileset->fs_leafdir_exrotor = 7548404SAndrew.W.Wilson@sun.com entry->fse_index + 1; 7555184Sek110237 } 7568404SAndrew.W.Wilson@sun.com break; 7578404SAndrew.W.Wilson@sun.com } 7588404SAndrew.W.Wilson@sun.com } 7598404SAndrew.W.Wilson@sun.com 7608404SAndrew.W.Wilson@sun.com if (entry == NULL) 7618404SAndrew.W.Wilson@sun.com goto empty; 7628404SAndrew.W.Wilson@sun.com 7638404SAndrew.W.Wilson@sun.com /* see if entry in use */ 7648404SAndrew.W.Wilson@sun.com start_point = entry; 7658404SAndrew.W.Wilson@sun.com while (entry->fse_flags & FSE_BUSY) { 7668404SAndrew.W.Wilson@sun.com 7678404SAndrew.W.Wilson@sun.com /* it is, so try next */ 7688404SAndrew.W.Wilson@sun.com entry = AVL_NEXT(atp, entry); 7698404SAndrew.W.Wilson@sun.com if (entry == NULL) 7708404SAndrew.W.Wilson@sun.com entry = avl_first(atp); 7718404SAndrew.W.Wilson@sun.com 7728404SAndrew.W.Wilson@sun.com /* see if we have wrapped around */ 7738404SAndrew.W.Wilson@sun.com if ((entry == NULL) || (entry == start_point)) { 7748404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_SCRIPT, 7758404SAndrew.W.Wilson@sun.com "All %d files are busy", avl_numnodes(atp)); 7768404SAndrew.W.Wilson@sun.com goto empty; 7775184Sek110237 } 7785184Sek110237 7795184Sek110237 } 7805184Sek110237 7817556SAndrew.W.Wilson@sun.com /* update file or directory idle counts */ 7827946SAndrew.W.Wilson@sun.com switch (flags & FILESET_PICKMASK) { 7837946SAndrew.W.Wilson@sun.com case FILESET_PICKFILE: 7847946SAndrew.W.Wilson@sun.com fileset->fs_idle_files--; 7857946SAndrew.W.Wilson@sun.com break; 7867946SAndrew.W.Wilson@sun.com case FILESET_PICKDIR: 7877556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs--; 7887946SAndrew.W.Wilson@sun.com break; 7897946SAndrew.W.Wilson@sun.com case FILESET_PICKLEAFDIR: 7907946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs--; 7917946SAndrew.W.Wilson@sun.com break; 7927946SAndrew.W.Wilson@sun.com } 7937556SAndrew.W.Wilson@sun.com 7947556SAndrew.W.Wilson@sun.com /* Indicate that file or directory is now busy */ 7957556SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_BUSY; 7967556SAndrew.W.Wilson@sun.com 7977556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 7985184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "Picked file %s", entry->fse_path); 7995184Sek110237 return (entry); 8005184Sek110237 8015184Sek110237 empty: 8028404SAndrew.W.Wilson@sun.com filebench_log(LOG_DEBUG_SCRIPT, "No file found"); 8037556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 8045184Sek110237 return (NULL); 8055184Sek110237 } 8065184Sek110237 8075184Sek110237 /* 8087556SAndrew.W.Wilson@sun.com * Removes a filesetentry from the "FSE_BUSY" state, signaling any threads 8097556SAndrew.W.Wilson@sun.com * that are waiting for a NOT BUSY filesetentry. Also sets whether it is 8107556SAndrew.W.Wilson@sun.com * existant or not, or leaves that designation alone. 8117556SAndrew.W.Wilson@sun.com */ 8127556SAndrew.W.Wilson@sun.com void 8138404SAndrew.W.Wilson@sun.com fileset_unbusy(filesetentry_t *entry, int update_exist, 8148404SAndrew.W.Wilson@sun.com int new_exist_val, int open_cnt_incr) 8157556SAndrew.W.Wilson@sun.com { 8167556SAndrew.W.Wilson@sun.com fileset_t *fileset = NULL; 8177556SAndrew.W.Wilson@sun.com 8187556SAndrew.W.Wilson@sun.com if (entry) 8197556SAndrew.W.Wilson@sun.com fileset = entry->fse_fileset; 8207556SAndrew.W.Wilson@sun.com 8217556SAndrew.W.Wilson@sun.com if (fileset == NULL) { 8227556SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, "fileset_unbusy: NO FILESET!"); 8237556SAndrew.W.Wilson@sun.com return; 8247556SAndrew.W.Wilson@sun.com } 8257556SAndrew.W.Wilson@sun.com 8267556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 8277556SAndrew.W.Wilson@sun.com 8288404SAndrew.W.Wilson@sun.com /* modify FSE_EXIST flag and actual dirs/files count, if requested */ 8298404SAndrew.W.Wilson@sun.com if (update_exist) { 8308404SAndrew.W.Wilson@sun.com if (new_exist_val == TRUE) { 8318404SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_FREE) { 8328404SAndrew.W.Wilson@sun.com 8338404SAndrew.W.Wilson@sun.com /* asked to set and it was free */ 8348404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_EXISTS; 8358404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_FREE); 8368404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 8378404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 8388404SAndrew.W.Wilson@sun.com fileset_move_entry( 8398404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, 8408404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, entry); 8418404SAndrew.W.Wilson@sun.com break; 8428404SAndrew.W.Wilson@sun.com 8438404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 8448404SAndrew.W.Wilson@sun.com break; 8458404SAndrew.W.Wilson@sun.com 8468404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 8478404SAndrew.W.Wilson@sun.com fileset_move_entry( 8488404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, 8498404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 8508404SAndrew.W.Wilson@sun.com entry); 8518404SAndrew.W.Wilson@sun.com break; 8528404SAndrew.W.Wilson@sun.com } 8538404SAndrew.W.Wilson@sun.com 8548404SAndrew.W.Wilson@sun.com } else if (!(entry->fse_flags & FSE_EXISTS)) { 8558404SAndrew.W.Wilson@sun.com 8568404SAndrew.W.Wilson@sun.com /* asked to set, and it was clear */ 8578404SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_EXISTS; 8588404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 8598404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 8608404SAndrew.W.Wilson@sun.com fileset_move_entry( 8618404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, 8628404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, entry); 8638404SAndrew.W.Wilson@sun.com break; 8648404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 8658404SAndrew.W.Wilson@sun.com break; 8668404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 8678404SAndrew.W.Wilson@sun.com fileset_move_entry( 8688404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 8698404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 8708404SAndrew.W.Wilson@sun.com entry); 8718404SAndrew.W.Wilson@sun.com break; 8728404SAndrew.W.Wilson@sun.com } 8738404SAndrew.W.Wilson@sun.com } 8748404SAndrew.W.Wilson@sun.com } else { 8758404SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_FREE) { 8768404SAndrew.W.Wilson@sun.com /* asked to clear, and it was free */ 8778404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~(FSE_FREE | FSE_EXISTS)); 8788404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 8798404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 8808404SAndrew.W.Wilson@sun.com fileset_move_entry( 8818404SAndrew.W.Wilson@sun.com &fileset->fs_free_files, 8828404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, entry); 8838404SAndrew.W.Wilson@sun.com break; 8848404SAndrew.W.Wilson@sun.com 8858404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 8868404SAndrew.W.Wilson@sun.com break; 8878404SAndrew.W.Wilson@sun.com 8888404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 8898404SAndrew.W.Wilson@sun.com fileset_move_entry( 8908404SAndrew.W.Wilson@sun.com &fileset->fs_free_leaf_dirs, 8918404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 8928404SAndrew.W.Wilson@sun.com entry); 8938404SAndrew.W.Wilson@sun.com break; 8948404SAndrew.W.Wilson@sun.com } 8958404SAndrew.W.Wilson@sun.com } else if (entry->fse_flags & FSE_EXISTS) { 8968404SAndrew.W.Wilson@sun.com 8978404SAndrew.W.Wilson@sun.com /* asked to clear, and it was set */ 8988404SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_EXISTS); 8998404SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 9008404SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 9018404SAndrew.W.Wilson@sun.com fileset_move_entry( 9028404SAndrew.W.Wilson@sun.com &fileset->fs_exist_files, 9038404SAndrew.W.Wilson@sun.com &fileset->fs_noex_files, entry); 9048404SAndrew.W.Wilson@sun.com break; 9058404SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 9068404SAndrew.W.Wilson@sun.com break; 9078404SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 9088404SAndrew.W.Wilson@sun.com fileset_move_entry( 9098404SAndrew.W.Wilson@sun.com &fileset->fs_exist_leaf_dirs, 9108404SAndrew.W.Wilson@sun.com &fileset->fs_noex_leaf_dirs, 9118404SAndrew.W.Wilson@sun.com entry); 9128404SAndrew.W.Wilson@sun.com break; 9138404SAndrew.W.Wilson@sun.com } 9148404SAndrew.W.Wilson@sun.com } 9158404SAndrew.W.Wilson@sun.com } 9168404SAndrew.W.Wilson@sun.com } 9178404SAndrew.W.Wilson@sun.com 9188404SAndrew.W.Wilson@sun.com /* update open count */ 9198404SAndrew.W.Wilson@sun.com entry->fse_open_cnt += open_cnt_incr; 9208404SAndrew.W.Wilson@sun.com 9217556SAndrew.W.Wilson@sun.com /* increment idle count, clear FSE_BUSY and signal IF it was busy */ 9227556SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_BUSY) { 9237556SAndrew.W.Wilson@sun.com 9247556SAndrew.W.Wilson@sun.com /* unbusy it */ 9257556SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_BUSY); 9267556SAndrew.W.Wilson@sun.com 9277556SAndrew.W.Wilson@sun.com /* release any threads waiting for unbusy */ 9287556SAndrew.W.Wilson@sun.com if (entry->fse_flags & FSE_THRD_WAITNG) { 9297556SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_THRD_WAITNG); 9307556SAndrew.W.Wilson@sun.com (void) pthread_cond_broadcast( 9317556SAndrew.W.Wilson@sun.com &fileset->fs_thrd_wait_cv); 9327556SAndrew.W.Wilson@sun.com } 9337556SAndrew.W.Wilson@sun.com 9347556SAndrew.W.Wilson@sun.com /* increment idle count and signal waiting threads */ 9357946SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 9367946SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 9377946SAndrew.W.Wilson@sun.com fileset->fs_idle_files++; 9387946SAndrew.W.Wilson@sun.com if (fileset->fs_idle_files == 1) { 9397946SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9407946SAndrew.W.Wilson@sun.com &fileset->fs_idle_files_cv); 9417946SAndrew.W.Wilson@sun.com } 9427946SAndrew.W.Wilson@sun.com break; 9438404SAndrew.W.Wilson@sun.com 9447946SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 9457556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs++; 9467556SAndrew.W.Wilson@sun.com if (fileset->fs_idle_dirs == 1) { 9477556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9487556SAndrew.W.Wilson@sun.com &fileset->fs_idle_dirs_cv); 9497556SAndrew.W.Wilson@sun.com } 9507946SAndrew.W.Wilson@sun.com break; 9518404SAndrew.W.Wilson@sun.com 9527946SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 9537946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs++; 9547946SAndrew.W.Wilson@sun.com if (fileset->fs_idle_leafdirs == 1) { 9557556SAndrew.W.Wilson@sun.com (void) pthread_cond_signal( 9567946SAndrew.W.Wilson@sun.com &fileset->fs_idle_leafdirs_cv); 9577556SAndrew.W.Wilson@sun.com } 9587946SAndrew.W.Wilson@sun.com break; 9597556SAndrew.W.Wilson@sun.com } 9607556SAndrew.W.Wilson@sun.com } 9617556SAndrew.W.Wilson@sun.com 9627556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 9637556SAndrew.W.Wilson@sun.com } 9647556SAndrew.W.Wilson@sun.com 9657556SAndrew.W.Wilson@sun.com /* 9665184Sek110237 * Given a fileset "fileset", create the associated files as 9675184Sek110237 * specified in the attributes of the fileset. The fileset is 9686212Saw148015 * rooted in a directory whose pathname is in fileset_path. If the 9695184Sek110237 * directory exists, meaning that there is already a fileset, 9706212Saw148015 * and the fileset_reuse attribute is false, then remove it and all 9715184Sek110237 * its contained files and subdirectories. Next, the routine 9725184Sek110237 * creates a root directory for the fileset. All the file type 9735184Sek110237 * filesetentries are cycled through creating as needed 9745184Sek110237 * their containing subdirectory trees in the filesystem and 9756212Saw148015 * creating actual files for fileset_preallocpercent of them. The 9765184Sek110237 * created files are filled with fse_size bytes of unitialized 9777556SAndrew.W.Wilson@sun.com * data. The routine returns FILEBENCH_ERROR on errors, 9787556SAndrew.W.Wilson@sun.com * FILEBENCH_OK on success. 9795184Sek110237 */ 9805184Sek110237 static int 9815184Sek110237 fileset_create(fileset_t *fileset) 9825184Sek110237 { 9835184Sek110237 filesetentry_t *entry; 9845184Sek110237 char path[MAXPATHLEN]; 9855184Sek110237 struct stat64 sb; 9865184Sek110237 hrtime_t start = gethrtime(); 9876212Saw148015 char *fileset_path; 9886212Saw148015 char *fileset_name; 9896212Saw148015 int randno; 9905184Sek110237 int preallocated = 0; 9917736SAndrew.W.Wilson@sun.com int reusing; 9925184Sek110237 9936212Saw148015 if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) { 9945673Saw148015 filebench_log(LOG_ERROR, "%s path not set", 9955673Saw148015 fileset_entity_name(fileset)); 9967556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 9975184Sek110237 } 9985184Sek110237 9996212Saw148015 if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) { 10006212Saw148015 filebench_log(LOG_ERROR, "%s name not set", 10016212Saw148015 fileset_entity_name(fileset)); 10027556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 10036212Saw148015 } 10046212Saw148015 10055673Saw148015 #ifdef HAVE_RAW_SUPPORT 10065673Saw148015 /* treat raw device as special case */ 10075673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) 10087556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 10095673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 10105673Saw148015 10115184Sek110237 /* XXX Add check to see if there is enough space */ 10125184Sek110237 10137736SAndrew.W.Wilson@sun.com /* set up path to fileset */ 10147946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, fileset_path, MAXPATHLEN); 10157946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 10167946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, fileset_name, MAXPATHLEN); 10177736SAndrew.W.Wilson@sun.com 10189326SAndrew.W.Wilson@sun.com /* if reusing and trusting to exist, just blindly reuse */ 10199326SAndrew.W.Wilson@sun.com if (avd_get_bool(fileset->fs_trust_tree)) { 10209326SAndrew.W.Wilson@sun.com reusing = 1; 10219326SAndrew.W.Wilson@sun.com 10227736SAndrew.W.Wilson@sun.com /* if exists and resusing, then don't create new */ 10239326SAndrew.W.Wilson@sun.com } else if (((stat64(path, &sb) == 0)&& (strlen(path) > 3) && 10247736SAndrew.W.Wilson@sun.com (strlen(avd_get_str(fileset->fs_path)) > 2)) && 10257736SAndrew.W.Wilson@sun.com avd_get_bool(fileset->fs_reuse)) { 10267736SAndrew.W.Wilson@sun.com reusing = 1; 10277736SAndrew.W.Wilson@sun.com } else { 10287736SAndrew.W.Wilson@sun.com reusing = 0; 10297736SAndrew.W.Wilson@sun.com } 10307736SAndrew.W.Wilson@sun.com 10317736SAndrew.W.Wilson@sun.com if (!reusing) { 10327736SAndrew.W.Wilson@sun.com /* Remove existing */ 1033*9356SAndrew.W.Wilson@sun.com FB_RECUR_RM(path); 10347736SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, 10357736SAndrew.W.Wilson@sun.com "Removed any existing %s %s in %llu seconds", 10367736SAndrew.W.Wilson@sun.com fileset_entity_name(fileset), fileset_name, 10377736SAndrew.W.Wilson@sun.com (u_longlong_t)(((gethrtime() - start) / 10387736SAndrew.W.Wilson@sun.com 1000000000) + 1)); 10397736SAndrew.W.Wilson@sun.com } else { 10407736SAndrew.W.Wilson@sun.com /* we are re-using */ 10417736SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, "Re-using %s %s.", 10427736SAndrew.W.Wilson@sun.com fileset_entity_name(fileset), fileset_name); 10435184Sek110237 } 10447736SAndrew.W.Wilson@sun.com 10457736SAndrew.W.Wilson@sun.com /* make the filesets directory tree unless in reuse mode */ 10467736SAndrew.W.Wilson@sun.com if (!reusing && (avd_get_bool(fileset->fs_prealloc))) { 10477946SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, 10487736SAndrew.W.Wilson@sun.com "making tree for filset %s", path); 10495184Sek110237 10508615SAndrew.W.Wilson@sun.com (void) FB_MKDIR(path, 0755); 10517736SAndrew.W.Wilson@sun.com 10527736SAndrew.W.Wilson@sun.com if (fileset_create_subdirs(fileset, path) == FILEBENCH_ERROR) 10537736SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 10547736SAndrew.W.Wilson@sun.com } 10555673Saw148015 10565184Sek110237 start = gethrtime(); 10575184Sek110237 10585673Saw148015 filebench_log(LOG_VERBOSE, "Creating %s %s...", 10596212Saw148015 fileset_entity_name(fileset), fileset_name); 10605673Saw148015 10616212Saw148015 randno = ((RAND_MAX * (100 10626212Saw148015 - avd_get_int(fileset->fs_preallocpercent))) / 100); 10636212Saw148015 10647946SAndrew.W.Wilson@sun.com /* alloc any files, as required */ 10658404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset, FILESET_PICKFILE); 10668404SAndrew.W.Wilson@sun.com while (entry = fileset_pick(fileset, 10678404SAndrew.W.Wilson@sun.com FILESET_PICKFREE | FILESET_PICKFILE, 0, 0)) { 10685673Saw148015 pthread_t tid; 10697736SAndrew.W.Wilson@sun.com int newrand; 10705184Sek110237 10717736SAndrew.W.Wilson@sun.com newrand = rand(); 10727736SAndrew.W.Wilson@sun.com 10738404SAndrew.W.Wilson@sun.com if (newrand < randno) { 10748404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 10758404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 10765184Sek110237 continue; 10778404SAndrew.W.Wilson@sun.com } 10785184Sek110237 10795184Sek110237 preallocated++; 10805184Sek110237 10815673Saw148015 if (reusing) 10825673Saw148015 entry->fse_flags |= FSE_REUSING; 10835673Saw148015 else 10845673Saw148015 entry->fse_flags &= (~FSE_REUSING); 10855673Saw148015 10867556SAndrew.W.Wilson@sun.com /* fire off allocation threads for each file if paralloc set */ 10876212Saw148015 if (avd_get_bool(fileset->fs_paralloc)) { 10885184Sek110237 10897556SAndrew.W.Wilson@sun.com /* limit total number of simultaneous allocations */ 10907556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock( 10917556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 10927556SAndrew.W.Wilson@sun.com while (filebench_shm->shm_fsparalloc_count 10937556SAndrew.W.Wilson@sun.com >= MAX_PARALLOC_THREADS) { 10945673Saw148015 (void) pthread_cond_wait( 10957556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 10967556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 10975673Saw148015 } 10985673Saw148015 10998615SAndrew.W.Wilson@sun.com /* quit if any allocation thread reports an error */ 11007556SAndrew.W.Wilson@sun.com if (filebench_shm->shm_fsparalloc_count < 0) { 11017556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock( 11027556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11037556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11045184Sek110237 } 11055184Sek110237 11067556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count++; 11077556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock( 11087556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 11095184Sek110237 11107556SAndrew.W.Wilson@sun.com /* 11117556SAndrew.W.Wilson@sun.com * Fire off a detached allocation thread per file. 11127556SAndrew.W.Wilson@sun.com * The thread will self destruct when it finishes 11137556SAndrew.W.Wilson@sun.com * writing pre-allocation data to the file. 11147556SAndrew.W.Wilson@sun.com */ 11155673Saw148015 if (pthread_create(&tid, NULL, 11165673Saw148015 (void *(*)(void*))fileset_alloc_thread, 11177556SAndrew.W.Wilson@sun.com entry) == 0) { 11187556SAndrew.W.Wilson@sun.com /* 11197556SAndrew.W.Wilson@sun.com * A thread was created; detach it so it can 11207556SAndrew.W.Wilson@sun.com * fully quit when finished. 11217556SAndrew.W.Wilson@sun.com */ 11227556SAndrew.W.Wilson@sun.com (void) pthread_detach(tid); 11237556SAndrew.W.Wilson@sun.com } else { 11245184Sek110237 filebench_log(LOG_ERROR, 11255673Saw148015 "File prealloc thread create failed"); 11265673Saw148015 filebench_shutdown(1); 11275184Sek110237 } 11285184Sek110237 11295673Saw148015 } else { 11307556SAndrew.W.Wilson@sun.com if (fileset_alloc_file(entry) == FILEBENCH_ERROR) 11317556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11325673Saw148015 } 11335673Saw148015 } 11345184Sek110237 11357946SAndrew.W.Wilson@sun.com /* alloc any leaf directories, as required */ 11368404SAndrew.W.Wilson@sun.com fileset_pickreset(fileset, FILESET_PICKLEAFDIR); 11378404SAndrew.W.Wilson@sun.com while (entry = fileset_pick(fileset, 11388404SAndrew.W.Wilson@sun.com FILESET_PICKFREE | FILESET_PICKLEAFDIR, 0, 0)) { 11397946SAndrew.W.Wilson@sun.com 11408404SAndrew.W.Wilson@sun.com if (rand() < randno) { 11418404SAndrew.W.Wilson@sun.com /* unbusy the unallocated entry */ 11428404SAndrew.W.Wilson@sun.com fileset_unbusy(entry, TRUE, FALSE, 0); 11437946SAndrew.W.Wilson@sun.com continue; 11448404SAndrew.W.Wilson@sun.com } 11457946SAndrew.W.Wilson@sun.com 11467946SAndrew.W.Wilson@sun.com preallocated++; 11477946SAndrew.W.Wilson@sun.com 11487946SAndrew.W.Wilson@sun.com if (reusing) 11497946SAndrew.W.Wilson@sun.com entry->fse_flags |= FSE_REUSING; 11507946SAndrew.W.Wilson@sun.com else 11517946SAndrew.W.Wilson@sun.com entry->fse_flags &= (~FSE_REUSING); 11527946SAndrew.W.Wilson@sun.com 11537946SAndrew.W.Wilson@sun.com if (fileset_alloc_leafdir(entry) == FILEBENCH_ERROR) 11547946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 11557946SAndrew.W.Wilson@sun.com } 11567946SAndrew.W.Wilson@sun.com 11575673Saw148015 exit: 11585184Sek110237 filebench_log(LOG_VERBOSE, 11596286Saw148015 "Preallocated %d of %llu of %s %s in %llu seconds", 11605184Sek110237 preallocated, 11616286Saw148015 (u_longlong_t)fileset->fs_constentries, 11626212Saw148015 fileset_entity_name(fileset), fileset_name, 11636286Saw148015 (u_longlong_t)(((gethrtime() - start) / 1000000000) + 1)); 11645184Sek110237 11657556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 11665184Sek110237 } 11675184Sek110237 11685184Sek110237 /* 1169*9356SAndrew.W.Wilson@sun.com * Removes all files and directories associated with a fileset 1170*9356SAndrew.W.Wilson@sun.com * from the storage subsystem. 1171*9356SAndrew.W.Wilson@sun.com */ 1172*9356SAndrew.W.Wilson@sun.com static void 1173*9356SAndrew.W.Wilson@sun.com fileset_delete_storage(fileset_t *fileset) 1174*9356SAndrew.W.Wilson@sun.com { 1175*9356SAndrew.W.Wilson@sun.com char path[MAXPATHLEN]; 1176*9356SAndrew.W.Wilson@sun.com char *fileset_path; 1177*9356SAndrew.W.Wilson@sun.com char *fileset_name; 1178*9356SAndrew.W.Wilson@sun.com 1179*9356SAndrew.W.Wilson@sun.com if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) 1180*9356SAndrew.W.Wilson@sun.com return; 1181*9356SAndrew.W.Wilson@sun.com 1182*9356SAndrew.W.Wilson@sun.com if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) 1183*9356SAndrew.W.Wilson@sun.com return; 1184*9356SAndrew.W.Wilson@sun.com 1185*9356SAndrew.W.Wilson@sun.com #ifdef HAVE_RAW_SUPPORT 1186*9356SAndrew.W.Wilson@sun.com /* treat raw device as special case */ 1187*9356SAndrew.W.Wilson@sun.com if (fileset->fs_attrs & FILESET_IS_RAW_DEV) 1188*9356SAndrew.W.Wilson@sun.com return; 1189*9356SAndrew.W.Wilson@sun.com #endif /* HAVE_RAW_SUPPORT */ 1190*9356SAndrew.W.Wilson@sun.com 1191*9356SAndrew.W.Wilson@sun.com /* set up path to file */ 1192*9356SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, fileset_path, MAXPATHLEN); 1193*9356SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 1194*9356SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, fileset_name, MAXPATHLEN); 1195*9356SAndrew.W.Wilson@sun.com 1196*9356SAndrew.W.Wilson@sun.com /* now delete any files and directories on the disk */ 1197*9356SAndrew.W.Wilson@sun.com FB_RECUR_RM(path); 1198*9356SAndrew.W.Wilson@sun.com } 1199*9356SAndrew.W.Wilson@sun.com 1200*9356SAndrew.W.Wilson@sun.com /* 1201*9356SAndrew.W.Wilson@sun.com * Removes the fileset entity and all of its filesetentry entities. 1202*9356SAndrew.W.Wilson@sun.com */ 1203*9356SAndrew.W.Wilson@sun.com static void 1204*9356SAndrew.W.Wilson@sun.com fileset_delete_fileset(fileset_t *fileset) 1205*9356SAndrew.W.Wilson@sun.com { 1206*9356SAndrew.W.Wilson@sun.com filesetentry_t *entry, *next_entry; 1207*9356SAndrew.W.Wilson@sun.com 1208*9356SAndrew.W.Wilson@sun.com /* run down the file list, removing and freeing each filesetentry */ 1209*9356SAndrew.W.Wilson@sun.com for (entry = fileset->fs_filelist; entry; entry = next_entry) { 1210*9356SAndrew.W.Wilson@sun.com 1211*9356SAndrew.W.Wilson@sun.com /* free the entry */ 1212*9356SAndrew.W.Wilson@sun.com next_entry = entry->fse_next; 1213*9356SAndrew.W.Wilson@sun.com 1214*9356SAndrew.W.Wilson@sun.com /* return it to the pool */ 1215*9356SAndrew.W.Wilson@sun.com switch (entry->fse_flags & FSE_TYPE_MASK) { 1216*9356SAndrew.W.Wilson@sun.com case FSE_TYPE_FILE: 1217*9356SAndrew.W.Wilson@sun.com case FSE_TYPE_LEAFDIR: 1218*9356SAndrew.W.Wilson@sun.com case FSE_TYPE_DIR: 1219*9356SAndrew.W.Wilson@sun.com ipc_free(FILEBENCH_FILESETENTRY, (void *)entry); 1220*9356SAndrew.W.Wilson@sun.com break; 1221*9356SAndrew.W.Wilson@sun.com default: 1222*9356SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 1223*9356SAndrew.W.Wilson@sun.com "Unallocated filesetentry found on list"); 1224*9356SAndrew.W.Wilson@sun.com break; 1225*9356SAndrew.W.Wilson@sun.com } 1226*9356SAndrew.W.Wilson@sun.com } 1227*9356SAndrew.W.Wilson@sun.com 1228*9356SAndrew.W.Wilson@sun.com ipc_free(FILEBENCH_FILESET, (void *)fileset); 1229*9356SAndrew.W.Wilson@sun.com } 1230*9356SAndrew.W.Wilson@sun.com 1231*9356SAndrew.W.Wilson@sun.com void 1232*9356SAndrew.W.Wilson@sun.com fileset_delete_all_filesets(void) 1233*9356SAndrew.W.Wilson@sun.com { 1234*9356SAndrew.W.Wilson@sun.com fileset_t *fileset, *next_fileset; 1235*9356SAndrew.W.Wilson@sun.com 1236*9356SAndrew.W.Wilson@sun.com for (fileset = filebench_shm->shm_filesetlist; 1237*9356SAndrew.W.Wilson@sun.com fileset; fileset = next_fileset) { 1238*9356SAndrew.W.Wilson@sun.com next_fileset = fileset->fs_next; 1239*9356SAndrew.W.Wilson@sun.com fileset_delete_storage(fileset); 1240*9356SAndrew.W.Wilson@sun.com fileset_delete_fileset(fileset); 1241*9356SAndrew.W.Wilson@sun.com } 1242*9356SAndrew.W.Wilson@sun.com 1243*9356SAndrew.W.Wilson@sun.com filebench_shm->shm_filesetlist = NULL; 1244*9356SAndrew.W.Wilson@sun.com } 1245*9356SAndrew.W.Wilson@sun.com /* 12465184Sek110237 * Adds an entry to the fileset's file list. Single threaded so 12475184Sek110237 * no locking needed. 12485184Sek110237 */ 12495184Sek110237 static void 12505184Sek110237 fileset_insfilelist(fileset_t *fileset, filesetentry_t *entry) 12515184Sek110237 { 12528404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_FILE | FSE_FREE; 12538404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_free_files, entry); 12548404SAndrew.W.Wilson@sun.com 12555184Sek110237 if (fileset->fs_filelist == NULL) { 12565184Sek110237 fileset->fs_filelist = entry; 12578404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12585184Sek110237 } else { 12598404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_filelist; 12605184Sek110237 fileset->fs_filelist = entry; 12615184Sek110237 } 12625184Sek110237 } 12635184Sek110237 12645184Sek110237 /* 12655184Sek110237 * Adds an entry to the fileset's directory list. Single 12665184Sek110237 * threaded so no locking needed. 12675184Sek110237 */ 12685184Sek110237 static void 12695184Sek110237 fileset_insdirlist(fileset_t *fileset, filesetentry_t *entry) 12705184Sek110237 { 12718404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_DIR | FSE_EXISTS; 12728404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_dirs, entry); 12738404SAndrew.W.Wilson@sun.com 12745184Sek110237 if (fileset->fs_dirlist == NULL) { 12755184Sek110237 fileset->fs_dirlist = entry; 12768404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12775184Sek110237 } else { 12788404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_dirlist; 12795184Sek110237 fileset->fs_dirlist = entry; 12805184Sek110237 } 12815184Sek110237 } 12825184Sek110237 12835184Sek110237 /* 12847946SAndrew.W.Wilson@sun.com * Adds an entry to the fileset's leaf directory list. Single 12857946SAndrew.W.Wilson@sun.com * threaded so no locking needed. 12867946SAndrew.W.Wilson@sun.com */ 12877946SAndrew.W.Wilson@sun.com static void 12887946SAndrew.W.Wilson@sun.com fileset_insleafdirlist(fileset_t *fileset, filesetentry_t *entry) 12897946SAndrew.W.Wilson@sun.com { 12908404SAndrew.W.Wilson@sun.com entry->fse_flags = FSE_TYPE_LEAFDIR | FSE_FREE; 12918404SAndrew.W.Wilson@sun.com avl_add(&fileset->fs_free_leaf_dirs, entry); 12928404SAndrew.W.Wilson@sun.com 12937946SAndrew.W.Wilson@sun.com if (fileset->fs_leafdirlist == NULL) { 12947946SAndrew.W.Wilson@sun.com fileset->fs_leafdirlist = entry; 12958404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = NULL; 12967946SAndrew.W.Wilson@sun.com } else { 12978404SAndrew.W.Wilson@sun.com entry->fse_nextoftype = fileset->fs_leafdirlist; 12987946SAndrew.W.Wilson@sun.com fileset->fs_leafdirlist = entry; 12997946SAndrew.W.Wilson@sun.com } 13007946SAndrew.W.Wilson@sun.com } 13017946SAndrew.W.Wilson@sun.com 13027946SAndrew.W.Wilson@sun.com /* 13038404SAndrew.W.Wilson@sun.com * Compares two fileset entries to determine their relative order 13048404SAndrew.W.Wilson@sun.com */ 13058404SAndrew.W.Wilson@sun.com static int 13068404SAndrew.W.Wilson@sun.com fileset_entry_compare(const void *node_1, const void *node_2) 13078404SAndrew.W.Wilson@sun.com { 13088404SAndrew.W.Wilson@sun.com if (((filesetentry_t *)node_1)->fse_index < 13098404SAndrew.W.Wilson@sun.com ((filesetentry_t *)node_2)->fse_index) 13108404SAndrew.W.Wilson@sun.com return (-1); 13118404SAndrew.W.Wilson@sun.com 13128404SAndrew.W.Wilson@sun.com if (((filesetentry_t *)node_1)->fse_index == 13138404SAndrew.W.Wilson@sun.com ((filesetentry_t *)node_2)->fse_index) 13148404SAndrew.W.Wilson@sun.com return (0); 13158404SAndrew.W.Wilson@sun.com 13168404SAndrew.W.Wilson@sun.com return (1); 13178404SAndrew.W.Wilson@sun.com } 13188404SAndrew.W.Wilson@sun.com 13198404SAndrew.W.Wilson@sun.com /* 13207946SAndrew.W.Wilson@sun.com * Obtains a filesetentry entity for a file to be placed in a 13215184Sek110237 * (sub)directory of a fileset. The size of the file may be 13226212Saw148015 * specified by fileset_meansize, or calculated from a gamma 13236212Saw148015 * distribution of parameter fileset_sizegamma and of mean size 13246212Saw148015 * fileset_meansize. The filesetentry entity is placed on the file 13255184Sek110237 * list in the specified parent filesetentry entity, which may 13265184Sek110237 * be a directory filesetentry, or the root filesetentry in the 13275184Sek110237 * fileset. It is also placed on the fileset's list of all 13287556SAndrew.W.Wilson@sun.com * contained files. Returns FILEBENCH_OK if successful or FILEBENCH_ERROR 13297556SAndrew.W.Wilson@sun.com * if ipc memory for the path string cannot be allocated. 13305184Sek110237 */ 13315184Sek110237 static int 13325184Sek110237 fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial) 13335184Sek110237 { 13345184Sek110237 char tmpname[16]; 13355184Sek110237 filesetentry_t *entry; 13365184Sek110237 double drand; 13378404SAndrew.W.Wilson@sun.com uint_t index; 13385184Sek110237 13395184Sek110237 if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 13405184Sek110237 == NULL) { 13415184Sek110237 filebench_log(LOG_ERROR, 13425184Sek110237 "fileset_populate_file: Can't malloc filesetentry"); 13437556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 13445184Sek110237 } 13455184Sek110237 13467556SAndrew.W.Wilson@sun.com /* Another currently idle file */ 13477556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 13488404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_files++; 13497556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 13507556SAndrew.W.Wilson@sun.com 13518404SAndrew.W.Wilson@sun.com entry->fse_index = index; 13525184Sek110237 entry->fse_parent = parent; 13535184Sek110237 entry->fse_fileset = fileset; 13545184Sek110237 fileset_insfilelist(fileset, entry); 13555184Sek110237 13565184Sek110237 (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 13575184Sek110237 if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 13585184Sek110237 filebench_log(LOG_ERROR, 13595184Sek110237 "fileset_populate_file: Can't alloc path string"); 13607556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 13615184Sek110237 } 13625184Sek110237 13636212Saw148015 /* see if random variable was supplied for file size */ 13646212Saw148015 if (fileset->fs_meansize == -1) { 13656212Saw148015 entry->fse_size = (off64_t)avd_get_int(fileset->fs_size); 13666212Saw148015 } else { 13676212Saw148015 double gamma; 13685184Sek110237 13696212Saw148015 gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0; 13706212Saw148015 if (gamma > 0) { 13716212Saw148015 drand = gamma_dist_knuth(gamma, 13726212Saw148015 fileset->fs_meansize / gamma); 13736212Saw148015 entry->fse_size = (off64_t)drand; 13746212Saw148015 } else { 13756212Saw148015 entry->fse_size = (off64_t)fileset->fs_meansize; 13766212Saw148015 } 13775184Sek110237 } 13785184Sek110237 13795184Sek110237 fileset->fs_bytes += entry->fse_size; 13805184Sek110237 13815184Sek110237 fileset->fs_realfiles++; 13827556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 13835184Sek110237 } 13845184Sek110237 13855184Sek110237 /* 13867946SAndrew.W.Wilson@sun.com * Obtaines a filesetentry entity for a leaf directory to be placed in a 13877946SAndrew.W.Wilson@sun.com * (sub)directory of a fileset. The leaf directory will always be empty so 13887946SAndrew.W.Wilson@sun.com * it can be created and deleted (mkdir, rmdir) at will. The filesetentry 13897946SAndrew.W.Wilson@sun.com * entity is placed on the leaf directory list in the specified parent 13907946SAndrew.W.Wilson@sun.com * filesetentry entity, which may be a (sub) directory filesetentry, or 13917946SAndrew.W.Wilson@sun.com * the root filesetentry in the fileset. It is also placed on the fileset's 13927946SAndrew.W.Wilson@sun.com * list of all contained leaf directories. Returns FILEBENCH_OK if successful 13937946SAndrew.W.Wilson@sun.com * or FILEBENCH_ERROR if ipc memory cannot be allocated. 13947946SAndrew.W.Wilson@sun.com */ 13957946SAndrew.W.Wilson@sun.com static int 13967946SAndrew.W.Wilson@sun.com fileset_populate_leafdir(fileset_t *fileset, filesetentry_t *parent, int serial) 13977946SAndrew.W.Wilson@sun.com { 13987946SAndrew.W.Wilson@sun.com char tmpname[16]; 13997946SAndrew.W.Wilson@sun.com filesetentry_t *entry; 14008404SAndrew.W.Wilson@sun.com uint_t index; 14017946SAndrew.W.Wilson@sun.com 14027946SAndrew.W.Wilson@sun.com if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 14037946SAndrew.W.Wilson@sun.com == NULL) { 14047946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 14057946SAndrew.W.Wilson@sun.com "fileset_populate_file: Can't malloc filesetentry"); 14067946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14077946SAndrew.W.Wilson@sun.com } 14087946SAndrew.W.Wilson@sun.com 14097946SAndrew.W.Wilson@sun.com /* Another currently idle leaf directory */ 14107946SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 14118404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_leafdirs++; 14127946SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 14137946SAndrew.W.Wilson@sun.com 14148404SAndrew.W.Wilson@sun.com entry->fse_index = index; 14157946SAndrew.W.Wilson@sun.com entry->fse_parent = parent; 14167946SAndrew.W.Wilson@sun.com entry->fse_fileset = fileset; 14177946SAndrew.W.Wilson@sun.com fileset_insleafdirlist(fileset, entry); 14187946SAndrew.W.Wilson@sun.com 14197946SAndrew.W.Wilson@sun.com (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 14207946SAndrew.W.Wilson@sun.com if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 14217946SAndrew.W.Wilson@sun.com filebench_log(LOG_ERROR, 14227946SAndrew.W.Wilson@sun.com "fileset_populate_file: Can't alloc path string"); 14237946SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14247946SAndrew.W.Wilson@sun.com } 14257946SAndrew.W.Wilson@sun.com 14267946SAndrew.W.Wilson@sun.com fileset->fs_realleafdirs++; 14277946SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 14287946SAndrew.W.Wilson@sun.com } 14297946SAndrew.W.Wilson@sun.com 14307946SAndrew.W.Wilson@sun.com /* 14315184Sek110237 * Creates a directory node in a fileset, by obtaining a 14325184Sek110237 * filesetentry entity for the node and initializing it 14335184Sek110237 * according to parameters of the fileset. It determines a 14345184Sek110237 * directory tree depth and directory width, optionally using 14355184Sek110237 * a gamma distribution. If its calculated depth is less then 14365184Sek110237 * its actual depth in the directory tree, it becomes a leaf 14375184Sek110237 * node and files itself with "width" number of file type 14385184Sek110237 * filesetentries, otherwise it files itself with "width" 14395184Sek110237 * number of directory type filesetentries, using recursive 14405184Sek110237 * calls to fileset_populate_subdir. The end result of the 14415184Sek110237 * initial call to this routine is a tree of directories of 14425184Sek110237 * random width and varying depth with sufficient leaf 14435184Sek110237 * directories to contain all required files. 14447556SAndrew.W.Wilson@sun.com * Returns FILEBENCH_OK on success. Returns FILEBENCH_ERROR if ipc path 14457556SAndrew.W.Wilson@sun.com * string memory cannot be allocated and returns the error code (currently 14467556SAndrew.W.Wilson@sun.com * also FILEBENCH_ERROR) from calls to fileset_populate_file or recursive 14475184Sek110237 * calls to fileset_populate_subdir. 14485184Sek110237 */ 14495184Sek110237 static int 14505184Sek110237 fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, 14515184Sek110237 int serial, double depth) 14525184Sek110237 { 14536212Saw148015 double randepth, drand, ranwidth; 14545184Sek110237 int isleaf = 0; 14555184Sek110237 char tmpname[16]; 14565184Sek110237 filesetentry_t *entry; 14575184Sek110237 int i; 14588404SAndrew.W.Wilson@sun.com uint_t index; 14595184Sek110237 14605184Sek110237 depth += 1; 14615184Sek110237 14625184Sek110237 /* Create dir node */ 14635184Sek110237 if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) 14645184Sek110237 == NULL) { 14655184Sek110237 filebench_log(LOG_ERROR, 14665184Sek110237 "fileset_populate_subdir: Can't malloc filesetentry"); 14677556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14685184Sek110237 } 14695184Sek110237 14707556SAndrew.W.Wilson@sun.com /* another idle directory */ 14717556SAndrew.W.Wilson@sun.com (void) ipc_mutex_lock(&fileset->fs_pick_lock); 14728404SAndrew.W.Wilson@sun.com index = fileset->fs_idle_dirs++; 14737556SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock(&fileset->fs_pick_lock); 14745184Sek110237 14755184Sek110237 (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); 14765184Sek110237 if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { 14775184Sek110237 filebench_log(LOG_ERROR, 14785184Sek110237 "fileset_populate_subdir: Can't alloc path string"); 14797556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 14805184Sek110237 } 14815184Sek110237 14828404SAndrew.W.Wilson@sun.com entry->fse_index = index; 14835184Sek110237 entry->fse_parent = parent; 14847946SAndrew.W.Wilson@sun.com entry->fse_fileset = fileset; 14855184Sek110237 fileset_insdirlist(fileset, entry); 14865184Sek110237 14876212Saw148015 if (fileset->fs_dirdepthrv) { 14886212Saw148015 randepth = (int)avd_get_int(fileset->fs_dirdepthrv); 14895184Sek110237 } else { 14906212Saw148015 double gamma; 14916212Saw148015 14926212Saw148015 gamma = avd_get_int(fileset->fs_dirgamma) / 1000.0; 14936212Saw148015 if (gamma > 0) { 14946212Saw148015 drand = gamma_dist_knuth(gamma, 14956212Saw148015 fileset->fs_meandepth / gamma); 14966212Saw148015 randepth = (int)drand; 14976212Saw148015 } else { 14986212Saw148015 randepth = (int)fileset->fs_meandepth; 14996212Saw148015 } 15005184Sek110237 } 15015184Sek110237 15026212Saw148015 if (fileset->fs_meanwidth == -1) { 15036212Saw148015 ranwidth = avd_get_dbl(fileset->fs_dirwidth); 15046212Saw148015 } else { 15056212Saw148015 double gamma; 15065184Sek110237 15076212Saw148015 gamma = avd_get_int(fileset->fs_sizegamma) / 1000.0; 15086212Saw148015 if (gamma > 0) { 15096212Saw148015 drand = gamma_dist_knuth(gamma, 15106212Saw148015 fileset->fs_meanwidth / gamma); 15116212Saw148015 ranwidth = drand; 15126212Saw148015 } else { 15136212Saw148015 ranwidth = fileset->fs_meanwidth; 15146212Saw148015 } 15155184Sek110237 } 15165184Sek110237 15175184Sek110237 if (randepth == 0) 15185184Sek110237 randepth = 1; 15195184Sek110237 if (ranwidth == 0) 15205184Sek110237 ranwidth = 1; 15215184Sek110237 if (depth >= randepth) 15225184Sek110237 isleaf = 1; 15235184Sek110237 15245184Sek110237 /* 15257946SAndrew.W.Wilson@sun.com * Create directory of random width filled with files according 15267946SAndrew.W.Wilson@sun.com * to distribution, or if root directory, continue until #files required 15275184Sek110237 */ 15286212Saw148015 for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && 15296212Saw148015 (fileset->fs_realfiles < fileset->fs_constentries); 15306212Saw148015 i++) { 15315184Sek110237 int ret = 0; 15325184Sek110237 15335184Sek110237 if (parent && isleaf) 15345184Sek110237 ret = fileset_populate_file(fileset, entry, i); 15355184Sek110237 else 15365184Sek110237 ret = fileset_populate_subdir(fileset, entry, i, depth); 15375184Sek110237 15385184Sek110237 if (ret != 0) 15395184Sek110237 return (ret); 15405184Sek110237 } 15417946SAndrew.W.Wilson@sun.com 15427946SAndrew.W.Wilson@sun.com /* 15437946SAndrew.W.Wilson@sun.com * Create directory of random width filled with leaf directories 15447946SAndrew.W.Wilson@sun.com * according to distribution, or if root directory, continue until 15457946SAndrew.W.Wilson@sun.com * the number of leaf directories required has been generated. 15467946SAndrew.W.Wilson@sun.com */ 15477946SAndrew.W.Wilson@sun.com for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && 15487946SAndrew.W.Wilson@sun.com (fileset->fs_realleafdirs < fileset->fs_constleafdirs); 15497946SAndrew.W.Wilson@sun.com i++) { 15507946SAndrew.W.Wilson@sun.com int ret = 0; 15517946SAndrew.W.Wilson@sun.com 15527946SAndrew.W.Wilson@sun.com if (parent && isleaf) 15537946SAndrew.W.Wilson@sun.com ret = fileset_populate_leafdir(fileset, entry, i); 15547946SAndrew.W.Wilson@sun.com else 15557946SAndrew.W.Wilson@sun.com ret = fileset_populate_subdir(fileset, entry, i, depth); 15567946SAndrew.W.Wilson@sun.com 15577946SAndrew.W.Wilson@sun.com if (ret != 0) 15587946SAndrew.W.Wilson@sun.com return (ret); 15597946SAndrew.W.Wilson@sun.com } 15607946SAndrew.W.Wilson@sun.com 15617556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 15625184Sek110237 } 15635184Sek110237 15645184Sek110237 /* 15655184Sek110237 * Populates a fileset with files and subdirectory entries. Uses 15666212Saw148015 * the supplied fileset_dirwidth and fileset_entries (number of files) to 15676212Saw148015 * calculate the required fileset_meandepth (of subdirectories) and 15686212Saw148015 * initialize the fileset_meanwidth and fileset_meansize variables. Then 15695184Sek110237 * calls fileset_populate_subdir() to do the recursive 15705184Sek110237 * subdirectory entry creation and leaf file entry creation. All 15715184Sek110237 * of the above is skipped if the fileset has already been 15725184Sek110237 * populated. Returns 0 on success, or an error code from the 15735184Sek110237 * call to fileset_populate_subdir if that call fails. 15745184Sek110237 */ 15755184Sek110237 static int 15765184Sek110237 fileset_populate(fileset_t *fileset) 15775184Sek110237 { 15788404SAndrew.W.Wilson@sun.com fbint_t entries = avd_get_int(fileset->fs_entries); 15798404SAndrew.W.Wilson@sun.com fbint_t leafdirs = avd_get_int(fileset->fs_leafdirs); 15806212Saw148015 int meandirwidth; 15815184Sek110237 int ret; 15825184Sek110237 15835184Sek110237 /* Skip if already populated */ 15845184Sek110237 if (fileset->fs_bytes > 0) 15855184Sek110237 goto exists; 15865184Sek110237 15875673Saw148015 #ifdef HAVE_RAW_SUPPORT 15885673Saw148015 /* check for raw device */ 15895673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) 15907556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 15915673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 15925673Saw148015 15937946SAndrew.W.Wilson@sun.com /* 15947946SAndrew.W.Wilson@sun.com * save value of entries and leaf dirs obtained for later 15957946SAndrew.W.Wilson@sun.com * in case it was random 15967946SAndrew.W.Wilson@sun.com */ 15976212Saw148015 fileset->fs_constentries = entries; 15987946SAndrew.W.Wilson@sun.com fileset->fs_constleafdirs = leafdirs; 15996212Saw148015 16007556SAndrew.W.Wilson@sun.com /* initialize idle files and directories condition variables */ 16017946SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_files_cv, ipc_condattr()); 16027556SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_dirs_cv, ipc_condattr()); 16037946SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_idle_leafdirs_cv, ipc_condattr()); 16047556SAndrew.W.Wilson@sun.com 16057556SAndrew.W.Wilson@sun.com /* no files or dirs idle (or busy) yet */ 16067556SAndrew.W.Wilson@sun.com fileset->fs_idle_files = 0; 16077556SAndrew.W.Wilson@sun.com fileset->fs_idle_dirs = 0; 16087946SAndrew.W.Wilson@sun.com fileset->fs_idle_leafdirs = 0; 16097556SAndrew.W.Wilson@sun.com 16107556SAndrew.W.Wilson@sun.com /* initialize locks and other condition variables */ 16117556SAndrew.W.Wilson@sun.com (void) pthread_mutex_init(&fileset->fs_pick_lock, 16127556SAndrew.W.Wilson@sun.com ipc_mutexattr(IPC_MUTEX_NORMAL)); 16138404SAndrew.W.Wilson@sun.com (void) pthread_mutex_init(&fileset->fs_histo_lock, 16148404SAndrew.W.Wilson@sun.com ipc_mutexattr(IPC_MUTEX_NORMAL)); 16157556SAndrew.W.Wilson@sun.com (void) pthread_cond_init(&fileset->fs_thrd_wait_cv, ipc_condattr()); 16167556SAndrew.W.Wilson@sun.com 16178404SAndrew.W.Wilson@sun.com /* Initialize avl btrees */ 16188404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_free_files), fileset_entry_compare, 16198404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16208404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_noex_files), fileset_entry_compare, 16218404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16228404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_exist_files), fileset_entry_compare, 16238404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16248404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_free_leaf_dirs), fileset_entry_compare, 16258404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16268404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_noex_leaf_dirs), fileset_entry_compare, 16278404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16288404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_exist_leaf_dirs), fileset_entry_compare, 16298404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16308404SAndrew.W.Wilson@sun.com avl_create(&(fileset->fs_dirs), fileset_entry_compare, 16318404SAndrew.W.Wilson@sun.com sizeof (filesetentry_t), FSE_OFFSETOF(fse_link)); 16328404SAndrew.W.Wilson@sun.com 16336212Saw148015 /* is dirwidth a random variable? */ 16346212Saw148015 if (AVD_IS_RANDOM(fileset->fs_dirwidth)) { 16356212Saw148015 meandirwidth = 16366212Saw148015 (int)fileset->fs_dirwidth->avd_val.randptr->rnd_dbl_mean; 16376212Saw148015 fileset->fs_meanwidth = -1; 16386212Saw148015 } else { 16396212Saw148015 meandirwidth = (int)avd_get_int(fileset->fs_dirwidth); 16406212Saw148015 fileset->fs_meanwidth = (double)meandirwidth; 16416212Saw148015 } 16426212Saw148015 16435184Sek110237 /* 16445184Sek110237 * Input params are: 16455184Sek110237 * # of files 16465184Sek110237 * ave # of files per dir 16475184Sek110237 * max size of dir 16485184Sek110237 * # ave size of file 16495184Sek110237 * max size of file 16505184Sek110237 */ 16517946SAndrew.W.Wilson@sun.com fileset->fs_meandepth = log(entries+leafdirs) / log(meandirwidth); 16526212Saw148015 16536212Saw148015 /* Has a random variable been supplied for dirdepth? */ 16546212Saw148015 if (fileset->fs_dirdepthrv) { 16556212Saw148015 /* yes, so set the random variable's mean value to meandepth */ 16566212Saw148015 fileset->fs_dirdepthrv->avd_val.randptr->rnd_dbl_mean = 16576212Saw148015 fileset->fs_meandepth; 16586212Saw148015 } 16596212Saw148015 16606212Saw148015 /* test for random size variable */ 16616212Saw148015 if (AVD_IS_RANDOM(fileset->fs_size)) 16626212Saw148015 fileset->fs_meansize = -1; 16636212Saw148015 else 16646212Saw148015 fileset->fs_meansize = avd_get_int(fileset->fs_size); 16655184Sek110237 16665184Sek110237 if ((ret = fileset_populate_subdir(fileset, NULL, 1, 0)) != 0) 16675184Sek110237 return (ret); 16685184Sek110237 16695184Sek110237 16705184Sek110237 exists: 16715673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) { 16726286Saw148015 filebench_log(LOG_VERBOSE, "File %s: mbytes=%llu", 16736212Saw148015 avd_get_str(fileset->fs_name), 16746286Saw148015 (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); 16755673Saw148015 } else { 16767946SAndrew.W.Wilson@sun.com filebench_log(LOG_VERBOSE, "Fileset %s: %d files, %d leafdirs " 16776286Saw148015 "avg dir = %d, avg depth = %.1lf, mbytes=%llu", 16787946SAndrew.W.Wilson@sun.com avd_get_str(fileset->fs_name), entries, leafdirs, 16796212Saw148015 meandirwidth, 16805673Saw148015 fileset->fs_meandepth, 16816286Saw148015 (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); 16825673Saw148015 } 16836701Saw148015 16847556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 16855184Sek110237 } 16865184Sek110237 16875184Sek110237 /* 16886212Saw148015 * Allocates a fileset instance, initializes fileset_dirgamma and 16896212Saw148015 * fileset_sizegamma default values, and sets the fileset name to the 16905184Sek110237 * supplied name string. Puts the allocated fileset on the 16915184Sek110237 * master fileset list and returns a pointer to it. 16926701Saw148015 * 16936701Saw148015 * This routine implements the 'define fileset' calls found in a .f 16946701Saw148015 * workload, such as in the following example: 16956701Saw148015 * define fileset name=drew4ever, entries=$nfiles 16965184Sek110237 */ 16975184Sek110237 fileset_t * 16986212Saw148015 fileset_define(avd_t name) 16995184Sek110237 { 17005184Sek110237 fileset_t *fileset; 17015184Sek110237 17025184Sek110237 if (name == NULL) 17035184Sek110237 return (NULL); 17045184Sek110237 17055184Sek110237 if ((fileset = (fileset_t *)ipc_malloc(FILEBENCH_FILESET)) == NULL) { 17065184Sek110237 filebench_log(LOG_ERROR, 17075184Sek110237 "fileset_define: Can't malloc fileset"); 17085184Sek110237 return (NULL); 17095184Sek110237 } 17105184Sek110237 17116212Saw148015 filebench_log(LOG_DEBUG_IMPL, 17126212Saw148015 "Defining file %s", avd_get_str(name)); 17135184Sek110237 17146391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 17155184Sek110237 17166212Saw148015 fileset->fs_dirgamma = avd_int_alloc(1500); 17176212Saw148015 fileset->fs_sizegamma = avd_int_alloc(1500); 17188404SAndrew.W.Wilson@sun.com fileset->fs_histo_id = -1; 17195184Sek110237 17205184Sek110237 /* Add fileset to global list */ 17216391Saw148015 if (filebench_shm->shm_filesetlist == NULL) { 17226391Saw148015 filebench_shm->shm_filesetlist = fileset; 17235184Sek110237 fileset->fs_next = NULL; 17245184Sek110237 } else { 17256391Saw148015 fileset->fs_next = filebench_shm->shm_filesetlist; 17266391Saw148015 filebench_shm->shm_filesetlist = fileset; 17275184Sek110237 } 17285184Sek110237 17296391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 17305184Sek110237 17316212Saw148015 fileset->fs_name = name; 17325184Sek110237 17335184Sek110237 return (fileset); 17345184Sek110237 } 17355184Sek110237 17365184Sek110237 /* 17375184Sek110237 * If supplied with a pointer to a fileset and the fileset's 17386212Saw148015 * fileset_prealloc flag is set, calls fileset_populate() to populate 17395184Sek110237 * the fileset with filesetentries, then calls fileset_create() 17405184Sek110237 * to make actual directories and files for the filesetentries. 17415184Sek110237 * Otherwise, it applies fileset_populate() and fileset_create() 17425184Sek110237 * to all the filesets on the master fileset list. It always 17435184Sek110237 * returns zero (0) if one fileset is populated / created, 17445184Sek110237 * otherwise it returns the sum of returned values from 17455184Sek110237 * fileset_create() and fileset_populate(), which 17465184Sek110237 * will be a negative one (-1) times the number of 17475184Sek110237 * fileset_create() calls which failed. 17485184Sek110237 */ 17495184Sek110237 int 17505184Sek110237 fileset_createset(fileset_t *fileset) 17515184Sek110237 { 17525184Sek110237 fileset_t *list; 17535184Sek110237 int ret = 0; 17545184Sek110237 17555673Saw148015 /* set up for possible parallel allocate */ 17567556SAndrew.W.Wilson@sun.com filebench_shm->shm_fsparalloc_count = 0; 17577556SAndrew.W.Wilson@sun.com (void) pthread_cond_init( 17587556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 17597556SAndrew.W.Wilson@sun.com ipc_condattr()); 17605673Saw148015 17616212Saw148015 if (fileset && avd_get_bool(fileset->fs_prealloc)) { 17625673Saw148015 17636305Saw148015 /* check for raw files */ 17646305Saw148015 if (fileset_checkraw(fileset)) { 17656305Saw148015 filebench_log(LOG_INFO, 17666305Saw148015 "file %s/%s is a RAW device", 17676305Saw148015 avd_get_str(fileset->fs_path), 17686305Saw148015 avd_get_str(fileset->fs_name)); 17697556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 17706305Saw148015 } 17716305Saw148015 17725673Saw148015 filebench_log(LOG_INFO, 17735673Saw148015 "creating/pre-allocating %s %s", 17746212Saw148015 fileset_entity_name(fileset), 17756212Saw148015 avd_get_str(fileset->fs_name)); 17765673Saw148015 17777556SAndrew.W.Wilson@sun.com if ((ret = fileset_populate(fileset)) != FILEBENCH_OK) 17785184Sek110237 return (ret); 17795673Saw148015 17807556SAndrew.W.Wilson@sun.com if ((ret = fileset_create(fileset)) != FILEBENCH_OK) 17815673Saw148015 return (ret); 17825673Saw148015 } else { 17835673Saw148015 17845673Saw148015 filebench_log(LOG_INFO, 17855673Saw148015 "Creating/pre-allocating files and filesets"); 17865673Saw148015 17876391Saw148015 list = filebench_shm->shm_filesetlist; 17885673Saw148015 while (list) { 17896305Saw148015 /* check for raw files */ 17906305Saw148015 if (fileset_checkraw(list)) { 17916305Saw148015 filebench_log(LOG_INFO, 17926305Saw148015 "file %s/%s is a RAW device", 17936305Saw148015 avd_get_str(list->fs_path), 17946305Saw148015 avd_get_str(list->fs_name)); 17956305Saw148015 list = list->fs_next; 17966305Saw148015 continue; 17976305Saw148015 } 17986305Saw148015 17997556SAndrew.W.Wilson@sun.com if ((ret = fileset_populate(list)) != FILEBENCH_OK) 18005673Saw148015 return (ret); 18017556SAndrew.W.Wilson@sun.com 18027556SAndrew.W.Wilson@sun.com if ((ret = fileset_create(list)) != FILEBENCH_OK) 18035673Saw148015 return (ret); 18047556SAndrew.W.Wilson@sun.com 18055673Saw148015 list = list->fs_next; 18065673Saw148015 } 18075184Sek110237 } 18085184Sek110237 18095673Saw148015 /* wait for allocation threads to finish */ 18105673Saw148015 filebench_log(LOG_INFO, 18115673Saw148015 "waiting for fileset pre-allocation to finish"); 18125184Sek110237 18137556SAndrew.W.Wilson@sun.com (void) pthread_mutex_lock(&filebench_shm->shm_fsparalloc_lock); 18147556SAndrew.W.Wilson@sun.com while (filebench_shm->shm_fsparalloc_count > 0) 18157556SAndrew.W.Wilson@sun.com (void) pthread_cond_wait( 18167556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_cv, 18177556SAndrew.W.Wilson@sun.com &filebench_shm->shm_fsparalloc_lock); 18187556SAndrew.W.Wilson@sun.com (void) pthread_mutex_unlock(&filebench_shm->shm_fsparalloc_lock); 18195673Saw148015 18207556SAndrew.W.Wilson@sun.com if (filebench_shm->shm_fsparalloc_count < 0) 18217556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 18225673Saw148015 18237556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 18245184Sek110237 } 18255184Sek110237 18265184Sek110237 /* 18275184Sek110237 * Searches through the master fileset list for the named fileset. 18285184Sek110237 * If found, returns pointer to same, otherwise returns NULL. 18295184Sek110237 */ 18305184Sek110237 fileset_t * 18315184Sek110237 fileset_find(char *name) 18325184Sek110237 { 18336391Saw148015 fileset_t *fileset = filebench_shm->shm_filesetlist; 18345184Sek110237 18356391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 18365184Sek110237 18375184Sek110237 while (fileset) { 18386212Saw148015 if (strcmp(name, avd_get_str(fileset->fs_name)) == 0) { 18396391Saw148015 (void) ipc_mutex_unlock( 18406391Saw148015 &filebench_shm->shm_fileset_lock); 18415184Sek110237 return (fileset); 18425184Sek110237 } 18435184Sek110237 fileset = fileset->fs_next; 18445184Sek110237 } 18456391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 18465184Sek110237 18475184Sek110237 return (NULL); 18485184Sek110237 } 18495673Saw148015 18505673Saw148015 /* 18515673Saw148015 * Iterates over all the file sets in the filesetlist, 18525673Saw148015 * executing the supplied command "*cmd()" on them. Also 18535673Saw148015 * indicates to the executed command if it is the first 18545673Saw148015 * time the command has been executed since the current 18555673Saw148015 * call to fileset_iter. 18565673Saw148015 */ 18578404SAndrew.W.Wilson@sun.com int 18585673Saw148015 fileset_iter(int (*cmd)(fileset_t *fileset, int first)) 18595673Saw148015 { 18606391Saw148015 fileset_t *fileset = filebench_shm->shm_filesetlist; 18615673Saw148015 int count = 0; 18625673Saw148015 18636391Saw148015 (void) ipc_mutex_lock(&filebench_shm->shm_fileset_lock); 18645673Saw148015 18655673Saw148015 while (fileset) { 18668404SAndrew.W.Wilson@sun.com if (cmd(fileset, count == 0) == FILEBENCH_ERROR) { 18678404SAndrew.W.Wilson@sun.com (void) ipc_mutex_unlock( 18688404SAndrew.W.Wilson@sun.com &filebench_shm->shm_fileset_lock); 18698404SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 18708404SAndrew.W.Wilson@sun.com } 18715673Saw148015 fileset = fileset->fs_next; 18725673Saw148015 count++; 18735673Saw148015 } 18745673Saw148015 18756391Saw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_fileset_lock); 18768404SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 18775673Saw148015 } 18785673Saw148015 18795673Saw148015 /* 18805673Saw148015 * Prints information to the filebench log about the file 18815673Saw148015 * object. Also prints a header on the first call. 18825673Saw148015 */ 18835673Saw148015 int 18845673Saw148015 fileset_print(fileset_t *fileset, int first) 18855673Saw148015 { 18866212Saw148015 int pathlength; 18876212Saw148015 char *fileset_path; 18886212Saw148015 char *fileset_name; 18896212Saw148015 static char pad[] = " "; /* 30 spaces */ 18906212Saw148015 18916212Saw148015 if ((fileset_path = avd_get_str(fileset->fs_path)) == NULL) { 18926212Saw148015 filebench_log(LOG_ERROR, "%s path not set", 18936212Saw148015 fileset_entity_name(fileset)); 18947556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 18956212Saw148015 } 18966212Saw148015 18976212Saw148015 if ((fileset_name = avd_get_str(fileset->fs_name)) == NULL) { 18986212Saw148015 filebench_log(LOG_ERROR, "%s name not set", 18996212Saw148015 fileset_entity_name(fileset)); 19007556SAndrew.W.Wilson@sun.com return (FILEBENCH_ERROR); 19016212Saw148015 } 19026212Saw148015 19036212Saw148015 pathlength = strlen(fileset_path) + strlen(fileset_name); 19045673Saw148015 19055673Saw148015 if (pathlength > 29) 19065673Saw148015 pathlength = 29; 19075673Saw148015 19085673Saw148015 if (first) { 19095673Saw148015 filebench_log(LOG_INFO, "File or Fileset name%20s%12s%10s", 19105673Saw148015 "file size", 19115673Saw148015 "dir width", 19125673Saw148015 "entries"); 19135673Saw148015 } 19145673Saw148015 19155673Saw148015 if (fileset->fs_attrs & FILESET_IS_FILE) { 19165673Saw148015 if (fileset->fs_attrs & FILESET_IS_RAW_DEV) { 19175673Saw148015 filebench_log(LOG_INFO, 19185673Saw148015 "%s/%s%s (Raw Device)", 19196212Saw148015 fileset_path, fileset_name, &pad[pathlength]); 19205673Saw148015 } else { 19215673Saw148015 filebench_log(LOG_INFO, 19226286Saw148015 "%s/%s%s%9llu (Single File)", 19236212Saw148015 fileset_path, fileset_name, &pad[pathlength], 19246286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_size)); 19255673Saw148015 } 19265673Saw148015 } else { 19276286Saw148015 filebench_log(LOG_INFO, "%s/%s%s%9llu%12llu%10llu", 19286212Saw148015 fileset_path, fileset_name, 19295673Saw148015 &pad[pathlength], 19306286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_size), 19316286Saw148015 (u_longlong_t)avd_get_int(fileset->fs_dirwidth), 19326286Saw148015 (u_longlong_t)fileset->fs_constentries); 19335673Saw148015 } 19347556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19355673Saw148015 } 19367946SAndrew.W.Wilson@sun.com 19375673Saw148015 /* 19385673Saw148015 * checks to see if the path/name pair points to a raw device. If 19395673Saw148015 * so it sets the raw device flag (FILESET_IS_RAW_DEV) and returns 1. 19405673Saw148015 * If RAW is not defined, or it is not a raw device, it clears the 19415673Saw148015 * raw device flag and returns 0. 19425673Saw148015 */ 19435673Saw148015 int 19445673Saw148015 fileset_checkraw(fileset_t *fileset) 19455673Saw148015 { 19465673Saw148015 char path[MAXPATHLEN]; 19475673Saw148015 struct stat64 sb; 19486305Saw148015 char *pathname; 19496305Saw148015 char *setname; 19505673Saw148015 19515673Saw148015 fileset->fs_attrs &= (~FILESET_IS_RAW_DEV); 19525673Saw148015 19535673Saw148015 #ifdef HAVE_RAW_SUPPORT 19545673Saw148015 /* check for raw device */ 19556305Saw148015 if ((pathname = avd_get_str(fileset->fs_path)) == NULL) 19567556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19576305Saw148015 19586305Saw148015 if ((setname = avd_get_str(fileset->fs_name)) == NULL) 19597556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19606305Saw148015 19617946SAndrew.W.Wilson@sun.com (void) fb_strlcpy(path, pathname, MAXPATHLEN); 19627946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, "/", MAXPATHLEN); 19637946SAndrew.W.Wilson@sun.com (void) fb_strlcat(path, setname, MAXPATHLEN); 19645673Saw148015 if ((stat64(path, &sb) == 0) && 19655673Saw148015 ((sb.st_mode & S_IFMT) == S_IFBLK) && sb.st_rdev) { 19665673Saw148015 fileset->fs_attrs |= FILESET_IS_RAW_DEV; 19676305Saw148015 if (!(fileset->fs_attrs & FILESET_IS_FILE)) { 19686305Saw148015 filebench_log(LOG_ERROR, 19696305Saw148015 "WARNING Fileset %s/%s Cannot be RAW device", 19706305Saw148015 avd_get_str(fileset->fs_path), 19716305Saw148015 avd_get_str(fileset->fs_name)); 19726305Saw148015 filebench_shutdown(1); 19736305Saw148015 } 19746305Saw148015 19755673Saw148015 return (1); 19765673Saw148015 } 19775673Saw148015 #endif /* HAVE_RAW_SUPPORT */ 19785673Saw148015 19797556SAndrew.W.Wilson@sun.com return (FILEBENCH_OK); 19805673Saw148015 } 1981