diff options
-rw-r--r-- | extras/benchmarking/rdd.c | 176 |
1 files changed, 174 insertions, 2 deletions
diff --git a/extras/benchmarking/rdd.c b/extras/benchmarking/rdd.c index e616022e2d9..b06333370ae 100644 --- a/extras/benchmarking/rdd.c +++ b/extras/benchmarking/rdd.c @@ -36,6 +36,18 @@ #define UNIX_PATH_MAX 108 #endif +#define UNIT_KB 1024ULL +#define UNIT_MB UNIT_KB*1024ULL +#define UNIT_GB UNIT_MB*1024ULL +#define UNIT_TB UNIT_GB*1024ULL +#define UNIT_PB UNIT_TB*1024ULL + +#define UNIT_KB_STRING "KB" +#define UNIT_MB_STRING "MB" +#define UNIT_GB_STRING "GB" +#define UNIT_TB_STRING "TB" +#define UNIT_PB_STRING "PB" + struct rdd_file { char path[UNIX_PATH_MAX]; struct stat st; @@ -53,6 +65,7 @@ struct rdd_config { pthread_mutex_t lock; struct rdd_file in_file; struct rdd_file out_file; + ssize_t file_size; }; static struct rdd_config rdd_config; @@ -91,6 +104,21 @@ rdd_parse_opts (int key, char *arg, } strncpy (rdd_config.in_file.path, arg, len); + rdd_config.in_file.path[len] = '\0'; + } + break; + + case 'f': + { + char *tmp = NULL; + unsigned long long fs = 0; + if (string2bytesize (arg, &fs) == -1) { + fprintf (stderr, "invalid argument for file size " + "(%s)\n", arg); + return -1; + } + + rdd_config.file_size = fs; } break; @@ -189,6 +217,81 @@ rdd_parse_opts (int key, char *arg, return 0; } +int +string2bytesize (const char *str, unsigned long long *n) +{ + unsigned long long value = 0ULL; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtoull (str, &tail, 10); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + if (strcasecmp (tail, UNIT_KB_STRING) == 0) + { + value *= UNIT_KB; + } + else if (strcasecmp (tail, UNIT_MB_STRING) == 0) + { + value *= UNIT_MB; + } + else if (strcasecmp (tail, UNIT_GB_STRING) == 0) + { + value *= UNIT_GB; + } + else if (strcasecmp (tail, UNIT_TB_STRING) == 0) + { + value *= UNIT_TB; + } + else if (strcasecmp (tail, UNIT_PB_STRING) == 0) + { + value *= UNIT_PB; + } + + else + { + return -1; + } + } + + *n = value; + + return 0; +} + static struct argp_option rdd_options[] = { {"if", 'i', "INPUT_FILE", 0, "input-file"}, {"of", 'o', "OUTPUT_FILE", 0, "output-file"}, @@ -201,6 +304,9 @@ static struct argp_option rdd_options[] = { "Number of read-write sequences (defaults to 1000000)"}, {"max-ops", 'm', "MAXOPS", 0, "maximum number of read-writes to be performed in a sequence (defaults to 1)"}, + {"file-size", 'f', "FILESIZE", 0, + "the size of the file which will be created and upon it I/O will be done" + " (defaults to 100MB"}, {0, 0, 0, 0, 0} }; @@ -216,12 +322,16 @@ static struct argp argp = { static void rdd_default_config (void) { + char *tmp_path = "rdd.in"; + rdd_config.thread_count = 2; rdd_config.iters = 1000000; rdd_config.max_bs = 4096; rdd_config.min_bs = 1024; rdd_config.in_file.fd = rdd_config.out_file.fd = -1; rdd_config.max_ops_per_seq = 1; + strncpy (rdd_config.in_file.path, tmp_path, strlen (tmp_path)); + rdd_config.file_size = 104857600; return; } @@ -234,13 +344,17 @@ rdd_valid_config (void) int fd = -1; fd = open (rdd_config.in_file.path, O_RDONLY); - if (fd == -1) { + if (fd == -1 && (errno != ENOENT)) { + fprintf (stderr, "open: (%s)", strerror (errno)); ret = 0; goto out; } close (fd); if (rdd_config.min_bs > rdd_config.max_bs) { + fprintf (stderr, "minimum blocksize %ld is greater than the " + "maximum blocksize %ld", rdd_config.min_bs, + rdd_config.max_bs); ret = 0; goto out; } @@ -356,11 +470,69 @@ cleanup (void) } static int +check_and_create (void) +{ + int ret = -1; + char buf[4096] = {0,}; + struct stat stbuf = {0,}; + int fd[2] = {-1,}; + size_t total_size = -1; + + total_size = rdd_config.file_size; + + ret = stat (rdd_config.in_file.path, &stbuf); + if (ret == -1 && (errno != ENOENT)) + goto out; + + fd[1] = open (rdd_config.in_file.path, O_CREAT | O_WRONLY | O_TRUNC); + if (fd[1] == -1) + goto out; + + fd[0] = open ("/dev/urandom", O_RDONLY); + if (fd[0] == -1) + goto out; + + while (total_size > 0) { + if (total_size >= 4096) { + ret = read (fd[0], buf, 4096); + if (ret == -1) + goto out; + ret = write (fd[1], buf, 4096); + if (ret == -1) + goto out; + total_size = total_size - 4096; + } else { + ret = read (fd[0], buf, total_size); + if (ret == -1) + goto out; + ret = write (fd[1], buf, total_size); + if (ret == -1) + goto out; + total_size = total_size - total_size; + } + + } + + ret = 0; + +out: + if (fd[0] > 0) + close (fd[0]); + if (fd[1] > 0) + close (fd[1]); + return ret; +} + +static int rdd_spawn_threads (void) { int i = 0, ret = -1, fd = -1; char buf[4096]; + ret = check_and_create (); + if (ret == -1) + goto out; + fd = open (rdd_config.in_file.path, O_RDONLY); if (fd < 0) { fprintf (stderr, "cannot open %s (%s)\n", @@ -378,7 +550,7 @@ rdd_spawn_threads (void) } rdd_config.in_file.fd = fd; - fd = open (rdd_config.out_file.path, O_WRONLY | O_CREAT, + fd = open (rdd_config.out_file.path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IROTH); if (fd < 0) { close (rdd_config.in_file.fd); |