From 06bda502e32bb8609778d37cff7cf3798c4b6e4a Mon Sep 17 00:00:00 2001 From: Jeffrey Cody Date: Wed, 21 Mar 2012 21:55:16 +0100 Subject: [PATCH 49/55] cutils: extract buffer_is_zero() from qemu-img.c RH-Author: Jeffrey Cody Message-id: <0e11ac627330c388073969f5138db60725df8bea.1332362400.git.jcody@redhat.com> Patchwork-id: 38899 O-Subject: [RHEL6.3 qemu-kvm PATCH v8 49/54] cutils: extract buffer_is_zero() from qemu-img.c Bugzilla: 582475 RH-Acked-by: Paolo Bonzini RH-Acked-by: Marcelo Tosatti RH-Acked-by: Kevin Wolf From: Stefan Hajnoczi The qemu-img.c:is_not_zero() function checks if a buffer contains all zeroes. This function will come in handy for zero-detection in the block layer, so clean it up and move it to cutils.c. Note that the function now returns true if the buffer is all zeroes. This avoids the double-negatives (i.e. !is_not_zero()) that the old function can cause in callers. Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf (cherry picked from commit 1a6d39fd71ddf90c5b76026cac4d5ff51fbaf8d8) Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori Signed-off-by: Jeff Cody --- cutils.c | 35 +++++++++++++++++++++++++++++++++++ qemu-common.h | 2 ++ qemu-img.c | 23 +++++++---------------- 3 files changed, 44 insertions(+), 16 deletions(-) Signed-off-by: Michal Novotny --- cutils.c | 35 +++++++++++++++++++++++++++++++++++ qemu-common.h | 2 ++ qemu-img.c | 23 +++++++---------------- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/cutils.c b/cutils.c index 0edbbfd..b7b13f1 100644 --- a/cutils.c +++ b/cutils.c @@ -307,6 +307,41 @@ void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, } /* + * Checks if a buffer is all zeroes + * + * Attention! The len must be a multiple of 4 * sizeof(long) due to + * restriction of optimizations in this function. + */ +bool buffer_is_zero(const void *buf, size_t len) +{ + /* + * Use long as the biggest available internal data type that fits into the + * CPU register and unroll the loop to smooth out the effect of memory + * latency. + */ + + size_t i; + long d0, d1, d2, d3; + const long * const data = buf; + + assert(len % (4 * sizeof(long)) == 0); + len /= sizeof(long); + + for (i = 0; i < len; i += 4) { + d0 = data[i + 0]; + d1 = data[i + 1]; + d2 = data[i + 2]; + d3 = data[i + 3]; + + if (d0 || d1 || d2 || d3) { + return false; + } + } + + return true; +} + +/* * Convert string to bytes, allowing either B/b for bytes, K/k for KB, * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned * in *end, if not NULL. A valid value must be terminated by diff --git a/qemu-common.h b/qemu-common.h index 9b01f50..9f0c52c 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -283,6 +283,8 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count); void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, size_t skip); +bool buffer_is_zero(const void *buf, size_t len); + void qemu_progress_init(int enabled, float min_skip); void qemu_progress_end(void); void qemu_progress_print(float delta, int max); diff --git a/qemu-img.c b/qemu-img.c index c5de0a1..f4f7020 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -537,17 +537,6 @@ static int img_commit(int argc, char **argv) return 0; } -static int is_not_zero(const uint8_t *sector, int len) -{ - int i; - len >>= 2; - for(i = 0;i < len; i++) { - if (((uint32_t *)sector)[i] != 0) - return 1; - } - return 0; -} - /* * Returns true iff the first sector pointed to by 'buf' contains at least * a non-NUL byte. @@ -557,20 +546,22 @@ static int is_not_zero(const uint8_t *sector, int len) */ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) { - int v, i; + bool is_zero; + int i; if (n <= 0) { *pnum = 0; return 0; } - v = is_not_zero(buf, 512); + is_zero = buffer_is_zero(buf, 512); for(i = 1; i < n; i++) { buf += 512; - if (v != is_not_zero(buf, 512)) + if (is_zero != buffer_is_zero(buf, 512)) { break; + } } *pnum = i; - return v; + return !is_zero; } /* @@ -914,7 +905,7 @@ static int img_convert(int argc, char **argv) if (n < cluster_sectors) { memset(buf + n * 512, 0, cluster_size - n * 512); } - if (is_not_zero(buf, cluster_size)) { + if (!buffer_is_zero(buf, cluster_size)) { ret = bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors); if (ret != 0) { -- 1.7.7.6