[PATCH v9 3/5] move logical block size check function to a common utility function

Coiby Xu posted 5 patches 5 years, 7 months ago
Maintainers: Stefan Hajnoczi <stefanha@redhat.com>, Kevin Wolf <kwolf@redhat.com>, Eduardo Habkost <ehabkost@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>, Max Reitz <mreitz@redhat.com>, "Dr. David Alan Gilbert" <dgilbert@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>
There is a newer version of this series
[PATCH v9 3/5] move logical block size check function to a common utility function
Posted by Coiby Xu 5 years, 7 months ago
Move logical block size check function in hw/core/qdev-properties.c:set_blocksize() to util/block-helpers.c

Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
 hw/core/qdev-properties.c | 18 +++------------
 util/Makefile.objs        |  1 +
 util/block-helpers.c      | 46 +++++++++++++++++++++++++++++++++++++++
 util/block-helpers.h      |  7 ++++++
 4 files changed, 57 insertions(+), 15 deletions(-)
 create mode 100644 util/block-helpers.c
 create mode 100644 util/block-helpers.h

diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index cc924815da..a4a6aa5204 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -14,6 +14,7 @@
 #include "qapi/visitor.h"
 #include "chardev/char.h"
 #include "qemu/uuid.h"
+#include "util/block-helpers.h"
 
 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
                                   Error **errp)
@@ -736,8 +737,6 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
     Property *prop = opaque;
     uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
     Error *local_err = NULL;
-    const int64_t min = 512;
-    const int64_t max = 32768;
 
     if (dev->realized) {
         qdev_prop_set_after_realize(dev, name, errp);
@@ -749,21 +748,10 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
         error_propagate(errp, local_err);
         return;
     }
-    /* value of 0 means "unset" */
-    if (value && (value < min || value > max)) {
-        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                   dev->id ? : "", name, (int64_t)value, min, max);
+    check_logical_block_size(dev->id ? : "", name, value, errp);
+    if (errp) {
         return;
     }
-
-    /* We rely on power-of-2 blocksizes for bitmasks */
-    if ((value & (value - 1)) != 0) {
-        error_setg(errp,
-                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
-                  dev->id ?: "", name, (int64_t)value);
-        return;
-    }
-
     *ptr = value;
 }
 
diff --git a/util/Makefile.objs b/util/Makefile.objs
index b4d4af06dc..fa5380ddab 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -66,6 +66,7 @@ util-obj-y += hbitmap.o
 util-obj-y += main-loop.o
 util-obj-y += nvdimm-utils.o
 util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
+util-obj-y += block-helpers.o
 util-obj-$(CONFIG_LINUX) += vhost-user-server.o
 util-obj-y += qemu-coroutine-sleep.o
 util-obj-y += qemu-co-shared-resource.o
diff --git a/util/block-helpers.c b/util/block-helpers.c
new file mode 100644
index 0000000000..d31309cc0e
--- /dev/null
+++ b/util/block-helpers.c
@@ -0,0 +1,46 @@
+/*
+ * Block utility functions
+ *
+ * Copyright (c) 2020 Coiby Xu <coiby.xu@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "block-helpers.h"
+
+/*
+ * Logical block size input validation
+ *
+ * The size should meet the following conditions:
+ * 1. min=512
+ * 2. max=32768
+ * 3. a power of 2
+ *
+ *  Moved from hw/core/qdev-properties.c:set_blocksize()
+ */
+void check_logical_block_size(const char *id, const char *name, uint16_t value,
+                     Error **errp)
+{
+    const int64_t min = 512;
+    const int64_t max = 32768;
+
+    /* value of 0 means "unset" */
+    if (value && (value < min || value > max)) {
+        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
+                   id, name, (int64_t)value, min, max);
+        return;
+    }
+
+    /* We rely on power-of-2 blocksizes for bitmasks */
+    if ((value & (value - 1)) != 0) {
+        error_setg(errp,
+                   "Property %s.%s doesn't take value '%" PRId64
+                   "', it's not a power of 2",
+                   id, name, (int64_t)value);
+        return;
+    }
+}
diff --git a/util/block-helpers.h b/util/block-helpers.h
new file mode 100644
index 0000000000..f06be282a1
--- /dev/null
+++ b/util/block-helpers.h
@@ -0,0 +1,7 @@
+#ifndef BLOCK_HELPERS_H
+#define BLOCK_HELPERS_H
+
+void check_logical_block_size(const char *id, const char *name, uint16_t value,
+                     Error **errp);
+
+#endif /* BLOCK_HELPERS_H */
-- 
2.27.0


Re: [PATCH v9 3/5] move logical block size check function to a common utility function
Posted by Kevin Wolf 5 years, 7 months ago
Am 14.06.2020 um 20:39 hat Coiby Xu geschrieben:
> Move logical block size check function in hw/core/qdev-properties.c:set_blocksize() to util/block-helpers.c
> 
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>

Just a heads-up that you'll probably need to rebase this after the pull
request I sent yesterday is merged because it changes the block size
properties.

Kevin


[PATCH 1/6] block-helpers: move MIN/MAX_BLOCK_SIZE constants into header file
Posted by Stefan Hajnoczi 5 years, 7 months ago
Move the constants from hw/core/qdev-properties.c to
util/block-helpers.h so that knowledge of the min/max values is
encapsulated in block-helpers code.

Callers should not assume specific min/max values. In fact, the values
in hw/core/qdev-properties.c and util/block-helpers.c did not match. Use
the hw/core/qdev-properties.c values since that's what existing code
expects.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 util/block-helpers.h      | 12 ++++++++++++
 hw/core/qdev-properties.c | 11 -----------
 util/block-helpers.c      |  7 ++-----
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/util/block-helpers.h b/util/block-helpers.h
index f06be282a1..46975ca7af 100644
--- a/util/block-helpers.h
+++ b/util/block-helpers.h
@@ -1,6 +1,18 @@
 #ifndef BLOCK_HELPERS_H
 #define BLOCK_HELPERS_H
 
+#include "qemu/units.h"
+
+/* lower limit is sector size */
+#define MIN_BLOCK_SIZE          INT64_C(512)
+#define MIN_BLOCK_SIZE_STR      "512 B"
+/*
+ * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
+ * matches qcow2 cluster size limit
+ */
+#define MAX_BLOCK_SIZE          (2 * MiB)
+#define MAX_BLOCK_SIZE_STR      "2 MiB"
+
 void check_logical_block_size(const char *id, const char *name, uint16_t value,
                      Error **errp);
 
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index b478f100af..03981feb02 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -14,7 +14,6 @@
 #include "qapi/visitor.h"
 #include "chardev/char.h"
 #include "qemu/uuid.h"
-#include "qemu/units.h"
 #include "util/block-helpers.h"
 
 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
@@ -782,16 +781,6 @@ const PropertyInfo qdev_prop_size32 = {
 
 /* --- blocksize --- */
 
-/* lower limit is sector size */
-#define MIN_BLOCK_SIZE          512
-#define MIN_BLOCK_SIZE_STR      "512 B"
-/*
- * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
- * matches qcow2 cluster size limit
- */
-#define MAX_BLOCK_SIZE          (2 * MiB)
-#define MAX_BLOCK_SIZE_STR      "2 MiB"
-
 static void set_blocksize(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
 {
diff --git a/util/block-helpers.c b/util/block-helpers.c
index d31309cc0e..089fe3401d 100644
--- a/util/block-helpers.c
+++ b/util/block-helpers.c
@@ -25,13 +25,10 @@
 void check_logical_block_size(const char *id, const char *name, uint16_t value,
                      Error **errp)
 {
-    const int64_t min = 512;
-    const int64_t max = 32768;
-
     /* value of 0 means "unset" */
-    if (value && (value < min || value > max)) {
+    if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
         error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
-                   id, name, (int64_t)value, min, max);
+                   id, name, value, MIN_BLOCK_SIZE, MAX_BLOCK_SIZE);
         return;
     }
 
-- 
2.26.2

[PATCH 2/6] block-helpers: switch to int64_t block size values
Posted by Stefan Hajnoczi 5 years, 7 months ago
The uint16_t type is too small for MAX_BLOCK_SIZE (2 MiB). The int64_t
type is widely used in QEMU as a type for disk offsets and sizes, so
it's an appropriate type to use here. It will work for all callers.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 util/block-helpers.h | 2 +-
 util/block-helpers.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/util/block-helpers.h b/util/block-helpers.h
index 46975ca7af..ec6421560c 100644
--- a/util/block-helpers.h
+++ b/util/block-helpers.h
@@ -13,7 +13,7 @@
 #define MAX_BLOCK_SIZE          (2 * MiB)
 #define MAX_BLOCK_SIZE_STR      "2 MiB"
 
-void check_logical_block_size(const char *id, const char *name, uint16_t value,
+void check_logical_block_size(const char *id, const char *name, int64_t value,
                      Error **errp);
 
 #endif /* BLOCK_HELPERS_H */
diff --git a/util/block-helpers.c b/util/block-helpers.c
index 089fe3401d..9e68954c46 100644
--- a/util/block-helpers.c
+++ b/util/block-helpers.c
@@ -22,7 +22,7 @@
  *
  *  Moved from hw/core/qdev-properties.c:set_blocksize()
  */
-void check_logical_block_size(const char *id, const char *name, uint16_t value,
+void check_logical_block_size(const char *id, const char *name, int64_t value,
                      Error **errp)
 {
     /* value of 0 means "unset" */
@@ -37,7 +37,7 @@ void check_logical_block_size(const char *id, const char *name, uint16_t value,
         error_setg(errp,
                    "Property %s.%s doesn't take value '%" PRId64
                    "', it's not a power of 2",
-                   id, name, (int64_t)value);
+                   id, name, value);
         return;
     }
 }
-- 
2.26.2

[PATCH 3/6] block-helpers: rename check_logical_block_size() to check_block_size()
Posted by Stefan Hajnoczi 5 years, 7 months ago
Block size checking is the same whether it's a physical, logical, or
other block size value. Use a more general name to show this function
can be used in other cases too (just like the qdev property that this
code originally comes from).

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 util/block-helpers.h      | 4 ++--
 hw/core/qdev-properties.c | 2 +-
 util/block-helpers.c      | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/util/block-helpers.h b/util/block-helpers.h
index ec6421560c..b53295a529 100644
--- a/util/block-helpers.h
+++ b/util/block-helpers.h
@@ -13,7 +13,7 @@
 #define MAX_BLOCK_SIZE          (2 * MiB)
 #define MAX_BLOCK_SIZE_STR      "2 MiB"
 
-void check_logical_block_size(const char *id, const char *name, int64_t value,
-                     Error **errp);
+void check_block_size(const char *id, const char *name, int64_t value,
+                      Error **errp);
 
 #endif /* BLOCK_HELPERS_H */
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 03981feb02..28a6d8b2ee 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -800,7 +800,7 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
         error_propagate(errp, local_err);
         return;
     }
-    check_logical_block_size(dev->id ? : "", name, value, errp);
+    check_block_size(dev->id ? : "", name, value, errp);
     if (errp) {
         return;
     }
diff --git a/util/block-helpers.c b/util/block-helpers.c
index 9e68954c46..51d9d02c43 100644
--- a/util/block-helpers.c
+++ b/util/block-helpers.c
@@ -22,8 +22,8 @@
  *
  *  Moved from hw/core/qdev-properties.c:set_blocksize()
  */
-void check_logical_block_size(const char *id, const char *name, int64_t value,
-                     Error **errp)
+void check_block_size(const char *id, const char *name, int64_t value,
+                      Error **errp)
 {
     /* value of 0 means "unset" */
     if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
-- 
2.26.2

[PATCH 4/6] block-helpers: use local_err in case errp is NULL
Posted by Stefan Hajnoczi 5 years, 7 months ago
If we use errp then we won't know when check_block_size() fails when
errp is NULL.

The purpose of local_err is to detect an error has occurred even if the
caller doesn't care about the specific error and has passed a NULL errp.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 hw/core/qdev-properties.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 28a6d8b2ee..0a651c7d32 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -800,8 +800,9 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
         error_propagate(errp, local_err);
         return;
     }
-    check_block_size(dev->id ? : "", name, value, errp);
-    if (errp) {
+    check_block_size(dev->id ? : "", name, value, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
         return;
     }
     *ptr = value;
-- 
2.26.2

[PATCH 5/6] block-helpers: keep the copyright line from the original file
Posted by Stefan Hajnoczi 5 years, 7 months ago
The check_block_size() code comes from hw/core/qdev-properties.c. Keep
the copyright.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 util/block-helpers.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/util/block-helpers.c b/util/block-helpers.c
index 51d9d02c43..9d12368032 100644
--- a/util/block-helpers.c
+++ b/util/block-helpers.c
@@ -1,6 +1,7 @@
 /*
  * Block utility functions
  *
+ * Copyright IBM, Corp. 2011
  * Copyright (c) 2020 Coiby Xu <coiby.xu@gmail.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
-- 
2.26.2

[PATCH 6/6] block-helpers: update doc comment in gtkdoc style
Posted by Stefan Hajnoczi 5 years, 7 months ago
QEMU uses the gtkdoc style for API doc comments. For examples, see
include/qom/object.h.

Fully document the function with up-to-date information (the min/max
values were outdated).

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 util/block-helpers.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/util/block-helpers.c b/util/block-helpers.c
index 9d12368032..c4851432f5 100644
--- a/util/block-helpers.c
+++ b/util/block-helpers.c
@@ -13,15 +13,17 @@
 #include "qapi/qmp/qerror.h"
 #include "block-helpers.h"
 
-/*
- * Logical block size input validation
+/**
+ * check_block_size:
+ * @id: The unique ID of the object
+ * @name: The name of the property being validated
+ * @value: The block size in bytes
+ * @errp: A pointer to an area to store an error
  *
- * The size should meet the following conditions:
- * 1. min=512
- * 2. max=32768
- * 3. a power of 2
- *
- *  Moved from hw/core/qdev-properties.c:set_blocksize()
+ * This function checks that the block size meets the following conditions:
+ * 1. At least MIN_BLOCK_SIZE
+ * 2. No larger than MAX_BLOCK_SIZE
+ * 3. A power of 2
  */
 void check_block_size(const char *id, const char *name, int64_t value,
                       Error **errp)
-- 
2.26.2