client/server: inflate error handling
authorJeff Furlong <jeff.furlong@wdc.com>
Fri, 8 Feb 2019 23:33:34 +0000 (16:33 -0700)
committerJens Axboe <axboe@kernel.dk>
Fri, 8 Feb 2019 23:33:34 +0000 (16:33 -0700)
Occasionally fio client/server with zlib enabled may report:

fio: inflate error -5
fio: failed decompressing log
fio: failed converting IO log

The error -5 is a Z_BUF_ERROR, and references are available at
https://zlib.net/zlib_how.html and https://www.zlib.net/manual.html  It
seems that when decompressing the buffer, if the buffer chunk is the
same size as remaining data in the buffer, the Z_BUF_ERROR can safely be
ignored.  So one idea is to ignore the safe errors noting the zlib
references:

"inflate() can also return Z_STREAM_ERROR, which should not be possible
here, but could be checked for as noted above for def(). Z_BUF_ERROR
does not need to be checked for here, for the same reasons noted for
def(). Z_STREAM_END will be checked for later.

        ret = inflate(&strm, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
        switch (ret) {
        case Z_NEED_DICT:
            ret = Z_DATA_ERROR;     /* and fall through */
        case Z_DATA_ERROR:
        case Z_MEM_ERROR:
            (void)inflateEnd(&strm);
            return ret;
        }

...

The way we tell that deflate() has no more output is by seeing that it
did not fill the output buffer, leaving avail_out greater than zero.
However suppose that deflate() has no more output, but just so happened
to exactly fill the output buffer! avail_out is zero, and we can't tell
that deflate() has done all it can. As far as we know, deflate() has
more output for us. So we call it again. But now deflate() produces no
output at all, and avail_out remains unchanged as CHUNK. That deflate()
call wasn't able to do anything, either consume input or produce output,
and so it returns Z_BUF_ERROR. (See, I told you I'd cover this later.)
However this is not a problem at all. Now we finally have the desired
indication that deflate() is really done, and so we drop out of the
inner loop to provide more input to deflate()."

Signed-off-by: Jens Axboe <axboe@kernel.dk>
client.c

index 480425f..8d7c033 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1598,6 +1598,11 @@ static struct cmd_iolog_pdu *convert_iolog_gz(struct fio_net_cmd *cmd,
                err = inflate(&stream, Z_NO_FLUSH);
                /* may be Z_OK, or Z_STREAM_END */
                if (err < 0) {
+                       /*
+                        * Z_STREAM_ERROR and Z_BUF_ERROR can safely be
+                        * ignored */
+                       if (err == Z_STREAM_ERROR || err == Z_BUF_ERROR)
+                               break;
                        log_err("fio: inflate error %d\n", err);
                        free(ret);
                        ret = NULL;