From patchwork Sat Mar 30 15:07:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 10878537 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 73F4F14DE for ; Sat, 30 Mar 2019 15:10:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5A27D2880F for ; Sat, 30 Mar 2019 15:10:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4811A28807; Sat, 30 Mar 2019 15:10:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CAFE028807 for ; Sat, 30 Mar 2019 15:10:20 +0000 (UTC) Received: from localhost ([127.0.0.1]:60051 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hAFci-00034I-6X for patchwork-qemu-devel@patchwork.kernel.org; Sat, 30 Mar 2019 11:10:20 -0400 Received: from eggs.gnu.org ([209.51.188.92]:51333) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hAFbB-0002EX-9U for qemu-devel@nongnu.org; Sat, 30 Mar 2019 11:08:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hAFb2-0003c2-RM for qemu-devel@nongnu.org; Sat, 30 Mar 2019 11:08:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46048) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hAFaU-0003DQ-3b; Sat, 30 Mar 2019 11:08:06 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9E2573086209; Sat, 30 Mar 2019 15:07:07 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-75.phx2.redhat.com [10.3.116.75]) by smtp.corp.redhat.com (Postfix) with ESMTP id ADB964D6F7; Sat, 30 Mar 2019 15:07:04 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Sat, 30 Mar 2019 10:07:02 -0500 Message-Id: <20190330150702.11687-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Sat, 30 Mar 2019 15:07:07 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH] qemu-img: Saner printing of large file sizes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Markus Armbruster , Max Reitz , jsnow@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Disk sizes close to INT64_MAX cause overflow, for some pretty ridiculous output: $ ./nbdkit -U - memory size=$((2**63 - 512)) --run 'qemu-img info $nbd' image: nbd+unix://?socket=/tmp/nbdkitHSAzNz/socket file format: raw virtual size: -8388607T (9223372036854775296 bytes) disk size: unavailable But there's no reason to have two separate implementations of integer to human-readable abbreviation, where one has overflow and stops at 'T', while the other avoids overflow and goes all the way to 'E'. With this patch, the output now claims 8EiB instead of -8388607T, which really is the correct rounding of largest file size supported by qemu (we could go 511 bytes larger if we used byte-accurate sizing instead of rounding up to the next sector boundary, but that wouldn't change the human-readable result). Reported-by: Richard W.M. Jones Signed-off-by: Eric Blake Tested-by: Richard W.M. Jones Reviewed-by: Alberto Garcia Reviewed-by: Vladimir Sementsov-Ogievskiy --- block/qapi.c | 49 +++++++++++-------------------------------------- 1 file changed, 11 insertions(+), 38 deletions(-) diff --git a/block/qapi.c b/block/qapi.c index 21edab34fca..110d05dc575 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -630,43 +630,14 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, return head; } -#define NB_SUFFIXES 4 - -static char *get_human_readable_size(char *buf, int buf_size, int64_t size) -{ - static const char suffixes[NB_SUFFIXES] = {'K', 'M', 'G', 'T'}; - int64_t base; - int i; - - if (size <= 999) { - snprintf(buf, buf_size, "%" PRId64, size); - } else { - base = 1024; - for (i = 0; i < NB_SUFFIXES; i++) { - if (size < (10 * base)) { - snprintf(buf, buf_size, "%0.1f%c", - (double)size / base, - suffixes[i]); - break; - } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { - snprintf(buf, buf_size, "%" PRId64 "%c", - ((size + (base >> 1)) / base), - suffixes[i]); - break; - } - base = base * 1024; - } - } - return buf; -} - void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, QEMUSnapshotInfo *sn) { - char buf1[128], date_buf[128], clock_buf[128]; + char date_buf[128], clock_buf[128]; struct tm tm; time_t ti; int64_t secs; + char *sizing = NULL; if (!sn) { func_fprintf(f, @@ -684,14 +655,15 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, (int)((secs / 60) % 60), (int)(secs % 60), (int)((sn->vm_clock_nsec / 1000000) % 1000)); + sizing = size_to_str(sn->vm_state_size); func_fprintf(f, "%-10s%-20s%7s%20s%15s", sn->id_str, sn->name, - get_human_readable_size(buf1, sizeof(buf1), - sn->vm_state_size), + sizing, date_buf, clock_buf); } + g_free(sizing); } static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation, @@ -796,14 +768,13 @@ void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, ImageInfo *info) { - char size_buf[128], dsize_buf[128]; + char *size_buf, *dsize_buf; if (!info->has_actual_size) { - snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); + dsize_buf = g_strdup("unavailable"); } else { - get_human_readable_size(dsize_buf, sizeof(dsize_buf), - info->actual_size); + dsize_buf = size_to_str(info->actual_size); } - get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); + size_buf = size_to_str(info->virtual_size); func_fprintf(f, "image: %s\n" "file format: %s\n" @@ -812,6 +783,8 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, info->filename, info->format, size_buf, info->virtual_size, dsize_buf); + g_free(size_buf); + g_free(dsize_buf); if (info->has_encrypted && info->encrypted) { func_fprintf(f, "encrypted: yes\n");