Allow percentage setting for size=
authorJens Axboe <jaxboe@fusionio.com>
Tue, 12 Jul 2011 17:47:03 +0000 (19:47 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Tue, 12 Jul 2011 17:47:03 +0000 (19:47 +0200)
Sometimes it's useful to set this to a particular size of a device.
Allowing percentages makes this more easy, as one does not have to
do the math outside of fio and pass in as environment variables
or custom job files.

To use, simply add a

size=15%

or whatever is needed, then fio will use 15% of the total size of
the device(s) or file(s) given. Percentage can be from 1 to 100.

Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
HOWTO
filesetup.c
fio.1
fio.h
options.c
parse.c
parse.h

diff --git a/HOWTO b/HOWTO
index ee899b8fdb6c402814086dde41f986d152c456c9..ce1bd9e6131db987ea6c8992c5deeebd9bddc3bf 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -382,7 +382,10 @@ size=int   The total size of file io for this job. Fio will run until
                fio will divide this size between the available files
                specified by the job. If not set, fio will use the full
                size of the given files or devices. If the the files
-               do not exist, size must be given.
+               do not exist, size must be given. It is also possible to
+               give size as a percentage between 1 and 100. If size=20%
+               is given, fio will use 20% of the full size of the given
+               files or devices.
 
 filesize=int   Individual file sizes. May be a range, in which case fio
                will select sizes for files at random within the given range
index 2a79e7452d083f36b9cb0e4777ea8bfe94de01d5..8f515923bcf9b25c725c9d9a3e94ed2ecb1711a3 100644 (file)
@@ -759,6 +759,9 @@ int setup_files(struct thread_data *td)
                }
        }
 
+       if (td->o.size_percent)
+               total_size = (total_size * td->o.size_percent) / 100;
+
        if (!td->o.size || td->o.size > total_size)
                td->o.size = total_size;
 
diff --git a/fio.1 b/fio.1
index 0838d07bff465008f62862c555d2f61821a35ceb..b7046d5adf6428f16dc79fdb38650a7bba89f2cc 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -257,7 +257,9 @@ been transfered, unless limited by other options (\fBruntime\fR, for instance).
 Unless \fBnrfiles\fR and \fBfilesize\fR options are given, this amount will be
 divided between the available files for the job. If not set, fio will use the
 full size of the given files or devices. If the the files do not exist, size
-must be given.
+must be given. It is also possible to give size as a percentage between 1 and
+100. If size=20% is given, fio will use 20% of the full size of the given files
+or devices.
 .TP
 .BI fill_device \fR=\fPbool "\fR,\fB fill_fs" \fR=\fPbool
 Sets size to something really large and waits for ENOSPC (no space left on
diff --git a/fio.h b/fio.h
index b869dd15e280201aa79bd63dcdd39dfc6089dc8f..d8e3011bb4f19a17eb3b542d16af0a693e995ee9 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -165,6 +165,7 @@ struct thread_options {
        unsigned int iodepth_batch_complete;
 
        unsigned long long size;
+       unsigned int size_percent;
        unsigned int fill_device;
        unsigned long long file_size_low;
        unsigned long long file_size_high;
index b4456a42bca3b53c9fe41896bd8ac65990ca060e..74c64780a92658695217ee46859d631eb0008b14 100644 (file)
--- a/options.c
+++ b/options.c
@@ -744,6 +744,20 @@ static int str_gtod_cpu_cb(void *data, long long *il)
        return 0;
 }
 
+static int str_size_cb(void *data, unsigned long long *__val)
+{
+       struct thread_data *td = data;
+       unsigned long long v = *__val;
+
+       if (parse_is_percent(v)) {
+               td->o.size = 0;
+               td->o.size_percent = -1ULL - v;
+       } else
+               td->o.size = v;
+
+       return 0;
+}
+
 static int rw_verify(struct fio_option *o, void *data)
 {
        struct thread_data *td = data;
@@ -1031,8 +1045,7 @@ static struct fio_option options[FIO_MAX_OPTS] = {
        {
                .name   = "size",
                .type   = FIO_OPT_STR_VAL,
-               .off1   = td_var_offset(size),
-               .minval = 1,
+               .cb     = str_size_cb,
                .help   = "Total size of device or files",
        },
        {
diff --git a/parse.c b/parse.c
index 97ea4aab47961115a97a16cbbe6b0034e429027d..ef23fbe90ed6b3ce8b4309bfe8751b56c23ae9aa 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -118,7 +118,8 @@ static unsigned long get_mult_time(char c)
        }
 }
 
-static unsigned long long __get_mult_bytes(const char *p, void *data)
+static unsigned long long __get_mult_bytes(const char *p, void *data,
+                                          int *percent)
 {
        unsigned int kb_base = fio_get_kb_base(data);
        unsigned long long ret = 1;
@@ -158,6 +159,10 @@ static unsigned long long __get_mult_bytes(const char *p, void *data)
                pow = 2;
        else if (!strcmp("k", c) || !strcmp("kb", c))
                pow = 1;
+       else if (!strcmp("%", c)) {
+               *percent = 1;
+               return ret;
+       }
 
        while (pow--)
                ret *= (unsigned long long) mult;
@@ -166,12 +171,13 @@ static unsigned long long __get_mult_bytes(const char *p, void *data)
        return ret;
 }
 
-static unsigned long long get_mult_bytes(const char *str, int len, void *data)
+static unsigned long long get_mult_bytes(const char *str, int len, void *data,
+                                        int *percent)
 {
        const char *p = str;
 
        if (len < 2)
-               return __get_mult_bytes(str, data);
+               return __get_mult_bytes(str, data, percent);
 
         /*
          * Go forward until we hit a non-digit
@@ -182,10 +188,10 @@ static unsigned long long get_mult_bytes(const char *str, int len, void *data)
                p++;
        }
 
-       if (!isalpha((int) *p))
+       if (!isalpha((int) *p) && (*p != '%'))
                p = NULL;
 
-       return __get_mult_bytes(p, data);
+       return __get_mult_bytes(p, data, percent);
 }
 
 /*
@@ -208,9 +214,16 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data)
        if (*val == LONG_MAX && errno == ERANGE)
                return 1;
 
-       if (kilo)
-               *val *= get_mult_bytes(str, len, data);
-       else
+       if (kilo) {
+               unsigned long long mult;
+               int perc = 0;
+
+               mult = get_mult_bytes(str, len, data, &perc);
+               if (perc)
+                       *val = -1ULL - *val;
+               else
+                       *val *= mult;
+       } else
                *val *= get_mult_time(str[len - 1]);
 
        return 0;
diff --git a/parse.h b/parse.h
index 41e3633c24edb162ba629a8766389a91984db414..2dd8459f646304303dd571fbb638e331451756ef 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -89,4 +89,9 @@ typedef int (fio_opt_str_set_fn)(void *);
 #define max(a, b)      ((a) > (b) ? (a) : (b))
 #endif
 
+static inline int parse_is_percent(unsigned long long val)
+{
+       return val <= -1ULL && val >= (-1ULL - 100ULL);
+}
+
 #endif