diff options
author | aw148015 <Andrew.W.Wilson@sun.com> | 2008-10-27 11:14:30 -0700 |
---|---|---|
committer | aw148015 <Andrew.W.Wilson@sun.com> | 2008-10-27 11:14:30 -0700 |
commit | 0bb1cc7eeccb58d82ac6a19e80e41a3781810c28 (patch) | |
tree | da69b8fc153d7fb6f58cf9fbb0306ee8bd5a725b /usr/src | |
parent | 5338c544ca00e11e246822f5d465dd162f781dbf (diff) | |
download | illumos-joyent-0bb1cc7eeccb58d82ac6a19e80e41a3781810c28.tar.gz |
6720351 FileBench should have a Video Server like workload
6725102 FileBench needs some directory manipulation flowops
6753319 SUNWfilebench package dependency issue in snv_99
Diffstat (limited to 'usr/src')
22 files changed, 1108 insertions, 193 deletions
diff --git a/usr/src/cmd/filebench/common/eventgen.c b/usr/src/cmd/filebench/common/eventgen.c index 5080004ba3..71dce57d6c 100644 --- a/usr/src/cmd/filebench/common/eventgen.c +++ b/usr/src/cmd/filebench/common/eventgen.c @@ -25,8 +25,6 @@ * Portions Copyright 2008 Denis Cheng */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * The event generator in this module is the producer half of a * metering system which blocks flows using consumer routines in the @@ -86,16 +84,18 @@ eventgen_thread(void) while (1) { struct timespec sleeptime; hrtime_t delta; - int count; + int count, rate; - if (filebench_shm->shm_eventgen_hz == 0) { + if (filebench_shm->shm_eventgen_hz == NULL) { (void) sleep(1); continue; + } else { + rate = avd_get_int(filebench_shm->shm_eventgen_hz); } + /* Sleep for 10xperiod */ sleeptime.tv_sec = 0; - sleeptime.tv_nsec = FB_SEC2NSEC / - filebench_shm->shm_eventgen_hz; + sleeptime.tv_nsec = FB_SEC2NSEC / rate; sleeptime.tv_nsec *= 10; if (sleeptime.tv_nsec < 1000UL) @@ -108,7 +108,7 @@ eventgen_thread(void) (void) nanosleep(&sleeptime, NULL); delta = gethrtime() - last; last = gethrtime(); - count = (filebench_shm->shm_eventgen_hz * delta) / FB_SEC2NSEC; + count = (rate * delta) / FB_SEC2NSEC; filebench_log(LOG_DEBUG_SCRIPT, "delta %llums count %d", @@ -117,8 +117,7 @@ eventgen_thread(void) /* Send 'count' events */ (void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock); /* Keep the producer with a max of 5 second depth */ - if (filebench_shm->shm_eventgen_q < - (5 * filebench_shm->shm_eventgen_hz)) + if (filebench_shm->shm_eventgen_q < (5 * rate)) filebench_shm->shm_eventgen_q += count; (void) pthread_cond_signal(&filebench_shm->shm_eventgen_cv); @@ -157,22 +156,35 @@ eventgen_init(void) var_t * eventgen_ratevar(var_t *var) { - VAR_SET_INT(var, filebench_shm->shm_eventgen_hz); + VAR_SET_INT(var, avd_get_int(filebench_shm->shm_eventgen_hz)); return (var); } /* * Sets the event generator rate to that supplied by - * fbint_t rate. + * var_t *rate. */ void -eventgen_setrate(fbint_t rate) +eventgen_setrate(avd_t rate) { - filebench_shm->shm_eventgen_hz = (int)rate; + filebench_shm->shm_eventgen_hz = rate; + if (rate == NULL) { + filebench_log(LOG_ERROR, + "eventgen_setrate() called without a rate"); + return; + } + + if (AVD_IS_VAR(rate)) { + filebench_log(LOG_VERBOSE, + "Eventgen rate taken from variable"); + } else { + filebench_log(LOG_VERBOSE, "Eventgen: %llu per second", + (u_longlong_t)avd_get_int(rate)); + } } /* - * Turns off the event generator by setting the rate to zero + * Clears the event queue so we have a clean start */ void eventgen_reset(void) diff --git a/usr/src/cmd/filebench/common/eventgen.h b/usr/src/cmd/filebench/common/eventgen.h index 2f50fcac82..4797714224 100644 --- a/usr/src/cmd/filebench/common/eventgen.h +++ b/usr/src/cmd/filebench/common/eventgen.h @@ -26,8 +26,6 @@ #ifndef _FB_EVENTGEN_H #define _FB_EVENTGEN_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "config.h" #include "vars.h" @@ -37,7 +35,7 @@ extern "C" { #define FB_SEC2NSEC 1000000000UL void eventgen_init(void); -void eventgen_setrate(fbint_t rate); +void eventgen_setrate(avd_t rate); var_t *eventgen_ratevar(var_t *var); void eventgen_usage(void); void eventgen_reset(void); diff --git a/usr/src/cmd/filebench/common/filebench.h b/usr/src/cmd/filebench/common/filebench.h index d31df501c2..3c2e482bbb 100644 --- a/usr/src/cmd/filebench/common/filebench.h +++ b/usr/src/cmd/filebench/common/filebench.h @@ -117,7 +117,7 @@ void filebench_shutdown(int error); #define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif -#define FILEBENCH_VERSION "1.4.0" +#define FILEBENCH_VERSION "1.4.1" #define FILEBENCHDIR "/usr/benchmarks/filebench" #define FILEBENCH_PROMPT "filebench> " #define MAX_LINE_LEN 1024 diff --git a/usr/src/cmd/filebench/common/fileset.c b/usr/src/cmd/filebench/common/fileset.c index 99ee2887c9..4521913ec7 100644 --- a/usr/src/cmd/filebench/common/fileset.c +++ b/usr/src/cmd/filebench/common/fileset.c @@ -35,6 +35,7 @@ #include "filebench.h" #include "fileset.h" #include "gamma_dist.h" +#include "utils.h" /* * File sets, of type fileset_t, are entities which contain @@ -48,9 +49,10 @@ * Fileset entities are allocated by fileset_define() which is called from * parser_gram.y: parser_fileset_define(). The filesetentry tree corrseponding * to the eventual directory and file tree to be instantiated on the storage - * medium is built by fileset_populate(), which is called from - * fileset_createset(). After calling fileset_populate(), fileset_createset() - * will call fileset_create() to pre-allocate designated files and directories. + * medium is built by fileset_populate(), which is This routine is called + * from fileset_createset(), which is in turn called by fileset_createset(). + * After calling fileset_populate(), fileset_createset() will call + * fileset_create() to pre-allocate designated files and directories. * * Fileset_createset() is called from parser_gram.y: parser_create_fileset() * when a "create fileset" or "run" command is encountered. When the @@ -129,8 +131,8 @@ fileset_usage(void) /* * Frees up memory mapped file region of supplied size. The * file descriptor "fd" indicates which memory mapped file. - * If successful, returns 0. Otherwise returns -1 times the number of - * times msync() failed. + * If successful, returns 0. Otherwise returns -1 if "size" + * is zero, or -1 times the number of times msync() failed. */ static int fileset_freemem(int fd, off64_t size) @@ -166,17 +168,17 @@ fileset_resolvepath(filesetentry_t *entry) char pathtmp[MAXPATHLEN]; char *s; - *path = 0; + path[0] = '\0'; while (fsep->fse_parent) { (void) strcpy(pathtmp, "/"); - (void) strcat(pathtmp, fsep->fse_path); - (void) strcat(pathtmp, path); - (void) strcpy(path, pathtmp); + (void) fb_strlcat(pathtmp, fsep->fse_path, MAXPATHLEN); + (void) fb_strlcat(pathtmp, path, MAXPATHLEN); + (void) fb_strlcpy(path, pathtmp, MAXPATHLEN); fsep = fsep->fse_parent; } s = malloc(strlen(path) + 1); - (void) strcpy(s, path); + (void) fb_strlcpy(s, path, MAXPATHLEN); return (s); } @@ -233,7 +235,6 @@ null_str: filebench_log(LOG_ERROR, "Failed to create directory path %s: Out of memory", path); - return (FILEBENCH_ERROR); } @@ -250,9 +251,9 @@ fileset_create_subdirs(fileset_t *fileset, char *filesetpath) /* walk the subdirectory list, enstanciating subdirs */ direntry = fileset->fs_dirlist; while (direntry) { - (void) strcpy(full_path, filesetpath); + (void) fb_strlcpy(full_path, filesetpath, MAXPATHLEN); part_path = fileset_resolvepath(direntry); - (void) strcat(full_path, part_path); + (void) fb_strlcat(full_path, part_path, MAXPATHLEN); free(part_path); /* now create this portion of the subdirectory tree */ @@ -265,12 +266,56 @@ fileset_create_subdirs(fileset_t *fileset, char *filesetpath) } /* + * given a fileset entry, determines if the associated leaf directory + * needs to be made or not, and if so does the mkdir. + */ +static int +fileset_alloc_leafdir(filesetentry_t *entry) +{ + fileset_t *fileset; + char path[MAXPATHLEN]; + struct stat64 sb; + char *pathtmp; + + fileset = entry->fse_fileset; + (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); + pathtmp = fileset_resolvepath(entry); + (void) fb_strlcat(path, pathtmp, MAXPATHLEN); + free(pathtmp); + + filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); + + /* see if not reusing and this directory does not exist */ + if (!((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0))) { + + /* No file or not reusing, so create */ + if (mkdir(path, 0755) < 0) { + filebench_log(LOG_ERROR, + "Failed to pre-allocate leaf directory %s: %s", + path, strerror(errno)); + + return (FILEBENCH_ERROR); + } + } + + (void) ipc_mutex_lock(&fileset->fs_pick_lock); + entry->fse_flags |= FSE_EXISTS; + fileset->fs_num_act_leafdirs++; + (void) ipc_mutex_unlock(&fileset->fs_pick_lock); + + return (FILEBENCH_OK); +} + +/* * given a fileset entry, determines if the associated file * needs to be allocated or not, and if so does the allocation. */ static int fileset_alloc_file(filesetentry_t *entry) { + fileset_t *fileset; char path[MAXPATHLEN]; char *buf; struct stat64 sb; @@ -278,12 +323,13 @@ fileset_alloc_file(filesetentry_t *entry) off64_t seek; int fd; - *path = 0; - (void) strcpy(path, avd_get_str(entry->fse_fileset->fs_path)); - (void) strcat(path, "/"); - (void) strcat(path, avd_get_str(entry->fse_fileset->fs_name)); + fileset = entry->fse_fileset; + (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); pathtmp = fileset_resolvepath(entry); - (void) strcat(path, pathtmp); + (void) fb_strlcat(path, pathtmp, MAXPATHLEN); + free(pathtmp); filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); @@ -300,16 +346,14 @@ fileset_alloc_file(filesetentry_t *entry) filebench_log(LOG_DEBUG_IMPL, "Re-using file %s", path); - if (!avd_get_bool(entry->fse_fileset->fs_cached)) + if (!avd_get_bool(fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); - (void) ipc_mutex_lock( - &entry->fse_fileset->fs_pick_lock); + (void) ipc_mutex_lock(&fileset->fs_pick_lock); entry->fse_flags |= FSE_EXISTS; - entry->fse_fileset->fs_num_act_files++; - (void) ipc_mutex_unlock( - &entry->fse_fileset->fs_pick_lock); + fileset->fs_num_act_files++; + (void) ipc_mutex_unlock(&fileset->fs_pick_lock); (void) close(fd); return (FILEBENCH_OK); @@ -325,16 +369,14 @@ fileset_alloc_file(filesetentry_t *entry) (void) ftruncate(fd, (off_t)entry->fse_size); #endif - if (!avd_get_bool(entry->fse_fileset->fs_cached)) + if (!avd_get_bool(fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); - (void) ipc_mutex_lock( - &entry->fse_fileset->fs_pick_lock); + (void) ipc_mutex_lock(&fileset->fs_pick_lock); entry->fse_flags |= FSE_EXISTS; - entry->fse_fileset->fs_num_act_files++; - (void) ipc_mutex_unlock( - &entry->fse_fileset->fs_pick_lock); + fileset->fs_num_act_files++; + (void) ipc_mutex_unlock(&fileset->fs_pick_lock); (void) close(fd); return (FILEBENCH_OK); @@ -354,10 +396,10 @@ fileset_alloc_file(filesetentry_t *entry) if ((buf = (char *)malloc(FILE_ALLOC_BLOCK)) == NULL) return (FILEBENCH_ERROR); - (void) ipc_mutex_lock(&entry->fse_fileset->fs_pick_lock); + (void) ipc_mutex_lock(&fileset->fs_pick_lock); entry->fse_flags |= FSE_EXISTS; - entry->fse_fileset->fs_num_act_files++; - (void) ipc_mutex_unlock(&entry->fse_fileset->fs_pick_lock); + fileset->fs_num_act_files++; + (void) ipc_mutex_unlock(&fileset->fs_pick_lock); for (seek = 0; seek < entry->fse_size; ) { off64_t wsize; @@ -381,7 +423,7 @@ fileset_alloc_file(filesetentry_t *entry) seek += wsize; } - if (!avd_get_bool(entry->fse_fileset->fs_cached)) + if (!avd_get_bool(fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); (void) close(fd); @@ -438,13 +480,12 @@ fileset_openfile(fileset_t *fileset, int fd; int open_attrs = 0; - *path = 0; - (void) strcpy(path, avd_get_str(fileset->fs_path)); - (void) strcat(path, "/"); - (void) strcat(path, avd_get_str(fileset->fs_name)); + (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); pathtmp = fileset_resolvepath(entry); - (void) strcat(path, pathtmp); - (void) strcpy(dir, path); + (void) fb_strlcat(path, pathtmp, MAXPATHLEN); + (void) fb_strlcpy(dir, path, MAXPATHLEN); free(pathtmp); (void) trunc_dirname(dir); @@ -489,7 +530,8 @@ fileset_openfile(fileset_t *fileset, /* * Selects a fileset entry from a fileset. If the - * FILESET_PICKDIR flag is set it will pick a directory + * FILESET_PICKLEAFDIR flag is set it will pick a leaf directory entry, + * if the FILESET_PICKDIR flag is set it will pick a non leaf directory * entry, otherwise a file entry. The FILESET_PICKRESET * flag will cause it to reset the free list to the * overall list (file or directory). The FILESET_PICKUNIQUE @@ -512,72 +554,130 @@ fileset_pick(fileset_t *fileset, int flags, int tid) (void) ipc_mutex_lock(&fileset->fs_pick_lock); /* see if we have to wait for available files or directories */ - if (flags & FILESET_PICKDIR) { + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: + if (fileset->fs_filelist == NULL) + goto empty; + while (fileset->fs_idle_files == 0) { + (void) pthread_cond_wait(&fileset->fs_idle_files_cv, + &fileset->fs_pick_lock); + } + break; + case FILESET_PICKDIR: + if (fileset->fs_dirlist == NULL) + goto empty; while (fileset->fs_idle_dirs == 0) { (void) pthread_cond_wait(&fileset->fs_idle_dirs_cv, &fileset->fs_pick_lock); } - } else { - while (fileset->fs_idle_files == 0) { - (void) pthread_cond_wait(&fileset->fs_idle_files_cv, + break; + case FILESET_PICKLEAFDIR: + if (fileset->fs_leafdirlist == NULL) + goto empty; + while (fileset->fs_idle_leafdirs == 0) { + (void) pthread_cond_wait(&fileset->fs_idle_leafdirs_cv, &fileset->fs_pick_lock); } + break; } /* see if asking for impossible */ - if (flags & FILESET_PICKEXISTS) { - if (fileset->fs_num_act_files == 0) { - (void) ipc_mutex_unlock(&fileset->fs_pick_lock); - return (NULL); + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: + if (flags & FILESET_PICKEXISTS) { + if (fileset->fs_num_act_files == 0) { + (void) ipc_mutex_unlock( + &fileset->fs_pick_lock); + return (NULL); + } + } else if (flags & FILESET_PICKNOEXIST) { + if (fileset->fs_num_act_files == + fileset->fs_realfiles) { + (void) ipc_mutex_unlock( + &fileset->fs_pick_lock); + return (NULL); + } } - } else if (flags & FILESET_PICKNOEXIST) { - if (fileset->fs_num_act_files == fileset->fs_realfiles) { - (void) ipc_mutex_unlock(&fileset->fs_pick_lock); - return (NULL); + break; + case FILESET_PICKLEAFDIR: + if (flags & FILESET_PICKEXISTS) { + if (fileset->fs_num_act_leafdirs == 0) { + (void) ipc_mutex_unlock( + &fileset->fs_pick_lock); + return (NULL); + } + } else if (flags & FILESET_PICKNOEXIST) { + if (fileset->fs_num_act_leafdirs == + fileset->fs_realleafdirs) { + (void) ipc_mutex_unlock( + &fileset->fs_pick_lock); + return (NULL); + } } + break; + case FILESET_PICKDIR: + default: + break; } while (entry == NULL) { - if ((flags & FILESET_PICKDIR) && (flags & FILESET_PICKRESET)) { - entry = fileset->fs_dirlist; - while (entry) { - entry->fse_flags |= FSE_FREE; - entry = entry->fse_dirnext; - } - fileset->fs_dirfree = fileset->fs_dirlist; - } - - if (!(flags & FILESET_PICKDIR) && (flags & FILESET_PICKRESET)) { - entry = fileset->fs_filelist; - while (entry) { - entry->fse_flags |= FSE_FREE; - entry = entry->fse_filenext; + if (flags & FILESET_PICKRESET) { + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: + entry = fileset->fs_filelist; + while (entry) { + entry->fse_flags |= FSE_FREE; + entry = entry->fse_filenext; + } + fileset->fs_filefree = fileset->fs_filelist; + break; + case FILESET_PICKDIR: + entry = fileset->fs_dirlist; + while (entry) { + entry->fse_flags |= FSE_FREE; + entry = entry->fse_dirnext; + } + fileset->fs_dirfree = fileset->fs_dirlist; + break; + case FILESET_PICKLEAFDIR: + entry = fileset->fs_leafdirlist; + while (entry) { + entry->fse_flags |= FSE_FREE; + entry = entry->fse_leafdirnext; + } + fileset->fs_leafdirfree = + fileset->fs_leafdirlist; + break; } - fileset->fs_filefree = fileset->fs_filelist; } if (flags & FILESET_PICKUNIQUE) { - if (flags & FILESET_PICKDIR) { + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: + entry = fileset->fs_filefree; + if (entry == NULL) + goto empty; + fileset->fs_filefree = entry->fse_filenext; + break; + case FILESET_PICKDIR: entry = fileset->fs_dirfree; if (entry == NULL) goto empty; fileset->fs_dirfree = entry->fse_dirnext; - } else { - entry = fileset->fs_filefree; + break; + case FILESET_PICKLEAFDIR: + entry = fileset->fs_leafdirfree; if (entry == NULL) goto empty; - fileset->fs_filefree = entry->fse_filenext; + fileset->fs_leafdirfree = + entry->fse_leafdirnext; + break; } entry->fse_flags &= ~FSE_FREE; } else { - if (flags & FILESET_PICKDIR) { - entry = fileset->fs_dirrotor; - if (entry == NULL) - fileset->fs_dirrotor = - entry = fileset->fs_dirlist; - fileset->fs_dirrotor = entry->fse_dirnext; - } else { + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: if (flags & FILESET_PICKNOEXIST) { entry = fileset->fs_file_ne_rotor; if (entry == NULL) @@ -595,6 +695,22 @@ fileset_pick(fileset_t *fileset, int flags, int tid) fileset->fs_filerotor[tid] = entry->fse_filenext; } + break; + case FILESET_PICKDIR: + entry = fileset->fs_dirrotor; + if (entry == NULL) + fileset->fs_dirrotor = + entry = fileset->fs_dirlist; + fileset->fs_dirrotor = entry->fse_dirnext; + break; + case FILESET_PICKLEAFDIR: + entry = fileset->fs_leafdirrotor; + if (entry == NULL) + fileset->fs_leafdirrotor = + entry = fileset->fs_leafdirlist; + fileset->fs_leafdirrotor = + entry->fse_leafdirnext; + break; } } @@ -624,10 +740,17 @@ fileset_pick(fileset_t *fileset, int flags, int tid) } /* update file or directory idle counts */ - if (flags & FILESET_PICKDIR) - fileset->fs_idle_dirs--; - else + switch (flags & FILESET_PICKMASK) { + case FILESET_PICKFILE: fileset->fs_idle_files--; + break; + case FILESET_PICKDIR: + fileset->fs_idle_dirs--; + break; + case FILESET_PICKLEAFDIR: + fileset->fs_idle_leafdirs--; + break; + } /* Indicate that file or directory is now busy */ entry->fse_flags |= FSE_BUSY; @@ -650,7 +773,6 @@ void fileset_unbusy(filesetentry_t *entry, int update_exist, int new_exist_val) { fileset_t *fileset = NULL; - int fse_is_dir; if (entry) fileset = entry->fse_fileset; @@ -661,7 +783,6 @@ fileset_unbusy(filesetentry_t *entry, int update_exist, int new_exist_val) } (void) ipc_mutex_lock(&fileset->fs_pick_lock); - fse_is_dir = entry->fse_flags & FSE_DIR; /* increment idle count, clear FSE_BUSY and signal IF it was busy */ if (entry->fse_flags & FSE_BUSY) { @@ -677,18 +798,28 @@ fileset_unbusy(filesetentry_t *entry, int update_exist, int new_exist_val) } /* increment idle count and signal waiting threads */ - if (fse_is_dir) { + switch (entry->fse_flags & FSE_TYPE_MASK) { + case FSE_TYPE_FILE: + fileset->fs_idle_files++; + if (fileset->fs_idle_files == 1) { + (void) pthread_cond_signal( + &fileset->fs_idle_files_cv); + } + break; + case FSE_TYPE_DIR: fileset->fs_idle_dirs++; if (fileset->fs_idle_dirs == 1) { (void) pthread_cond_signal( &fileset->fs_idle_dirs_cv); } - } else { - fileset->fs_idle_files++; - if (fileset->fs_idle_files == 1) { + break; + case FSE_TYPE_LEAFDIR: + fileset->fs_idle_leafdirs++; + if (fileset->fs_idle_leafdirs == 1) { (void) pthread_cond_signal( - &fileset->fs_idle_files_cv); + &fileset->fs_idle_leafdirs_cv); } + break; } } @@ -699,20 +830,32 @@ fileset_unbusy(filesetentry_t *entry, int update_exist, int new_exist_val) /* asked to set, and it was clear */ entry->fse_flags |= FSE_EXISTS; - if (fse_is_dir) - fileset->fs_num_act_dirs++; - else + switch (entry->fse_flags & FSE_TYPE_MASK) { + case FSE_TYPE_FILE: fileset->fs_num_act_files++; + break; + case FSE_TYPE_DIR: + break; + case FSE_TYPE_LEAFDIR: + fileset->fs_num_act_leafdirs++; + break; + } } } else { if (entry->fse_flags & FSE_EXISTS) { /* asked to clear, and it was set */ entry->fse_flags &= (~FSE_EXISTS); - if (fse_is_dir) - fileset->fs_num_act_dirs--; - else + switch (entry->fse_flags & FSE_TYPE_MASK) { + case FSE_TYPE_FILE: fileset->fs_num_act_files--; + break; + case FSE_TYPE_DIR: + break; + case FSE_TYPE_LEAFDIR: + fileset->fs_num_act_leafdirs--; + break; + } } } } @@ -741,7 +884,7 @@ fileset_create(fileset_t *fileset) filesetentry_t *entry; char path[MAXPATHLEN]; struct stat64 sb; - int pickflags = FILESET_PICKUNIQUE | FILESET_PICKRESET; + int pickflags; hrtime_t start = gethrtime(); char *fileset_path; char *fileset_name; @@ -761,6 +904,9 @@ fileset_create(fileset_t *fileset) return (FILEBENCH_ERROR); } + /* declare all files currently non existant (single threaded code) */ + fileset->fs_num_act_files = 0; + #ifdef HAVE_RAW_SUPPORT /* treat raw device as special case */ if (fileset->fs_attrs & FILESET_IS_RAW_DEV) @@ -770,9 +916,9 @@ fileset_create(fileset_t *fileset) /* XXX Add check to see if there is enough space */ /* set up path to fileset */ - (void) strcpy(path, fileset_path); - (void) strcat(path, "/"); - (void) strcat(path, fileset_name); + (void) fb_strlcpy(path, fileset_path, MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, fileset_name, MAXPATHLEN); /* if exists and resusing, then don't create new */ if (((stat64(path, &sb) == 0)&& (strlen(path) > 3) && @@ -802,7 +948,7 @@ fileset_create(fileset_t *fileset) /* make the filesets directory tree unless in reuse mode */ if (!reusing && (avd_get_bool(fileset->fs_prealloc))) { - filebench_log(LOG_INFO, + filebench_log(LOG_VERBOSE, "making tree for filset %s", path); (void) mkdir(path, 0755); @@ -822,6 +968,8 @@ fileset_create(fileset_t *fileset) randno = ((RAND_MAX * (100 - avd_get_int(fileset->fs_preallocpercent))) / 100); + /* alloc any files, as required */ + pickflags = FILESET_PICKUNIQUE | FILESET_PICKRESET; while (entry = fileset_pick(fileset, pickflags, 0)) { pthread_t tid; int newrand; @@ -892,6 +1040,30 @@ fileset_create(fileset_t *fileset) } } + /* alloc any leaf directories, as required */ + pickflags = + FILESET_PICKUNIQUE | FILESET_PICKRESET | FILESET_PICKLEAFDIR; + while (entry = fileset_pick(fileset, pickflags, 0)) { + + pickflags = FILESET_PICKUNIQUE | FILESET_PICKLEAFDIR; + + /* entry doesn't need to be locked during initialization */ + fileset_unbusy(entry, FALSE, FALSE); + + if (rand() < randno) + continue; + + preallocated++; + + if (reusing) + entry->fse_flags |= FSE_REUSING; + else + entry->fse_flags &= (~FSE_REUSING); + + if (fileset_alloc_leafdir(entry) == FILEBENCH_ERROR) + return (FILEBENCH_ERROR); + } + exit: filebench_log(LOG_VERBOSE, "Preallocated %d of %llu of %s %s in %llu seconds", @@ -936,7 +1108,23 @@ fileset_insdirlist(fileset_t *fileset, filesetentry_t *entry) } /* - * Obtaines a filesetentry entity for a file to be placed in a + * Adds an entry to the fileset's leaf directory list. Single + * threaded so no locking needed. + */ +static void +fileset_insleafdirlist(fileset_t *fileset, filesetentry_t *entry) +{ + if (fileset->fs_leafdirlist == NULL) { + fileset->fs_leafdirlist = entry; + entry->fse_leafdirnext = NULL; + } else { + entry->fse_leafdirnext = fileset->fs_leafdirlist; + fileset->fs_leafdirlist = entry; + } +} + +/* + * Obtains a filesetentry entity for a file to be placed in a * (sub)directory of a fileset. The size of the file may be * specified by fileset_meansize, or calculated from a gamma * distribution of parameter fileset_sizegamma and of mean size @@ -968,7 +1156,7 @@ fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial) entry->fse_parent = parent; entry->fse_fileset = fileset; - entry->fse_flags = FSE_FREE; + entry->fse_flags = FSE_TYPE_FILE | FSE_FREE; fileset_insfilelist(fileset, entry); (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); @@ -1001,6 +1189,50 @@ fileset_populate_file(fileset_t *fileset, filesetentry_t *parent, int serial) } /* + * Obtaines a filesetentry entity for a leaf directory to be placed in a + * (sub)directory of a fileset. The leaf directory will always be empty so + * it can be created and deleted (mkdir, rmdir) at will. The filesetentry + * entity is placed on the leaf directory list in the specified parent + * filesetentry entity, which may be a (sub) directory filesetentry, or + * the root filesetentry in the fileset. It is also placed on the fileset's + * list of all contained leaf directories. Returns FILEBENCH_OK if successful + * or FILEBENCH_ERROR if ipc memory cannot be allocated. + */ +static int +fileset_populate_leafdir(fileset_t *fileset, filesetentry_t *parent, int serial) +{ + char tmpname[16]; + filesetentry_t *entry; + + if ((entry = (filesetentry_t *)ipc_malloc(FILEBENCH_FILESETENTRY)) + == NULL) { + filebench_log(LOG_ERROR, + "fileset_populate_file: Can't malloc filesetentry"); + return (FILEBENCH_ERROR); + } + + /* Another currently idle leaf directory */ + (void) ipc_mutex_lock(&fileset->fs_pick_lock); + fileset->fs_idle_leafdirs++; + (void) ipc_mutex_unlock(&fileset->fs_pick_lock); + + entry->fse_parent = parent; + entry->fse_fileset = fileset; + entry->fse_flags = FSE_TYPE_LEAFDIR | FSE_FREE; + fileset_insleafdirlist(fileset, entry); + + (void) snprintf(tmpname, sizeof (tmpname), "%08d", serial); + if ((entry->fse_path = (char *)ipc_pathalloc(tmpname)) == NULL) { + filebench_log(LOG_ERROR, + "fileset_populate_file: Can't alloc path string"); + return (FILEBENCH_ERROR); + } + + fileset->fs_realleafdirs++; + return (FILEBENCH_OK); +} + +/* * Creates a directory node in a fileset, by obtaining a * filesetentry entity for the node and initializing it * according to parameters of the fileset. It determines a @@ -1052,7 +1284,8 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, } entry->fse_parent = parent; - entry->fse_flags = FSE_DIR | FSE_FREE; + entry->fse_fileset = fileset; + entry->fse_flags = FSE_TYPE_DIR | FSE_FREE; fileset_insdirlist(fileset, entry); if (fileset->fs_dirdepthrv) { @@ -1093,8 +1326,8 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, isleaf = 1; /* - * Create directory of random width according to distribution, or - * if root directory, continue until #files required + * Create directory of random width filled with files according + * to distribution, or if root directory, continue until #files required */ for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && (fileset->fs_realfiles < fileset->fs_constentries); @@ -1109,6 +1342,26 @@ fileset_populate_subdir(fileset_t *fileset, filesetentry_t *parent, if (ret != 0) return (ret); } + + /* + * Create directory of random width filled with leaf directories + * according to distribution, or if root directory, continue until + * the number of leaf directories required has been generated. + */ + for (i = 1; ((parent == NULL) || (i < ranwidth + 1)) && + (fileset->fs_realleafdirs < fileset->fs_constleafdirs); + i++) { + int ret = 0; + + if (parent && isleaf) + ret = fileset_populate_leafdir(fileset, entry, i); + else + ret = fileset_populate_subdir(fileset, entry, i, depth); + + if (ret != 0) + return (ret); + } + return (FILEBENCH_OK); } @@ -1127,6 +1380,7 @@ static int fileset_populate(fileset_t *fileset) { int entries = (int)avd_get_int(fileset->fs_entries); + int leafdirs = (int)avd_get_int(fileset->fs_leafdirs); int meandirwidth; int ret; @@ -1140,19 +1394,26 @@ fileset_populate(fileset_t *fileset) return (FILEBENCH_OK); #endif /* HAVE_RAW_SUPPORT */ - /* save value of entries obtained for later, in case it was random */ + /* + * save value of entries and leaf dirs obtained for later + * in case it was random + */ fileset->fs_constentries = entries; + fileset->fs_constleafdirs = leafdirs; - /* declare all files currently non existant */ + /* declare all files and leafdirs currently non existant */ fileset->fs_num_act_files = 0; + fileset->fs_num_act_leafdirs = 0; /* initialize idle files and directories condition variables */ - (void) pthread_cond_init(&fileset->fs_idle_dirs_cv, ipc_condattr()); (void) pthread_cond_init(&fileset->fs_idle_files_cv, ipc_condattr()); + (void) pthread_cond_init(&fileset->fs_idle_dirs_cv, ipc_condattr()); + (void) pthread_cond_init(&fileset->fs_idle_leafdirs_cv, ipc_condattr()); /* no files or dirs idle (or busy) yet */ fileset->fs_idle_files = 0; fileset->fs_idle_dirs = 0; + fileset->fs_idle_leafdirs = 0; /* initialize locks and other condition variables */ (void) pthread_mutex_init(&fileset->fs_pick_lock, @@ -1177,7 +1438,7 @@ fileset_populate(fileset_t *fileset) * # ave size of file * max size of file */ - fileset->fs_meandepth = log(entries) / log(meandirwidth); + fileset->fs_meandepth = log(entries+leafdirs) / log(meandirwidth); /* Has a random variable been supplied for dirdepth? */ if (fileset->fs_dirdepthrv) { @@ -1202,9 +1463,9 @@ exists: avd_get_str(fileset->fs_name), (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); } else { - filebench_log(LOG_VERBOSE, "Fileset %s: %d files, " + filebench_log(LOG_VERBOSE, "Fileset %s: %d files, %d leafdirs " "avg dir = %d, avg depth = %.1lf, mbytes=%llu", - avd_get_str(fileset->fs_name), entries, + avd_get_str(fileset->fs_name), entries, leafdirs, meandirwidth, fileset->fs_meandepth, (u_longlong_t)(fileset->fs_bytes / 1024UL / 1024UL)); @@ -1456,6 +1717,7 @@ fileset_print(fileset_t *fileset, int first) } return (FILEBENCH_OK); } + /* * checks to see if the path/name pair points to a raw device. If * so it sets the raw device flag (FILESET_IS_RAW_DEV) and returns 1. @@ -1480,9 +1742,9 @@ fileset_checkraw(fileset_t *fileset) if ((setname = avd_get_str(fileset->fs_name)) == NULL) return (FILEBENCH_OK); - (void) strcpy(path, pathname); - (void) strcat(path, "/"); - (void) strcat(path, setname); + (void) fb_strlcpy(path, pathname, MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, setname, MAXPATHLEN); if ((stat64(path, &sb) == 0) && ((sb.st_mode & S_IFMT) == S_IFBLK) && sb.st_rdev) { fileset->fs_attrs |= FILESET_IS_RAW_DEV; diff --git a/usr/src/cmd/filebench/common/fileset.h b/usr/src/cmd/filebench/common/fileset.h index 84ca652c3f..fa08b443c5 100644 --- a/usr/src/cmd/filebench/common/fileset.h +++ b/usr/src/cmd/filebench/common/fileset.h @@ -59,18 +59,22 @@ extern "C" { #define FSE_MAXTID 16384 #define FSE_MAXPATHLEN 16 -#define FSE_DIR 0x01 -#define FSE_FREE 0x02 -#define FSE_EXISTS 0x04 -#define FSE_BUSY 0x08 -#define FSE_THRD_WAITNG 0x10 -#define FSE_REUSING 0x20 +#define FSE_TYPE_FILE 0x00 +#define FSE_TYPE_DIR 0x01 +#define FSE_TYPE_LEAFDIR 0x02 +#define FSE_TYPE_MASK 0x03 +#define FSE_FREE 0x04 +#define FSE_EXISTS 0x08 +#define FSE_BUSY 0x10 +#define FSE_REUSING 0x20 +#define FSE_THRD_WAITNG 0x40 typedef struct filesetentry { struct filesetentry *fse_next; struct filesetentry *fse_parent; struct filesetentry *fse_filenext; /* List of files */ struct filesetentry *fse_dirnext; /* List of directories */ + struct filesetentry *fse_leafdirnext; /* List of leaf dirs */ struct fileset *fse_fileset; /* Parent fileset */ char *fse_path; int fse_depth; @@ -78,10 +82,15 @@ typedef struct filesetentry { int fse_flags; /* protected by fs_pick_lock */ } filesetentry_t; -#define FILESET_PICKANY 0x1 /* Pick any file from the set */ -#define FILESET_PICKUNIQUE 0x2 /* Pick a unique file from set until empty */ -#define FILESET_PICKRESET 0x4 /* Reset FILESET_PICKUNIQUE selection list */ -#define FILESET_PICKDIR 0x8 /* Pick a directory */ +/* type of fileset entry to obtain */ +#define FILESET_PICKFILE 0x00 /* Pick a file from the set */ +#define FILESET_PICKDIR 0x01 /* Pick a directory */ +#define FILESET_PICKLEAFDIR 0x02 /* Pick a leaf directory */ +#define FILESET_PICKMASK 0x03 /* Pick type mask */ +/* other pick flags */ +#define FILESET_PICKUNIQUE 0x04 /* Pick a unique file or leafdir from the */ + /* fileset until empty */ +#define FILESET_PICKRESET 0x08 /* Reset FILESET_PICKUNIQUE selection list */ #define FILESET_PICKEXISTS 0x10 /* Pick an existing file */ #define FILESET_PICKNOEXIST 0x20 /* Pick a file that doesn't exist */ @@ -96,6 +105,10 @@ typedef struct fileset { avd_t fs_entries; /* Number of entries attr */ /* (possibly random) */ fbint_t fs_constentries; /* Constant version of enties attr */ + avd_t fs_leafdirs; /* Number of leaf directories attr */ + /* (possibly random) */ + fbint_t fs_constleafdirs; /* Constant version of leafdirs */ + /* attr */ avd_t fs_preallocpercent; /* Prealloc size */ int fs_attrs; /* Attributes */ avd_t fs_dirwidth; /* Explicit or mean for distribution */ @@ -116,28 +129,37 @@ typedef struct fileset { double fs_meanwidth; /* Specified mean dir width */ double fs_meansize; /* Specified mean file size */ int fs_realfiles; /* Actual files */ + int fs_realleafdirs; /* Actual explicit leaf directories */ off64_t fs_bytes; /* Total space consumed by files */ + + int64_t fs_idle_files; /* number of files NOT busy */ + pthread_cond_t fs_idle_files_cv; /* idle files condition variable */ fbint_t fs_num_act_files; /* total number of files */ /* actually existing in the */ /* host or server's file system */ - fbint_t fs_num_act_dirs; /* total number of directories */ - /* actually existing in the */ - /* host or server's file system */ - int64_t fs_idle_files; /* number of files NOT busy */ - pthread_cond_t fs_idle_files_cv; /* idle files condition variable */ int64_t fs_idle_dirs; /* number of dirs NOT busy */ pthread_cond_t fs_idle_dirs_cv; /* idle dirs condition variable */ + + int64_t fs_idle_leafdirs; /* number of dirs NOT busy */ + pthread_cond_t fs_idle_leafdirs_cv; /* idle dirs condition variable */ + fbint_t fs_num_act_leafdirs; /* total number of leaf dirs */ + /* actually existing in the */ + /* host or server's file system */ pthread_mutex_t fs_pick_lock; /* per fileset "pick" function lock */ pthread_cond_t fs_thrd_wait_cv; /* per fileset file busy wait cv */ filesetentry_t *fs_filelist; /* List of files */ - filesetentry_t *fs_dirlist; /* List of directories */ filesetentry_t *fs_filefree; /* Ptr to next free file */ - filesetentry_t *fs_dirfree; /* Ptr to next free directory */ filesetentry_t *fs_filerotor[FSE_MAXTID]; /* next file to */ /* select */ filesetentry_t *fs_file_ne_rotor; /* next non existent file */ /* to select for createfile */ + filesetentry_t *fs_dirlist; /* List of directories */ + filesetentry_t *fs_dirfree; /* List of free directories */ filesetentry_t *fs_dirrotor; /* Ptr to next directory to select */ + filesetentry_t *fs_leafdirlist; /* List of leaf directories */ + filesetentry_t *fs_leafdirfree; /* Ptr to next free leaf directory */ + filesetentry_t *fs_leafdirrotor; /* Ptr to next leaf */ + /* directory to select */ } fileset_t; int fileset_createset(fileset_t *); diff --git a/usr/src/cmd/filebench/common/flowop_library.c b/usr/src/cmd/filebench/common/flowop_library.c index 9299ca0a6b..7727c169a8 100644 --- a/usr/src/cmd/filebench/common/flowop_library.c +++ b/usr/src/cmd/filebench/common/flowop_library.c @@ -38,6 +38,7 @@ #include <inttypes.h> #include <fcntl.h> #include <math.h> +#include <dirent.h> #ifdef HAVE_UTILITY_H #include <utility.h> @@ -75,7 +76,7 @@ #include "flowop.h" #include "fileset.h" #include "fb_random.h" - +#include "utils.h" /* * These routines implement the flowops from the f language. Each * flowop has has a name such as "read", and a set of function pointers @@ -128,6 +129,9 @@ static int flowoplib_openfile(threadflow_t *, flowop_t *flowop); static int flowoplib_openfile_common(threadflow_t *, flowop_t *flowop, int fd); static int flowoplib_createfile(threadflow_t *, flowop_t *flowop); static int flowoplib_closefile(threadflow_t *, flowop_t *flowop); +static int flowoplib_makedir(threadflow_t *, flowop_t *flowop); +static int flowoplib_removedir(threadflow_t *, flowop_t *flowop); +static int flowoplib_listdir(threadflow_t *, flowop_t *flowop); static int flowoplib_fsync(threadflow_t *, flowop_t *flowop); static int flowoplib_readwholefile(threadflow_t *, flowop_t *flowop); static int flowoplib_writewholefile(threadflow_t *, flowop_t *flowop); @@ -192,6 +196,12 @@ static flowoplib_t flowoplib_funcs[] = { flowoplib_createfile, flowoplib_destruct_generic, FLOW_TYPE_IO, 0, "closefile", flowoplib_init_generic, flowoplib_closefile, flowoplib_destruct_generic, + FLOW_TYPE_IO, 0, "makedir", flowoplib_init_generic, + flowoplib_makedir, flowoplib_destruct_generic, + FLOW_TYPE_IO, 0, "removedir", flowoplib_init_generic, + flowoplib_removedir, flowoplib_destruct_generic, + FLOW_TYPE_IO, 0, "listdir", flowoplib_init_generic, + flowoplib_listdir, flowoplib_destruct_generic, FLOW_TYPE_IO, 0, "fsync", flowoplib_init_generic, flowoplib_fsync, flowoplib_destruct_generic, FLOW_TYPE_IO, 0, "fsyncset", flowoplib_init_generic, @@ -996,7 +1006,7 @@ static int flowoplib_eventlimit(threadflow_t *threadflow, flowop_t *flowop) { /* Immediately bail if not set/enabled */ - if (filebench_shm->shm_eventgen_hz == 0) + if (filebench_shm->shm_eventgen_hz == NULL) return (FILEBENCH_OK); if (flowop->fo_initted == 0) { @@ -1006,7 +1016,7 @@ flowoplib_eventlimit(threadflow_t *threadflow, flowop_t *flowop) } flowop_beginop(threadflow, flowop); - while (filebench_shm->shm_eventgen_hz) { + while (filebench_shm->shm_eventgen_hz != NULL) { (void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock); if (filebench_shm->shm_eventgen_q > 0) { filebench_shm->shm_eventgen_q--; @@ -1059,7 +1069,7 @@ flowoplib_iopslimit(threadflow_t *threadflow, flowop_t *flowop) uint64_t events; /* Immediately bail if not set/enabled */ - if (filebench_shm->shm_eventgen_hz == 0) + if (filebench_shm->shm_eventgen_hz == NULL) return (FILEBENCH_OK); if (flowop->fo_initted == 0) { @@ -1114,7 +1124,7 @@ flowoplib_iopslimit(threadflow_t *threadflow, flowop_t *flowop) events = iops; flowop_beginop(threadflow, flowop); - while (filebench_shm->shm_eventgen_hz) { + while (filebench_shm->shm_eventgen_hz != NULL) { (void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock); if (filebench_shm->shm_eventgen_q >= events) { @@ -1147,7 +1157,7 @@ flowoplib_opslimit(threadflow_t *threadflow, flowop_t *flowop) uint64_t events; /* Immediately bail if not set/enabled */ - if (filebench_shm->shm_eventgen_hz == 0) + if (filebench_shm->shm_eventgen_hz == NULL) return (FILEBENCH_OK); if (flowop->fo_initted == 0) { @@ -1188,7 +1198,7 @@ flowoplib_opslimit(threadflow_t *threadflow, flowop_t *flowop) events = ops; flowop_beginop(threadflow, flowop); - while (filebench_shm->shm_eventgen_hz) { + while (filebench_shm->shm_eventgen_hz != NULL) { (void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock); if (filebench_shm->shm_eventgen_q >= events) { filebench_shm->shm_eventgen_q -= events; @@ -1222,7 +1232,7 @@ flowoplib_bwlimit(threadflow_t *threadflow, flowop_t *flowop) uint64_t events; /* Immediately bail if not set/enabled */ - if (filebench_shm->shm_eventgen_hz == 0) + if (filebench_shm->shm_eventgen_hz == NULL) return (FILEBENCH_OK); if (flowop->fo_initted == 0) { @@ -1281,7 +1291,7 @@ flowoplib_bwlimit(threadflow_t *threadflow, flowop_t *flowop) (u_longlong_t)bytes, (u_longlong_t)events); flowop_beginop(threadflow, flowop); - while (filebench_shm->shm_eventgen_hz) { + while (filebench_shm->shm_eventgen_hz != NULL) { (void) ipc_mutex_lock(&filebench_shm->shm_eventgen_lock); if (filebench_shm->shm_eventgen_q >= events) { filebench_shm->shm_eventgen_q -= events; @@ -1775,10 +1785,10 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd) int open_attrs = 0; char name[MAXPATHLEN]; - (void) strcpy(name, - avd_get_str(flowop->fo_fileset->fs_path)); - (void) strcat(name, "/"); - (void) strcat(name, fileset_name); + (void) fb_strlcpy(name, + avd_get_str(flowop->fo_fileset->fs_path), MAXPATHLEN); + (void) fb_strlcat(name, "/", MAXPATHLEN); + (void) fb_strlcat(name, fileset_name, MAXPATHLEN); if (avd_get_bool(flowop->fo_dsync)) { #ifdef sun @@ -1987,12 +1997,11 @@ flowoplib_deletefile(threadflow_t *threadflow, flowop_t *flowop) (void) ipc_mutex_unlock(&fileset->fs_pick_lock); } - *path = 0; - (void) strcpy(path, avd_get_str(fileset->fs_path)); - (void) strcat(path, "/"); - (void) strcat(path, avd_get_str(fileset->fs_name)); + (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, avd_get_str(fileset->fs_name), MAXPATHLEN); pathtmp = fileset_resolvepath(file); - (void) strcat(path, pathtmp); + (void) fb_strlcat(path, pathtmp, MAXPATHLEN); free(pathtmp); /* delete the selected file */ @@ -2118,6 +2127,200 @@ flowoplib_closefile(threadflow_t *threadflow, flowop_t *flowop) } /* + * Obtain a filesetentry for a leaf directory. Result placed where dirp + * points. Supply with flowop and a flag to indicate whether an existent + * or non-existent leaf directory is required. Returns FILEBENCH_NORSC + * if all out of the appropriate type of directories, FILEBENCH_ERROR + * if the flowop does not point to a fileset, and FILEBENCH_OK otherwise. + */ +static int +flowoplib_pickleafdir(filesetentry_t **dirp, flowop_t *flowop, int flags) +{ + fileset_t *fileset; + + if ((fileset = flowop->fo_fileset) == NULL) { + filebench_log(LOG_ERROR, "flowop NO fileset"); + return (FILEBENCH_ERROR); + } + + if ((*dirp = fileset_pick(fileset, + FILESET_PICKLEAFDIR | flags, 0)) == NULL) { + filebench_log(LOG_DEBUG_SCRIPT, + "flowop %s failed to pick directory from fileset %s", + flowop->fo_name, + avd_get_str(fileset->fs_name)); + return (FILEBENCH_NORSC); + } + + return (FILEBENCH_OK); +} + +/* + * Obtain the full pathname of the directory described by the filesetentry + * indicated by "dir", and copy it into the character array pointed to by + * path. Returns FILEBENCH_ERROR on errors, FILEBENCH_OK otherwise. + */ +static int +flowoplib_getdirpath(filesetentry_t *dir, char *path) +{ + char *fileset_path; + char *fileset_name; + char *part_path; + + if ((fileset_path = avd_get_str(dir->fse_fileset->fs_path)) == NULL) { + filebench_log(LOG_ERROR, "Fileset path not set"); + return (FILEBENCH_ERROR); + } + + if ((fileset_name = avd_get_str(dir->fse_fileset->fs_name)) == NULL) { + filebench_log(LOG_ERROR, "Fileset name not set"); + return (FILEBENCH_ERROR); + } + + (void) fb_strlcpy(path, fileset_path, MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, fileset_name, MAXPATHLEN); + + if ((part_path = fileset_resolvepath(dir)) == NULL) + return (FILEBENCH_ERROR); + + (void) fb_strlcat(path, part_path, MAXPATHLEN); + free(part_path); + + return (FILEBENCH_OK); +} + +/* + * Use mkdir to create a directory. Obtains the fileset name from the + * flowop, selects a non-existent leaf directory and obtains its full + * path, then uses mkdir to create it on the storage subsystem (make it + * existent). Returns FILEBENCH_NORSC is there are no more non-existent + * directories in the fileset, FILEBENCH_ERROR on other errors, and + * FILEBENCH_OK on success. + */ +static int +flowoplib_makedir(threadflow_t *threadflow, flowop_t *flowop) +{ + filesetentry_t *dir; + int ret; + char full_path[MAXPATHLEN]; + + if ((ret = flowoplib_pickleafdir(&dir, flowop, + FILESET_PICKNOEXIST)) != FILEBENCH_OK) + return (ret); + + if ((ret = flowoplib_getdirpath(dir, full_path)) != FILEBENCH_OK) + return (ret); + + flowop_beginop(threadflow, flowop); + (void) mkdir(full_path, 0755); + flowop_endop(threadflow, flowop, 0); + + /* indicate that it is no longer busy and now exists */ + fileset_unbusy(dir, TRUE, TRUE); + + return (FILEBENCH_OK); +} + +/* + * Use rmdir to delete a directory. Obtains the fileset name from the + * flowop, selects an existent leaf directory and obtains its full path, + * then uses rmdir to remove it from the storage subsystem (make it + * non-existent). Returns FILEBENCH_NORSC is there are no more existent + * directories in the fileset, FILEBENCH_ERROR on other errors, and + * FILEBENCH_OK on success. + */ +static int +flowoplib_removedir(threadflow_t *threadflow, flowop_t *flowop) +{ + filesetentry_t *dir; + int ret; + char full_path[MAXPATHLEN]; + + if ((ret = flowoplib_pickleafdir(&dir, flowop, + FILESET_PICKEXISTS)) != FILEBENCH_OK) + return (ret); + + if ((ret = flowoplib_getdirpath(dir, full_path)) != FILEBENCH_OK) + return (ret); + + flowop_beginop(threadflow, flowop); + (void) rmdir(full_path); + flowop_endop(threadflow, flowop, 0); + + /* indicate that it is no longer busy and no longer exists */ + fileset_unbusy(dir, TRUE, FALSE); + + return (FILEBENCH_OK); +} + +/* + * Use opendir(), multiple readdir() calls, and closedir() to list the + * contents of a directory. Obtains the fileset name from the + * flowop, selects a normal subdirectory (which always exist) and obtains + * its full path, then uses opendir() to get a DIR handle to it from the + * file system, a readdir() loop to access each directory entry, and + * finally cleans up with a closedir(). The latency reported is the total + * for all this activity, and it also reports the total number of bytes + * in the entries as the amount "read". Returns FILEBENCH_ERROR on errors, + * and FILEBENCH_OK on success. + */ +static int +flowoplib_listdir(threadflow_t *threadflow, flowop_t *flowop) +{ + fileset_t *fileset; + filesetentry_t *dir; + DIR *dir_handlep; + struct dirent *direntp; + int dir_bytes = 0; + int ret; + char full_path[MAXPATHLEN]; + + if ((fileset = flowop->fo_fileset) == NULL) { + filebench_log(LOG_ERROR, "flowop NO fileset"); + return (FILEBENCH_ERROR); + } + + if ((dir = fileset_pick(fileset, + FILESET_PICKDIR, 0)) == NULL) { + filebench_log(LOG_DEBUG_SCRIPT, + "flowop %s failed to pick directory from fileset %s", + flowop->fo_name, + avd_get_str(fileset->fs_name)); + return (FILEBENCH_NORSC); + } + + if ((ret = flowoplib_getdirpath(dir, full_path)) != FILEBENCH_OK) + return (ret); + + flowop_beginop(threadflow, flowop); + + /* open the directory */ + if ((dir_handlep = opendir(full_path)) == NULL) { + filebench_log(LOG_ERROR, + "flowop %s failed to open directory in fileset %s\n", + flowop->fo_name, avd_get_str(fileset->fs_name)); + return (FILEBENCH_ERROR); + } + + /* read through the directory entries */ + while ((direntp = readdir(dir_handlep)) != NULL) { + dir_bytes += (strlen(direntp->d_name) + + sizeof (struct dirent) - 1); + } + + /* close the directory */ + (void) closedir(dir_handlep); + + flowop_endop(threadflow, flowop, dir_bytes); + + /* indicate that it is no longer busy */ + fileset_unbusy(dir, FALSE, FALSE); + + return (FILEBENCH_OK); +} + +/* * Emulate stat of a file. Picks an arbitrary filesetentry with * an existing file from the flowop's fileset, then performs a * stat() operation on it. Returns FILEBENCH_ERROR if the flowop has no @@ -2151,7 +2354,6 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop) fileset = flowop->fo_fileset; } - if (fileset == NULL) { filebench_log(LOG_ERROR, "statfile with no fileset specified"); @@ -2182,12 +2384,13 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop) } /* resolve path and do a stat on file */ - *path = 0; - (void) strcpy(path, avd_get_str(fileset->fs_path)); - (void) strcat(path, "/"); - (void) strcat(path, avd_get_str(fileset->fs_name)); + (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), + MAXPATHLEN); + (void) fb_strlcat(path, "/", MAXPATHLEN); + (void) fb_strlcat(path, avd_get_str(fileset->fs_name), + MAXPATHLEN); pathtmp = fileset_resolvepath(file); - (void) strcat(path, pathtmp); + (void) fb_strlcat(path, pathtmp, MAXPATHLEN); free(pathtmp); /* stat the file */ diff --git a/usr/src/cmd/filebench/common/ipc.h b/usr/src/cmd/filebench/common/ipc.h index 937171ca10..8416a32ca7 100644 --- a/usr/src/cmd/filebench/common/ipc.h +++ b/usr/src/cmd/filebench/common/ipc.h @@ -146,7 +146,7 @@ typedef struct filebench_shm { /* * Event generator state */ - int shm_eventgen_hz; /* number of events per sec. */ + avd_t shm_eventgen_hz; /* number of events per sec. */ uint64_t shm_eventgen_q; /* count of unclaimed events */ pthread_mutex_t shm_eventgen_lock; /* lock protecting count */ pthread_cond_t shm_eventgen_cv; /* cv to wait on for more events */ diff --git a/usr/src/cmd/filebench/common/parser_gram.y b/usr/src/cmd/filebench/common/parser_gram.y index 7e4510cf9d..d6424d30ff 100644 --- a/usr/src/cmd/filebench/common/parser_gram.y +++ b/usr/src/cmd/filebench/common/parser_gram.y @@ -185,6 +185,7 @@ static void parser_version(cmd_t *cmd); %token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD %token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA FSA_DIRDEPTHRV %token FSA_DIRGAMMA FSA_USEISM FSA_TYPE FSA_RANDTABLE FSA_RANDSRC FSA_RANDROUND +%token FSA_LEAFDIRS %token FSA_RANDSEED FSA_RANDGAMMA FSA_RANDMEAN FSA_RANDMIN FSA_MASTER %token FSA_CLIENT %token FSS_TYPE FSS_SEED FSS_GAMMA FSS_MEAN FSS_MIN FSS_SRC FSS_ROUND @@ -1441,6 +1442,7 @@ attrs_define_fileset: | FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;} | FSA_CACHED { $$ = FSA_CACHED;} | FSA_ENTRIES { $$ = FSA_ENTRIES;}; +| FSA_LEAFDIRS { $$ = FSA_LEAFDIRS;}; randvar_attr_name: FSA_NAME { $$ = FSA_NAME;} @@ -2009,16 +2011,11 @@ static void parser_eventgen(cmd_t *cmd) { attr_t *attr; - fbint_t rate; /* Get the rate from attribute */ if (attr = get_attr_integer(cmd, FSA_RATE)) { if (attr->attr_avd) { - rate = avd_get_int(attr->attr_avd); - filebench_log(LOG_VERBOSE, - "Eventgen: %llu per second", - (u_longlong_t)rate); - eventgen_setrate(rate); + eventgen_setrate(attr->attr_avd); } } } @@ -2727,10 +2724,21 @@ parser_fileset_define(cmd_t *cmd) if (attr = get_attr_integer(cmd, FSA_ENTRIES)) { fileset->fs_entries = attr->attr_avd; } else { - filebench_log(LOG_ERROR, "Fileset has zero entries"); fileset->fs_entries = avd_int_alloc(0); } + /* Get the number of leafdirs in the fileset */ + if (attr = get_attr_integer(cmd, FSA_LEAFDIRS)) { + fileset->fs_leafdirs = attr->attr_avd; + } else { + fileset->fs_leafdirs = avd_int_alloc(0); + } + + if ((avd_get_int(fileset->fs_entries) == 0) && + (avd_get_int(fileset->fs_leafdirs) == 0)) { + filebench_log(LOG_ERROR, "Fileset has no files or leafdirs"); + } + /* Get the mean dir width of the fileset */ if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) { fileset->fs_dirwidth = attr->attr_avd; diff --git a/usr/src/cmd/filebench/common/parser_lex.l b/usr/src/cmd/filebench/common/parser_lex.l index 5485899877..6ac2645e86 100644 --- a/usr/src/cmd/filebench/common/parser_lex.l +++ b/usr/src/cmd/filebench/common/parser_lex.l @@ -126,6 +126,7 @@ name { return FSA_NAME;} namelength { return FSA_NAMELENGTH; } nice { return FSA_NICE;} entries { return FSA_ENTRIES;} +leafdirs { return FSA_LEAFDIRS;} prealloc { return FSA_PREALLOC; } paralloc { return FSA_PARALLOC; } reuse { return FSA_REUSE; } diff --git a/usr/src/cmd/filebench/common/utils.c b/usr/src/cmd/filebench/common/utils.c index 68dc415a2f..a68f72446d 100644 --- a/usr/src/cmd/filebench/common/utils.c +++ b/usr/src/cmd/filebench/common/utils.c @@ -25,8 +25,6 @@ * Portions Copyright 2008 Denis Cheng */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <limits.h> #include <string.h> #include <stdlib.h> @@ -42,9 +40,10 @@ #include "parsertypes.h" /* - * For now, just two routines: one to allocate a string in shared - * memory, and one to get the final file or directory name from a - * supplied pathname. + * For now, just three routines: one to allocate a string in shared + * memory, one to emulate a strlcpy() function and one to emulate a + * strlcat() function, both the second and third only used in non + * Solaris environments, * */ @@ -65,3 +64,65 @@ fb_stralloc(char *str) (void) strcpy(newstr, str); return (newstr); } + +#ifndef sun + +/* + * Implements the strlcpy function when compilied for non Solaris + * operating systems. On solaris the strlcpy() function is used + * directly. + */ +size_t +fb_strlcpy(char *dst, const char *src, size_t dstsize) +{ + uint_t i; + + for (i = 0; i < (dstsize - 1); i++) { + + /* quit if at end of source string */ + if (src[i] == '\0') + break; + + dst[i] = src[i]; + } + + /* set end of dst string to \0 */ + dst[i] = '\0'; + i++; + + return (i); +} + +/* + * Implements the strlcat function when compilied for non Solaris + * operating systems. On solaris the strlcat() function is used + * directly. + */ +size_t +fb_strlcat(char *dst, const char *src, size_t dstsize) +{ + uint_t i, j; + + /* find the end of the current destination string */ + for (i = 0; i < (dstsize - 1); i++) { + if (dst[i] == '\0') + break; + } + + /* append the source string to the destination string */ + for (j = 0; i < (dstsize - 1); i++) { + if (src[j] == '\0') + break; + + dst[i] = src[j]; + j++; + } + + /* set end of dst string to \0 */ + dst[i] = '\0'; + i++; + + return (i); +} + +#endif /* !sun */ diff --git a/usr/src/cmd/filebench/common/utils.h b/usr/src/cmd/filebench/common/utils.h index d2a8b655a3..cb9e39a9fc 100644 --- a/usr/src/cmd/filebench/common/utils.h +++ b/usr/src/cmd/filebench/common/utils.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _FB_UTILS_H #define _FB_UTILS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "config.h" #include <sys/types.h> @@ -41,6 +39,14 @@ extern "C" { extern char *fb_stralloc(char *str); +#ifdef sun +#define fb_strlcat strlcat +#define fb_strlcpy strlcpy +#else +extern size_t fb_strlcat(char *dst, const char *src, size_t dstsize); +extern size_t fb_strlcpy(char *dst, const char *src, size_t dstsize); +#endif /* sun */ + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/filebench/common/vars.h b/usr/src/cmd/filebench/common/vars.h index d3f8185c97..9225d22b9b 100644 --- a/usr/src/cmd/filebench/common/vars.h +++ b/usr/src/cmd/filebench/common/vars.h @@ -76,6 +76,9 @@ typedef struct avd { #define AVD_IS_RANDOM(vp) ((vp) && ((vp)->avd_type == AVD_IND_RANDVAR)) #define AVD_IS_STRING(vp) ((vp) && (((vp)->avd_type == AVD_VAL_STR) || \ ((vp)->avd_type == AVD_VARVAL_STR))) +#define AVD_IS_VAR(vp) ((vp) && (((vp)->avd_type == AVD_IND_VAR) || \ + ((vp)->avd_type == AVD_VARVAL_INT) || \ + ((vp)->avd_type == AVD_VARVAL_DBL))) typedef struct var { char *var_name; diff --git a/usr/src/cmd/filebench/config/Makefile b/usr/src/cmd/filebench/config/Makefile index 5697c531bf..ef6541041e 100644 --- a/usr/src/cmd/filebench/config/Makefile +++ b/usr/src/cmd/filebench/config/Makefile @@ -28,7 +28,7 @@ include ../../Makefile.cmd CONFIGS = fileio.prof filemacro.prof filemicro.prof generic.func \ -seqread.prof randomread.prof multi_fileserver.prof +seqread.prof randomread.prof multi_fileserver.prof videoserver.prof ROOTUSRBENCHDIR = $(ROOT)/usr/benchmarks ROOTUSRBENCHFBCONFIGDIR = $(ROOTUSRBENCHDIR)/filebench/config FBCONFIGS = $(CONFIGS:%=$(ROOTUSRBENCHFBCONFIGDIR)/%) diff --git a/usr/src/cmd/filebench/config/videoserver.prof b/usr/src/cmd/filebench/config/videoserver.prof new file mode 100644 index 0000000000..c749c992ae --- /dev/null +++ b/usr/src/cmd/filebench/config/videoserver.prof @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +DEFAULTS { + runtime = 120; + dir = /export/home/tmp; + stats = /tmp; + filesystem = zfs; + description = "fileserver zfs"; +} + +CONFIG video_server { + function = generic; + personality = videoserver; + filesize = 2g; + numactivevids = 8; + numpassivevids = 40; + nthreads = 16; + srvbwrate = 32; + repintval = 60; +} diff --git a/usr/src/cmd/filebench/workloads/Makefile b/usr/src/cmd/filebench/workloads/Makefile index f7025f58e1..f5dca4ac11 100644 --- a/usr/src/cmd/filebench/workloads/Makefile +++ b/usr/src/cmd/filebench/workloads/Makefile @@ -49,22 +49,27 @@ WORKLOADS = \ filemicro_statfile.f \ filemicro_writefsync.f \ fileserver.f \ + listdirs.f \ + makedirs.f \ mongo.f \ multistreamread.f \ multistreamreaddirect.f \ multistreamwrite.f \ multistreamwritedirect.f \ oltp.f \ + openfiles.f \ randomread.f \ randomrw.f \ randomwrite.f \ ratelimcopyfiles.f \ + removedirs.f \ singlestreamread.f \ singlestreamreaddirect.f \ singlestreamwrite.f \ singlestreamwritedirect.f \ tpcso.f \ varmail.f \ + videoserver.f \ webproxy.f \ webserver.f diff --git a/usr/src/cmd/filebench/workloads/listdirs.f b/usr/src/cmd/filebench/workloads/listdirs.f new file mode 100644 index 0000000000..e3fadc66c3 --- /dev/null +++ b/usr/src/cmd/filebench/workloads/listdirs.f @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Creates a fileset with a fairly deep directory tree, then does readdir +# operations on them for a specified amount of time +# +set $dir=/tmp +set $nfiles=50000 +set $meandirwidth=5 +set $nthreads=16 + +define fileset name=bigfileset,path=$dir,size=0,entries=$nfiles,dirwidth=$meandirwidth,prealloc + +define process name=lsdir,instances=1 +{ + thread name=dirlister,memsize=1m,instances=$nthreads + { + flowop listdir name=open1,filesetname=bigfileset + } +} + +echo "ListDirs Version 1.0 personality successfully loaded" +usage "Usage: set \$dir=<dir> defaults to $dir" +usage " set \$meandirwidth=<size> defaults to $meandirwidth" +usage " set \$nfiles=<value> defaults to $nfiles" +usage " set \$nthreads=<value> defaults to $nthreads" +usage "(sets mean dir width and dir depth is calculated as log (width, nfiles)" +usage " " +usage " run 60" diff --git a/usr/src/cmd/filebench/workloads/makedirs.f b/usr/src/cmd/filebench/workloads/makedirs.f new file mode 100644 index 0000000000..34f2991468 --- /dev/null +++ b/usr/src/cmd/filebench/workloads/makedirs.f @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Creates a directory with $ndirs potential leaf directories, than mkdir's them +# +set $dir=/tmp +set $ndirs=10000 +set $meandirwidth=100 +set $nthreads=16 + +set mode quit firstdone + +define fileset name=bigfileset,path=$dir,size=0,leafdirs=$ndirs,dirwidth=$meandirwidth + +define process name=dirmake,instances=1 +{ + thread name=dirmaker,memsize=1m,instances=$nthreads + { + flowop makedir name=mkdir1,filesetname=bigfileset + } +} + +echo "MakeDirs Version 1.0 personality successfully loaded" +usage "Usage: set \$dir=<dir> defaults to $dir" +usage " set \$meandirwidth=<size> defaults to $meandirwidth" +usage " set \$ndirs=<value> defaults to $ndirs" +usage " set \$nthreads=<value> defaults to $nthreads" +usage "(sets mean dir width and dir depth is calculated as log (width, ndirs)" +usage " " +usage " run" diff --git a/usr/src/cmd/filebench/workloads/openfiles.f b/usr/src/cmd/filebench/workloads/openfiles.f new file mode 100644 index 0000000000..b6eb1be835 --- /dev/null +++ b/usr/src/cmd/filebench/workloads/openfiles.f @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Creates a fileset with $nfiles empty files, then proceeds to open each one +# and then close it. +# +set $dir=/tmp +set $nfiles=50000 +set $meandirwidth=100 +set $nthreads=16 + +define fileset name=bigfileset,path=$dir,size=0,entries=$nfiles,dirwidth=$meandirwidth,prealloc + +define process name=fileopen,instances=1 +{ + thread name=fileopener,memsize=1m,instances=$nthreads + { + flowop openfile name=open1,filesetname=bigfileset,fd=1 + flowop closefile name=close1,fd=1 + } +} + +echo "Openfiles Version 1.0 personality successfully loaded" +usage "Usage: set \$dir=<dir> defaults to $dir" +usage " set \$meandirwidth=<size> defaults to $meandirwidth" +usage " set \$nfiles=<value> defaults to $nfiles" +usage " set \$nthreads=<value> defaults to $nthreads" +usage "(sets mean dir width and dir depth is calculated as log (width, nfiles)" +usage " " +usage " run 60" diff --git a/usr/src/cmd/filebench/workloads/removedirs.f b/usr/src/cmd/filebench/workloads/removedirs.f new file mode 100644 index 0000000000..f64255bc8c --- /dev/null +++ b/usr/src/cmd/filebench/workloads/removedirs.f @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Creates a fileset with $ndirs empty leaf directories then rmdir's all of them +# +set $dir=/tmp +set $ndirs=10000 +set $meandirwidth=100 +set $nthreads=16 + +set mode quit firstdone + +define fileset name=bigfileset,path=$dir,size=0,leafdirs=$ndirs,dirwidth=$meandirwidth,prealloc + +define process name=remdir,instances=1 +{ + thread name=fileopener,memsize=1m,instances=$nthreads + { + flowop removedir name=dirremover,filesetname=bigfileset + } +} + +echo "RemoveDir Version 1.0 personality successfully loaded" +usage "Usage: set \$dir=<dir> defaults to $dir" +usage " set \$meandirwidth=<size> defaults to $meandirwidth" +usage " set \$ndirs=<value> defaults to $ndirs" +usage " set \$nthreads=<value> defaults to $nthreads" +usage "(sets mean dir width and dir depth is calculated as log (width, ndirs)" +usage " " +usage " run" diff --git a/usr/src/cmd/filebench/workloads/videoserver.f b/usr/src/cmd/filebench/workloads/videoserver.f new file mode 100644 index 0000000000..668fd0e81c --- /dev/null +++ b/usr/src/cmd/filebench/workloads/videoserver.f @@ -0,0 +1,82 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# This workloads emulates a video server. It has two filesets, one of videos +# being actively served, and one of videos availabe but currently inactive +# (passive). However, one thread, vidwriter, is writing new videos to replace +# no longer viewed videos in the passive set. Meanwhile $nthreads threads are +# serving up videos from the activevids fileset. If the desired rate is R mb/s, +# and $nthreads is set to T, then set the $srvbwrate to R * T to get the +# desired rate per video stream. The video replacement rate of one video +# file per replacement interval, is set by $repintval which defaults to +# 10 seconds. Thus the write bandwidth will be set as $filesize/$repintval. + +set $dir=/tmp +set $filesize=10g +set $nthreads=48 +set $writeiosize=1m +set $readiosize=256k +set $numactivevids=32 +set $numpassivevids=194 +set $srvbwrate=96 +set $repintval=10 + +eventgen rate=$srvbwrate + +define fileset name=activevids,path=$dir,size=$filesize,entries=$numactivevids,dirwidth=4,prealloc,paralloc,reuse +define fileset name=passivevids,path=$dir,size=$filesize,entries=$numpassivevids,dirwidth=20,prealloc,paralloc,reuse,prealloc=50 + +define process name=vidwriter,instances=1 +{ + thread name=vidwriter,memsize=10m,instances=1 + { + flowop deletefile name=vidremover,filesetname=passivevids + flowop createfile name=wrtopen,filesetname=passivevids,fd=1 + flowop writewholefile name=newvid,iosize=$writeiosize,fd=1,srcfd=1 + flowop closefile name=wrtclose, fd=1 + flowop delay name=replaceinterval, value=$repintval + } +} + +define process name=vidreaders,instances=1 +{ + thread name=vidreaders,memsize=10m,instances=$nthreads + { + flowop read name=vidreader,filesetname=activevids,iosize=$readiosize + flowop bwlimit name=serverlimit, target=vidreader + } +} + +echo "Video Server Version 1.0 personality successfully loaded" +usage "Usage: set \$dir=<dir> defaults to $dir" +usage " set \$filesize=<size> defaults to $filesize" +usage " set \$nthreads=<value> defaults to $nthreads" +usage " set \$writeiosize=<value> defaults to $writeiosize" +usage " set \$readiosize=<value> defaults to $readiosize" +usage " set \$numactivevids=<value> defaults to $numactivevids" +usage " set \$numpassivevids=<value> defaults to $numpassivevids" +usage " set \$srvbwrate=<value> defaults to $srvbwrate" +usage " " +usage " run runtime (e.g. run 60)" + diff --git a/usr/src/pkgdefs/SUNWfilebench/depend b/usr/src/pkgdefs/SUNWfilebench/depend index 759ad37f76..a67e617920 100644 --- a/usr/src/pkgdefs/SUNWfilebench/depend +++ b/usr/src/pkgdefs/SUNWfilebench/depend @@ -20,11 +20,9 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # This package information file defines software dependencies associated # with the pkg. You can define three types of pkg dependencies with this file: # P indicates a prerequisite for installation @@ -49,3 +47,5 @@ P SUNWcsr Core Solaris, (Root) P SUNWcsu Core Solaris, (Usr) P SUNWcsl Core Solaris Libraries P SUNWperl584core Perl 5.8.4 (core) +P SUNWlibmsr +P SUNWtecla Tecla command-line editing library diff --git a/usr/src/pkgdefs/SUNWfilebench/prototype_com b/usr/src/pkgdefs/SUNWfilebench/prototype_com index 5efa232bce..9e421e095e 100644 --- a/usr/src/pkgdefs/SUNWfilebench/prototype_com +++ b/usr/src/pkgdefs/SUNWfilebench/prototype_com @@ -46,6 +46,7 @@ f none usr/benchmarks/filebench/config/generic.func 444 root bin f none usr/benchmarks/filebench/config/multi_fileserver.prof 444 root bin f none usr/benchmarks/filebench/config/seqread.prof 444 root bin f none usr/benchmarks/filebench/config/randomread.prof 444 root bin +f none usr/benchmarks/filebench/config/videoserver.prof 444 root bin d none usr/benchmarks/filebench/scripts 755 root bin f none usr/benchmarks/filebench/scripts/filebench_compare 555 root bin f none usr/benchmarks/filebench/scripts/fs_flush 555 root bin @@ -71,21 +72,26 @@ f none usr/benchmarks/filebench/workloads/filemicro_seqwriterandvartab.f 444 roo f none usr/benchmarks/filebench/workloads/filemicro_statfile.f 444 root bin f none usr/benchmarks/filebench/workloads/filemicro_writefsync.f 444 root bin f none usr/benchmarks/filebench/workloads/fileserver.f 444 root bin +f none usr/benchmarks/filebench/workloads/listdirs.f 444 root bin +f none usr/benchmarks/filebench/workloads/makedirs.f 444 root bin f none usr/benchmarks/filebench/workloads/mongo.f 444 root bin f none usr/benchmarks/filebench/workloads/multistreamread.f 444 root bin f none usr/benchmarks/filebench/workloads/multistreamreaddirect.f 444 root bin f none usr/benchmarks/filebench/workloads/multistreamwrite.f 444 root bin f none usr/benchmarks/filebench/workloads/multistreamwritedirect.f 444 root bin f none usr/benchmarks/filebench/workloads/oltp.f 444 root bin +f none usr/benchmarks/filebench/workloads/openfiles.f 444 root bin f none usr/benchmarks/filebench/workloads/randomread.f 444 root bin f none usr/benchmarks/filebench/workloads/randomrw.f 444 root bin f none usr/benchmarks/filebench/workloads/randomwrite.f 444 root bin f none usr/benchmarks/filebench/workloads/ratelimcopyfiles.f 444 root bin +f none usr/benchmarks/filebench/workloads/removedirs.f 444 root bin f none usr/benchmarks/filebench/workloads/singlestreamread.f 444 root bin f none usr/benchmarks/filebench/workloads/singlestreamreaddirect.f 444 root bin f none usr/benchmarks/filebench/workloads/singlestreamwrite.f 444 root bin f none usr/benchmarks/filebench/workloads/singlestreamwritedirect.f 444 root bin f none usr/benchmarks/filebench/workloads/tpcso.f 444 root bin f none usr/benchmarks/filebench/workloads/varmail.f 444 root bin +f none usr/benchmarks/filebench/workloads/videoserver.f 444 root bin f none usr/benchmarks/filebench/workloads/webproxy.f 444 root bin f none usr/benchmarks/filebench/workloads/webserver.f 444 root bin |