From: Jeff Furlong Date: Fri, 8 Feb 2019 23:33:34 +0000 (-0700) Subject: client/server: inflate error handling X-Git-Tag: fio-3.14~43 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=2f75f022393e432210d01b15088f425ee5260340;hp=370f38977a241e173b0c60b66252757be809ad3a client/server: inflate error handling 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 --- diff --git a/client.c b/client.c index 480425f6..8d7c0331 100644 --- 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;