From: Jens Axboe <axboe@kernel.dk>
To: Phillip Chen <phillip.a.chen@seagate.com>
Cc: fio@vger.kernel.org
Subject: Re: Random distribution: zoned argument
Date: Wed, 29 Nov 2017 18:37:29 -0700 [thread overview]
Message-ID: <b352de81-8175-87fa-be5e-3c5ceda20b23@kernel.dk> (raw)
In-Reply-To: <ad78196d-0e0b-bbf8-4c9f-02ce877b4051@kernel.dk>
On 11/29/2017 01:58 PM, Jens Axboe wrote:
> I'll take a look at adding absolute zoning, should be pretty
> trivial.
Quick and dirty here, can you see if this works with your magic
script?
Basically you just do:
random_distribution=zoned_abs:60/100m:10/200m:30/700m
like you would for 'zoned' - the first is a percentage, the
other part is a size. So the above would be:
- 60% of accesss to the first 100M
- 10% of access to the next 200M
- 30% of access to the next 700m
No checking for whether or not we exceed device/file size or anything
like that in this version, but everything else should work with the
existing code pretty nicely. Not tested...
diff --git a/fio.h b/fio.h
index 8ca934d14a4c..a44f1aae4721 100644
--- a/fio.h
+++ b/fio.h
@@ -158,6 +158,8 @@ void sk_out_drop(void);
struct zone_split_index {
uint8_t size_perc;
uint8_t size_perc_prev;
+ uint64_t size;
+ uint64_t size_prev;
};
/*
@@ -813,6 +815,7 @@ enum {
FIO_RAND_DIST_PARETO,
FIO_RAND_DIST_GAUSS,
FIO_RAND_DIST_ZONED,
+ FIO_RAND_DIST_ZONED_ABS,
};
#define FIO_DEF_ZIPF 1.1
diff --git a/io_u.c b/io_u.c
index 81ee724b7357..0a4ba435fb65 100644
--- a/io_u.c
+++ b/io_u.c
@@ -157,6 +157,72 @@ static int __get_next_rand_offset_gauss(struct thread_data *td,
return 0;
}
+static int __get_next_rand_offset_zoned_abs(struct thread_data *td,
+ struct fio_file *f,
+ enum fio_ddir ddir, uint64_t *b)
+{
+ struct zone_split_index *zsi;
+ uint64_t offset, lastb;
+ uint64_t send, stotal;
+ static int warned;
+ unsigned int v;
+
+ lastb = last_block(td, f, ddir);
+ if (!lastb)
+ return 1;
+
+ if (!td->o.zone_split_nr[ddir]) {
+bail:
+ return __get_next_rand_offset(td, f, ddir, b, lastb);
+ }
+
+ /*
+ * Generate a value, v, between 1 and 100, both inclusive
+ */
+ v = rand32_between(&td->zone_state, 1, 100);
+
+ zsi = &td->zone_state_index[ddir][v - 1];
+ stotal = zsi->size_prev / td->o.ba[ddir];
+ send = zsi->size / td->o.ba[ddir];
+
+ /*
+ * Should never happen
+ */
+ if (send == -1U) {
+ if (!warned) {
+ log_err("fio: bug in zoned generation\n");
+ warned = 1;
+ }
+ goto bail;
+ }
+
+ /*
+ * 'send' is some percentage below or equal to 100 that
+ * marks the end of the current IO range. 'stotal' marks
+ * the start, in percent.
+ */
+ if (stotal)
+ offset = stotal;
+ else
+ offset = 0;
+
+ lastb = send - stotal;
+
+ /*
+ * Generate index from 0..send-of-lastb
+ */
+ if (__get_next_rand_offset(td, f, ddir, b, lastb) == 1)
+ return 1;
+
+ /*
+ * Add our start offset, if any
+ */
+ if (offset)
+ *b += offset;
+
+ return 0;
+}
+
static int __get_next_rand_offset_zoned(struct thread_data *td,
struct fio_file *f, enum fio_ddir ddir,
uint64_t *b)
@@ -249,6 +315,8 @@ static int get_off_from_method(struct thread_data *td, struct fio_file *f,
return __get_next_rand_offset_gauss(td, f, ddir, b);
else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
return __get_next_rand_offset_zoned(td, f, ddir, b);
+ else if (td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
+ return __get_next_rand_offset_zoned_abs(td, f, ddir, b);
log_err("fio: unknown random distribution: %d\n", td->o.random_distribution);
return 1;
diff --git a/options.c b/options.c
index 4bea8f781304..b49674217e2b 100644
--- a/options.c
+++ b/options.c
@@ -54,16 +54,19 @@ static int bs_cmp(const void *p1, const void *p2)
return (int) bsp1->perc - (int) bsp2->perc;
}
+#define SPLIT_MAX_ENTRY 100
+
struct split {
unsigned int nr;
- unsigned int val1[100];
- unsigned int val2[100];
+ unsigned int val1[SPLIT_MAX_ENTRY];
+ unsigned long long val2[SPLIT_MAX_ENTRY];
};
static int split_parse_ddir(struct thread_options *o, struct split *split,
- enum fio_ddir ddir, char *str)
+ enum fio_ddir ddir, char *str, bool absolute)
{
- unsigned int i, perc;
+ unsigned long long perc;
+ unsigned int i;
long long val;
char *fname;
@@ -80,23 +83,35 @@ static int split_parse_ddir(struct thread_options *o, struct split *split,
if (perc_str) {
*perc_str = '\0';
perc_str++;
- perc = atoi(perc_str);
- if (perc > 100)
- perc = 100;
- else if (!perc)
+ if (absolute) {
+ if (str_to_decimal(perc_str, &val, 1, o, 0, 0)) {
+ log_err("fio: split conversion failed\n");
+ return 1;
+ }
+ perc = val;
+ } else {
+ perc = atoi(perc_str);
+ if (perc > 100)
+ perc = 100;
+ else if (!perc)
+ perc = -1U;
+ }
+ } else {
+ if (absolute)
+ perc = 0;
+ else
perc = -1U;
- } else
- perc = -1U;
+ }
if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
- log_err("fio: bssplit conversion failed\n");
+ log_err("fio: split conversion failed\n");
return 1;
}
split->val1[i] = val;
split->val2[i] = perc;
i++;
- if (i == 100)
+ if (i == SPLIT_MAX_ENTRY)
break;
}
@@ -104,7 +119,8 @@ static int split_parse_ddir(struct thread_options *o, struct split *split,
return 0;
}
-static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
+static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str,
+ bool data)
{
unsigned int i, perc, perc_missing;
unsigned int max_bs, min_bs;
@@ -112,7 +128,7 @@ static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
memset(&split, 0, sizeof(split));
- if (split_parse_ddir(o, &split, ddir, str))
+ if (split_parse_ddir(o, &split, ddir, str, data))
return 1;
if (!split.nr)
return 0;
@@ -176,9 +192,10 @@ static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str)
return 0;
}
-typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *);
+typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *, bool);
-static int str_split_parse(struct thread_data *td, char *str, split_parse_fn *fn)
+static int str_split_parse(struct thread_data *td, char *str,
+ split_parse_fn *fn, bool data)
{
char *odir, *ddir;
int ret = 0;
@@ -187,37 +204,37 @@ static int str_split_parse(struct thread_data *td, char *str, split_parse_fn *fn
if (odir) {
ddir = strchr(odir + 1, ',');
if (ddir) {
- ret = fn(&td->o, DDIR_TRIM, ddir + 1);
+ ret = fn(&td->o, DDIR_TRIM, ddir + 1, data);
if (!ret)
*ddir = '\0';
} else {
char *op;
op = strdup(odir + 1);
- ret = fn(&td->o, DDIR_TRIM, op);
+ ret = fn(&td->o, DDIR_TRIM, op, data);
free(op);
}
if (!ret)
- ret = fn(&td->o, DDIR_WRITE, odir + 1);
+ ret = fn(&td->o, DDIR_WRITE, odir + 1, data);
if (!ret) {
*odir = '\0';
- ret = fn(&td->o, DDIR_READ, str);
+ ret = fn(&td->o, DDIR_READ, str, data);
}
} else {
char *op;
op = strdup(str);
- ret = fn(&td->o, DDIR_WRITE, op);
+ ret = fn(&td->o, DDIR_WRITE, op, data);
free(op);
if (!ret) {
op = strdup(str);
- ret = fn(&td->o, DDIR_TRIM, op);
+ ret = fn(&td->o, DDIR_TRIM, op, data);
free(op);
}
if (!ret)
- ret = fn(&td->o, DDIR_READ, str);
+ ret = fn(&td->o, DDIR_READ, str, data);
}
return ret;
@@ -234,7 +251,7 @@ static int str_bssplit_cb(void *data, const char *input)
strip_blank_front(&str);
strip_blank_end(str);
- ret = str_split_parse(td, str, bssplit_ddir);
+ ret = str_split_parse(td, str, bssplit_ddir, false);
if (parse_dryrun()) {
int i;
@@ -824,14 +841,14 @@ static int str_sfr_cb(void *data, const char *str)
#endif
static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
- char *str)
+ char *str, bool absolute)
{
unsigned int i, perc, perc_missing, sperc, sperc_missing;
struct split split;
memset(&split, 0, sizeof(split));
- if (split_parse_ddir(o, &split, ddir, str))
+ if (split_parse_ddir(o, &split, ddir, str, absolute))
return 1;
if (!split.nr)
return 0;
@@ -840,7 +857,10 @@ static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
o->zone_split_nr[ddir] = split.nr;
for (i = 0; i < split.nr; i++) {
o->zone_split[ddir][i].access_perc = split.val1[i];
- o->zone_split[ddir][i].size_perc = split.val2[i];
+ if (absolute)
+ o->zone_split[ddir][i].size = split.val2[i];
+ else
+ o->zone_split[ddir][i].size_perc = split.val2[i];
}
/*
@@ -856,11 +876,12 @@ static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
else
perc += zsp->access_perc;
- if (zsp->size_perc == (uint8_t) -1U)
- sperc_missing++;
- else
- sperc += zsp->size_perc;
-
+ if (!absolute) {
+ if (zsp->size_perc == (uint8_t) -1U)
+ sperc_missing++;
+ else
+ sperc += zsp->size_perc;
+ }
}
if (perc > 100 || sperc > 100) {
@@ -908,10 +929,11 @@ static int zone_split_ddir(struct thread_options *o, enum fio_ddir ddir,
static void __td_zone_gen_index(struct thread_data *td, enum fio_ddir ddir)
{
unsigned int i, j, sprev, aprev;
+ uint64_t sprev_sz;
td->zone_state_index[ddir] = malloc(sizeof(struct zone_split_index) * 100);
- sprev = aprev = 0;
+ sprev_sz = sprev = aprev = 0;
for (i = 0; i < td->o.zone_split_nr[ddir]; i++) {
struct zone_split *zsp = &td->o.zone_split[ddir][i];
@@ -920,10 +942,14 @@ static void __td_zone_gen_index(struct thread_data *td, enum fio_ddir ddir)
zsi->size_perc = sprev + zsp->size_perc;
zsi->size_perc_prev = sprev;
+
+ zsi->size = sprev_sz + zsp->size;
+ zsi->size_prev = sprev_sz;
}
aprev += zsp->access_perc;
sprev += zsp->size_perc;
+ sprev_sz += zsp->size;
}
}
@@ -942,8 +968,10 @@ static void td_zone_gen_index(struct thread_data *td)
__td_zone_gen_index(td, i);
}
-static int parse_zoned_distribution(struct thread_data *td, const char *input)
+static int parse_zoned_distribution(struct thread_data *td, const char *input,
+ bool absolute)
{
+ const char *pre = absolute ? "zoned_abs:" : "zoned:";
char *str, *p;
int i, ret = 0;
@@ -953,14 +981,14 @@ static int parse_zoned_distribution(struct thread_data *td, const char *input)
strip_blank_end(str);
/* We expect it to start like that, bail if not */
- if (strncmp(str, "zoned:", 6)) {
+ if (strncmp(str, pre, strlen(pre))) {
log_err("fio: mismatch in zoned input <%s>\n", str);
free(p);
return 1;
}
- str += strlen("zoned:");
+ str += strlen(pre);
- ret = str_split_parse(td, str, zone_split_ddir);
+ ret = str_split_parse(td, str, zone_split_ddir, absolute);
free(p);
@@ -972,8 +1000,15 @@ static int parse_zoned_distribution(struct thread_data *td, const char *input)
for (j = 0; j < td->o.zone_split_nr[i]; j++) {
struct zone_split *zsp = &td->o.zone_split[i][j];
- dprint(FD_PARSE, "\t%d: %u/%u\n", j, zsp->access_perc,
- zsp->size_perc);
+ if (absolute) {
+ dprint(FD_PARSE, "\t%d: %u/%llu\n", j,
+ zsp->access_perc,
+ (unsigned long long) zsp->size);
+ } else {
+ dprint(FD_PARSE, "\t%d: %u/%u\n", j,
+ zsp->access_perc,
+ zsp->size_perc);
+ }
}
}
@@ -1012,7 +1047,9 @@ static int str_random_distribution_cb(void *data, const char *str)
else if (td->o.random_distribution == FIO_RAND_DIST_GAUSS)
val = 0.0;
else if (td->o.random_distribution == FIO_RAND_DIST_ZONED)
- return parse_zoned_distribution(td, str);
+ return parse_zoned_distribution(td, str, false);
+ else if (td->o.random_distribution == FIO_RAND_DIST_ZONED_ABS)
+ return parse_zoned_distribution(td, str, true);
else
return 0;
@@ -2241,7 +2278,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.oval = FIO_RAND_DIST_ZONED,
.help = "Zoned random distribution",
},
-
+ { .ival = "zoned_abs",
+ .oval = FIO_RAND_DIST_ZONED_ABS,
+ .help = "Zoned random absolute distribution",
+ },
},
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
diff --git a/server.h b/server.h
index ba3abfeb3228..dbd5c277de6b 100644
--- a/server.h
+++ b/server.h
@@ -49,7 +49,7 @@ struct fio_net_cmd_reply {
};
enum {
- FIO_SERVER_VER = 66,
+ FIO_SERVER_VER = 67,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
diff --git a/thread_options.h b/thread_options.h
index ca549b542703..050cd3822914 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -36,6 +36,8 @@ struct bssplit {
struct zone_split {
uint8_t access_perc;
uint8_t size_perc;
+ uint8_t pad[6];
+ uint64_t size;
};
#define NR_OPTS_SZ (FIO_MAX_OPTS / (8 * sizeof(uint64_t)))
--
Jens Axboe
next prev parent reply other threads:[~2017-11-30 1:37 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-20 17:17 Random distribution: zoned argument Phillip Chen
2017-11-21 1:57 ` Jens Axboe
2017-11-27 23:18 ` Phillip Chen
2017-11-29 19:33 ` Jens Axboe
2017-11-29 19:37 ` Jens Axboe
2017-11-29 20:39 ` Phillip Chen
2017-11-29 20:58 ` Jens Axboe
2017-11-30 1:37 ` Jens Axboe [this message]
2017-11-30 2:16 ` Jens Axboe
2017-11-30 2:30 ` Jens Axboe
2017-11-30 21:19 ` Phillip Chen
2017-11-30 21:22 ` Jens Axboe
2017-11-30 23:41 ` Phillip Chen
2017-11-30 23:47 ` Jens Axboe
2017-11-30 23:48 ` Jens Axboe
2017-12-01 0:04 ` Phillip Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b352de81-8175-87fa-be5e-3c5ceda20b23@kernel.dk \
--to=axboe@kernel.dk \
--cc=fio@vger.kernel.org \
--cc=phillip.a.chen@seagate.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox