log: make the logging functions handle > 1024 bytes correctly
authorJens Axboe <axboe@fb.com>
Wed, 24 May 2017 03:45:31 +0000 (21:45 -0600)
committerJens Axboe <axboe@fb.com>
Wed, 24 May 2017 03:45:31 +0000 (21:45 -0600)
We simply truncate the output if it's larger than our static
buffer. Make it dynamically allocated instead, and ensure that
we loop correctly to handle the full amount asked for.

This fixes a problem with truncated output. One example is
json output, with file names (for multiple files) that are
larger than 1024 bytes. With the truncated output, we would
truncate the file name and hence also miss the terminating
'"'. The latter means the json was no longer valid, either.

Signed-off-by: Jens Axboe <axboe@fb.com>
log.c

diff --git a/log.c b/log.c
index 172f153..f34892d 100644 (file)
--- a/log.c
+++ b/log.c
@@ -6,6 +6,8 @@
 
 #include "fio.h"
 
+#define LOG_START_SZ           512
+
 size_t log_info_buf(const char *buf, size_t len)
 {
        /*
@@ -29,38 +31,76 @@ size_t log_info_buf(const char *buf, size_t len)
 
 size_t log_valist(const char *str, va_list args)
 {
-       char buffer[1024];
-       size_t len;
+       size_t len, cur = LOG_START_SZ;
+       char *buffer;
+
+       do {
+               buffer = calloc(1, cur);
+
+               len = vsnprintf(buffer, cur, str, args);
+               if (len <= cur)
+                       break;
 
-       len = vsnprintf(buffer, sizeof(buffer), str, args);
+               cur = len;
+               free(buffer);
+       } while (1);
 
-       return log_info_buf(buffer, min(len, sizeof(buffer) - 1));
+       cur = log_info_buf(buffer, len);
+       free(buffer);
+
+       return cur;
 }
 
 size_t log_info(const char *format, ...)
 {
-       char buffer[1024];
+       size_t len, cur = LOG_START_SZ;
+       char *buffer;
        va_list args;
-       size_t len;
 
-       va_start(args, format);
-       len = vsnprintf(buffer, sizeof(buffer), format, args);
-       va_end(args);
+       do {
+               buffer = calloc(1, cur);
+
+               va_start(args, format);
+               len = vsnprintf(buffer, cur, format, args);
+               va_end(args);
 
-       return log_info_buf(buffer, min(len, sizeof(buffer) - 1));
+               if (len <= cur)
+                       break;
+
+               cur = len;
+               free(buffer);
+       } while (1);
+
+       cur = log_info_buf(buffer, len);
+       free(buffer);
+
+       return cur;
 }
 
 size_t __log_buf(struct buf_output *buf, const char *format, ...)
 {
-       char buffer[1024];
+       size_t len, cur = LOG_START_SZ;
+       char *buffer;
        va_list args;
-       size_t len;
 
-       va_start(args, format);
-       len = vsnprintf(buffer, sizeof(buffer), format, args);
-       va_end(args);
+       do {
+               buffer = calloc(1, cur);
+
+               va_start(args, format);
+               len = vsnprintf(buffer, cur, format, args);
+               va_end(args);
+
+               if (len <= cur)
+                       break;
 
-       return buf_output_add(buf, buffer, min(len, sizeof(buffer) - 1));
+               cur = len;
+               free(buffer);
+       } while (1);
+
+       cur = buf_output_add(buf, buffer, len);
+       free(buffer);
+
+       return cur;
 }
 
 int log_info_flush(void)
@@ -73,33 +113,44 @@ int log_info_flush(void)
 
 size_t log_err(const char *format, ...)
 {
-       char buffer[1024];
+       size_t ret, len, cur = LOG_START_SZ;
+       char *buffer;
        va_list args;
-       size_t len;
 
-       va_start(args, format);
-       len = vsnprintf(buffer, sizeof(buffer), format, args);
-       va_end(args);
-       len = min(len, sizeof(buffer) - 1);
+       do {
+               buffer = calloc(1, cur);
+
+               va_start(args, format);
+               len = vsnprintf(buffer, cur, format, args);
+               va_end(args);
+
+               if (len <= cur)
+                       break;
+
+               cur = len;
+               free(buffer);
+       } while (1);
+
 
        if (is_backend) {
-               size_t ret = fio_server_text_output(FIO_LOG_ERR, buffer, len);
+               ret = fio_server_text_output(FIO_LOG_ERR, buffer, len);
                if (ret != -1)
-                       return ret;
+                       goto done;
        }
 
        if (log_syslog) {
                syslog(LOG_INFO, "%s", buffer);
-               return len;
+               ret = len;
        } else {
-               if (f_err != stderr) {
-                       int fio_unused ret;
-
+               if (f_err != stderr)
                        ret = fwrite(buffer, len, 1, stderr);
-               }
 
-               return fwrite(buffer, len, 1, f_err);
+               ret = fwrite(buffer, len, 1, f_err);
        }
+
+done:
+       free(buffer);
+       return ret;
 }
 
 const char *log_get_level(int level)