[Libguestfs] [PATCH nbdkit v3 2/3] common: Introduce round up, down; and divide round up functions.

Richard W.M. Jones
Mon, 17 Sep 2018 21:27:26 -0000

This refactoring also fixes a bug spotted by Eric Blake:

  nbdkit --filter truncate pattern size=5G round-up=512

results in a 1G virtual disk.
---
 common/include/rounding.h   | 58 ++++++++++++++++++++++++++++++++++
 filters/cache/Makefile.am   |  3 +-
 filters/cache/cache.c       |  2 +-
 filters/cow/Makefile.am     |  3 +-
 filters/cow/cow.c           |  2 +-
 filters/truncate/truncate.c |  5 +--
 tests/Makefile.am           |  4 ++-
 tests/test-truncate3.sh     | 62 +++++++++++++++++++++++++++++++++++++
 8 files changed, 132 insertions(+), 7 deletions(-)

diff --git a/common/include/rounding.h b/common/include/rounding.h
new file mode 100644
index 0000000..ae1708c
--- /dev/null
+++ b/common/include/rounding.h
@@ -0,0 +1,58 @@
+/* nbdkit
+ * Copyright (C) 2018 Red Hat Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef NBDKIT_ROUNDING_H
+#define NBDKIT_ROUNDING_H
+
+#include <assert.h>
+
+#include "ispowerof2.h"
+
+/* Round up i to next multiple of n (n must be a power of 2).
+ */
+#define ROUND_UP(i, n) ({                          \
+      assert (is_power_of_2 (n));                  \
+      ((i) + (n) - 1) & -((typeof (i))n);          \
+})
+
+/* Round down i to next multiple of n (n must be a power of 2).
+ */
+#define ROUND_DOWN(i, n) ({                         \
+      assert (is_power_of_2 (n));                   \
+      (i) & -((typeof (i))(n));                     \
+})
+
+/* Return n / d, rounding the result up to the next integer. */
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#endif /* NBDKIT_ROUNDING_H */
diff --git a/filters/cache/Makefile.am b/filters/cache/Makefile.am
index 867812e..827ff17 100644
--- a/filters/cache/Makefile.am
+++ b/filters/cache/Makefile.am
@@ -41,7 +41,8 @@ nbdkit_cache_filter_la_SOURCES = \
 	$(top_srcdir)/include/nbdkit-filter.h

 nbdkit_cache_filter_la_CPPFLAGS = \
-	-I$(top_srcdir)/include
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/common/include
 nbdkit_cache_filter_la_CFLAGS = \
 	$(WARNINGS_CFLAGS)
 nbdkit_cache_filter_la_LDFLAGS = \
diff --git a/filters/cache/cache.c b/filters/cache/cache.c
index 90a0444..6ae6a4a 100644
--- a/filters/cache/cache.c
+++ b/filters/cache/cache.c
@@ -52,7 +52,7 @@

 #include <nbdkit-filter.h>

-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#include "rounding.h"

 /* XXX See design comment in filters/cow/cow.c. */
 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
diff --git a/filters/cow/Makefile.am b/filters/cow/Makefile.am
index 778df1e..c81b41c 100644
--- a/filters/cow/Makefile.am
+++ b/filters/cow/Makefile.am
@@ -41,7 +41,8 @@ nbdkit_cow_filter_la_SOURCES = \
 	$(top_srcdir)/include/nbdkit-filter.h

 nbdkit_cow_filter_la_CPPFLAGS = \
-	-I$(top_srcdir)/include
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/common/include
 nbdkit_cow_filter_la_CFLAGS = \
 	$(WARNINGS_CFLAGS)
 nbdkit_cow_filter_la_LDFLAGS = \
diff --git a/filters/cow/cow.c b/filters/cow/cow.c
index 5df1db2..001d5bf 100644
--- a/filters/cow/cow.c
+++ b/filters/cow/cow.c
@@ -89,7 +89,7 @@

 #include <nbdkit-filter.h>

-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#include "rounding.h"

 /* XXX See design comment above. */
 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
diff --git a/filters/truncate/truncate.c b/filters/truncate/truncate.c
index 185f6cc..b95432a 100644
--- a/filters/truncate/truncate.c
+++ b/filters/truncate/truncate.c
@@ -46,6 +46,7 @@

 #include "ispowerof2.h"
 #include "iszero.h"
+#include "rounding.h"

 #define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL

@@ -157,9 +158,9 @@ truncate_get_size (struct nbdkit_next_ops *next_ops, void
*nxdata,
   if (truncate_size >= 0)
     size = truncate_size;
   if (round_up > 0)
-    size = (size + round_up - 1) & ~(round_up - 1);
+    size = ROUND_UP (size, round_up);
   if (round_down > 0)
-    size &= ~(round_down - 1);
+    size = ROUND_DOWN (size, round_down);
   ret = size;

   pthread_mutex_unlock (&lock);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 23316ea..d04a7d6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -89,6 +89,7 @@ EXTRA_DIST = \
 	test-tls-psk.sh \
 	test-truncate1.sh \
 	test-truncate2.sh \
+	test-truncate3.sh \
 	test-vddk.sh \
 	test-version.sh \
 	test-version-filter.sh \
@@ -703,6 +704,7 @@ test_partition_LDADD = libtest.la $(LIBGUESTFS_LIBS)
 # truncate filter tests.
 TESTS += \
 	test-truncate1.sh \
-	test-truncate2.sh
+	test-truncate2.sh \
+	test-truncate3.sh

 endif HAVE_PLUGINS
diff --git a/tests/test-truncate3.sh b/tests/test-truncate3.sh
new file mode 100755
index 0000000..0ff1cbe
--- /dev/null
+++ b/tests/test-truncate3.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+# nbdkit
+# Copyright (C) 2018 Red Hat Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Red Hat nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS
IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+# Regression test for problem with truncate filter and C type
+# promotion, spotted by Eric Blake.
+
+source ./functions.sh
+set -e
+set -x
+
+files="truncate3.out truncate3.pid truncate3.sock"
+rm -f $files
+cleanup_fn rm -f $files
+
+# Test that qemu-img works
+if ! qemu-img --help >/dev/null; then
+    echo "$0: missing or broken qemu-img"
+    exit 77
+fi
+
+# Run nbdkit with pattern plugin and truncate filter in front.
+start_nbdkit -P truncate3.pid -U truncate3.sock \
+       --filter=truncate \
+       pattern size=5G \
+       round-up=512
+
+LANG=C qemu-img info nbd:unix:truncate3.sock > truncate3.out
+if ! grep "virtual size: 5.0G" truncate3.out; then
+    echo "$0: unexpected output from truncate3 regression test:"
+    cat truncate3.out
+    exit 1
+fi
--
2.19.0.rc0