Skip to content

parse.c incorrectly handling large FIO_OPT_INT values #975

Open
@sbates130272

Description

@sbates130272

We are working on a pretty high performance system and are using the --rate option to try and constrain throughputs to 8GB/s. However we noticed that since FIO_OPT_INT is constrained to 32 bits any values over 4GB should result in an error that is detected in val_too_large().

However the code in val_too_large is failing to do this because of this line:

return (unsigned int) val > o->maxval;

which is our case tests equates to

(unsigned int) 8G > 4G
0 > 4G
= false

You can check this for yourself with something like:

./fio --debug=parse --name=parse_check --rate=8G,8G --size=16k --filename /tmp/parse.dat

Which (with a simple patch) generates:

parse    1698  dup options
parse    1698  handle_option=name, ptr=parse
parse    1698  __handle_option=name, type=OPT_STR_STORE, ptr=parse
parse    1698  handle_option=rate, ptr=8G,8G
parse    1698  __handle_option=rate, type=OPT_INT, ptr=8G,8G
parse    1698    ret=0, out=8589934592, max=4294967295
parse    1698      is_uint=1, val=8589934592, o->maxval=4294967295, (unsigned int) val=0
parse    1698  __handle_option=rate, type=OPT_INT, ptr=8G
parse    1698    ret=0, out=8589934592, max=4294967295
parse    1698      is_uint=1, val=8589934592, o->maxval=4294967295, (unsigned int) val=0
parse    1698  handle_option=size, ptr=16k
parse    1698  __handle_option=size, type=OPT_STR_VAL, ptr=16k
parse    1698    ret=0, out=16384, max=0
parse    1698  handle_option=filename, ptr=/tmp/parse.dat
parse    1698  __handle_option=filename, type=OPT_STR_STORE, ptr=/tmp/parse.dat
parse: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
parse    1698  free options
fio-3.19-52-gb2ed-dirty
Starting 1 process

Here is the patch:

diff --git a/parse.c b/parse.c
index 04b2e198..711a2ec1 100644
--- a/parse.c
+++ b/parse.c
@@ -516,6 +516,9 @@ static bool val_too_large(const struct fio_option *o, unsigned long long val,
        if (!o->maxval)
                return false;
 
+        dprint(FD_PARSE, "    is_uint=%d, val=%llu, o->maxval=%llu, (unsigned int) val=%d\n",
+               is_uint, val, o->maxval, (unsigned int) val);
+
        if (is_uint) {
                if ((int) val < 0)
                        return (int) val > (int) o->maxval;
@@ -616,7 +619,7 @@ static int __handle_option(const struct fio_option *o, const char *ptr,
                else
                        ret = check_str_bytes(tmp, &ull, data);
 
-               dprint(FD_PARSE, "  ret=%d, out=%llu\n", ret, ull);
+               dprint(FD_PARSE, "  ret=%d, out=%llu, max=%llu\n", ret, ull, o->maxval);
 
                if (ret)
                        break;

Metadata

Metadata

Assignees

No one assigned

    Labels

    patcheswelcomeNo one internal is working on this but an external contributor's help is very welcome!triagedIssue cause is understood but a patch is needed to fix it

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions