summaryrefslogtreecommitdiff
path: root/usr/src/cmd/filebench/common/flowop_library.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/filebench/common/flowop_library.c')
-rw-r--r--usr/src/cmd/filebench/common/flowop_library.c251
1 files changed, 227 insertions, 24 deletions
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 */