[PATCH 08/11] tools/libxl: add functions for retrieving and setting xenstore quota

Juergen Gross posted 11 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH 08/11] tools/libxl: add functions for retrieving and setting xenstore quota
Posted by Juergen Gross 1 month, 1 week ago
Add some functions allowing to retrieve and set Xenstore quota (either
global or domain specific).

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 tools/golang/xenlight/helpers.gen.go |  78 ++++++++++++++++++++
 tools/golang/xenlight/types.gen.go   |   9 +++
 tools/include/libxl.h                |  20 ++++++
 tools/libs/light/Makefile            |   1 +
 tools/libs/light/libxl_types.idl     |   9 +++
 tools/libs/light/libxl_xsquota.c     | 102 +++++++++++++++++++++++++++
 6 files changed, 219 insertions(+)
 create mode 100644 tools/libs/light/libxl_xsquota.c

diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
index 8909fe8a1b..6c9af904c5 100644
--- a/tools/golang/xenlight/helpers.gen.go
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -998,6 +998,84 @@ xc.policy = C.libxl_rdm_reserve_policy(x.Policy)
  return nil
  }
 
+// NewXsQuotaItem returns an instance of XsQuotaItem initialized with defaults.
+func NewXsQuotaItem() (*XsQuotaItem, error) {
+var (
+x XsQuotaItem
+xc C.libxl_xs_quota_item)
+
+C.libxl_xs_quota_item_init(&xc)
+defer C.libxl_xs_quota_item_dispose(&xc)
+
+if err := x.fromC(&xc); err != nil {
+return nil, err }
+
+return &x, nil}
+
+func (x *XsQuotaItem) fromC(xc *C.libxl_xs_quota_item) error {
+ x.Name = C.GoString(xc.name)
+x.Val = uint32(xc.val)
+
+ return nil}
+
+func (x *XsQuotaItem) toC(xc *C.libxl_xs_quota_item) (err error){defer func(){
+if err != nil{
+C.libxl_xs_quota_item_dispose(xc)}
+}()
+
+if x.Name != "" {
+xc.name = C.CString(x.Name)}
+xc.val = C.uint32_t(x.Val)
+
+ return nil
+ }
+
+// NewXsQuotaSet returns an instance of XsQuotaSet initialized with defaults.
+func NewXsQuotaSet() (*XsQuotaSet, error) {
+var (
+x XsQuotaSet
+xc C.libxl_xs_quota_set)
+
+C.libxl_xs_quota_set_init(&xc)
+defer C.libxl_xs_quota_set_dispose(&xc)
+
+if err := x.fromC(&xc); err != nil {
+return nil, err }
+
+return &x, nil}
+
+func (x *XsQuotaSet) fromC(xc *C.libxl_xs_quota_set) error {
+ x.Quota = nil
+if n := int(xc.num_quota); n > 0 {
+cQuota := (*[1<<28]C.libxl_xs_quota_item)(unsafe.Pointer(xc.quota))[:n:n]
+x.Quota = make([]XsQuotaItem, n)
+for i, v := range cQuota {
+if err := x.Quota[i].fromC(&v); err != nil {
+return fmt.Errorf("converting field Quota: %v", err) }
+}
+}
+
+ return nil}
+
+func (x *XsQuotaSet) toC(xc *C.libxl_xs_quota_set) (err error){defer func(){
+if err != nil{
+C.libxl_xs_quota_set_dispose(xc)}
+}()
+
+if numQuota := len(x.Quota); numQuota > 0 {
+xc.quota = (*C.libxl_xs_quota_item)(C.malloc(C.ulong(numQuota)*C.sizeof_libxl_xs_quota_item))
+xc.num_quota = C.int(numQuota)
+cQuota := (*[1<<28]C.libxl_xs_quota_item)(unsafe.Pointer(xc.quota))[:numQuota:numQuota]
+for i,v := range x.Quota {
+if err := v.toC(&cQuota[i]); err != nil {
+return fmt.Errorf("converting field Quota: %v", err)
+}
+}
+}
+
+ return nil
+ }
+
 // NewDomainBuildInfo returns an instance of DomainBuildInfo initialized with defaults.
 func NewDomainBuildInfo(dtype DomainType) (*DomainBuildInfo, error) {
 var (
diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go
index ab9d4ca7b4..5393277190 100644
--- a/tools/golang/xenlight/types.gen.go
+++ b/tools/golang/xenlight/types.gen.go
@@ -543,6 +543,15 @@ Altp2MModeExternal Altp2MMode = 2
 Altp2MModeLimited Altp2MMode = 3
 )
 
+type XsQuotaItem struct {
+Name string
+Val uint32
+}
+
+type XsQuotaSet struct {
+Quota []XsQuotaItem
+}
+
 type DomainBuildInfo struct {
 MaxVcpus int
 AvailVcpus Bitmap
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index bc35e412da..a70d9d347f 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -1537,6 +1537,18 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src);
  */
 #define LIBXL_HAVE_XEN_PLATFORM_PCI_BAR_UC
 
+/*
+ * LIBXL_HAVE_XENSTORE_QUOTA
+ *
+ * If this is defined the Xenstore quota related functions
+ * libxl_xsquota_global_get()
+ * libxl_xsquota_global_set()
+ * libxl_xsquota_domain_get()
+ * libxl_xsquota_domain_set()
+ * are available.
+ */
+#define LIBXL_HAVE_XENSTORE_QUOTA
+
 typedef char **libxl_string_list;
 void libxl_string_list_dispose(libxl_string_list *sl);
 int libxl_string_list_length(const libxl_string_list *sl);
@@ -3011,6 +3023,14 @@ static inline int libxl_qemu_monitor_command_0x041200(libxl_ctx *ctx,
 #define libxl_qemu_monitor_command libxl_qemu_monitor_command_0x041200
 #endif
 
+/* Get/set global and per-domain Xenstore quota. */
+int libxl_xsquota_global_get(libxl_ctx *ctx, libxl_xs_quota_set *q);
+int libxl_xsquota_global_set(libxl_ctx *ctx, libxl_xs_quota_set *q);
+int libxl_xsquota_domain_get(libxl_ctx *ctx, uint32_t domid,
+                             libxl_xs_quota_set *q);
+int libxl_xsquota_domain_set(libxl_ctx *ctx, uint32_t domid,
+                             libxl_xs_quota_set *q);
+
 #include <libxl_event.h>
 
 /*
diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
index bc60c46558..ca22a40c6c 100644
--- a/tools/libs/light/Makefile
+++ b/tools/libs/light/Makefile
@@ -106,6 +106,7 @@ OBJS-y += libxl_pvcalls.o
 OBJS-y += libxl_vsnd.o
 OBJS-y += libxl_vkb.o
 OBJS-y += libxl_virtio.o
+OBJS-y += libxl_xsquota.o
 OBJS-y += libxl_genid.o
 OBJS-y += _libxl_types.o
 OBJS-y += libxl_flask.o
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index d64a573ff3..c5ddc40f35 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -574,6 +574,15 @@ libxl_altp2m_mode = Enumeration("altp2m_mode", [
     (3, "limited"),
     ], init_val = "LIBXL_ALTP2M_MODE_DISABLED")
 
+libxl_xs_quota_item = Struct("xs_quota_item", [
+    ("name", string),
+    ("val",  uint32),
+    ])
+
+libxl_xs_quota_set = Struct("xs_quota_set", [
+    ("quota", Array(libxl_xs_quota_item, "num_quota"))
+    ])
+
 libxl_domain_build_info = Struct("domain_build_info",[
     ("max_vcpus",       integer),
     ("avail_vcpus",     libxl_bitmap),
diff --git a/tools/libs/light/libxl_xsquota.c b/tools/libs/light/libxl_xsquota.c
new file mode 100644
index 0000000000..b9afa1c914
--- /dev/null
+++ b/tools/libs/light/libxl_xsquota.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+/* Xenstore quota handling functions. */
+
+#include "libxl_internal.h"
+
+static int get_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
+                     bool (func)(struct xs_handle *h, unsigned int domid,
+                                 char *quota, unsigned int *value))
+{
+    char **names;
+    unsigned int num, i;
+    int rc = 0;
+    GC_INIT(ctx);
+
+    names = xs_get_quota_names(ctx->xsh, &num);
+    if (!names) {
+        /* Xenstore quota support is optional! */
+        if (errno != ENOSYS)
+            rc = ERROR_FAIL;
+        q->num_quota = 0;
+        goto out;
+    }
+
+    q->num_quota = num;
+    q->quota = libxl__calloc(NOGC, num, sizeof(*q->quota));
+    for (i = 0; i < num; i++) {
+        q->quota[i].name = libxl__strdup(NOGC, names[i]);
+        if (!func(ctx->xsh, domid, q->quota[i].name, &q->quota[i].val)) {
+            libxl_xs_quota_set_dispose(q);
+            rc = ERROR_FAIL;
+            break;
+        }
+    }
+
+    free(names);
+
+ out:
+    GC_FREE;
+    return rc;
+}
+
+static int set_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
+                     bool (func)(struct xs_handle *h, unsigned int domid,
+                                 char *quota, unsigned int value))
+{
+    unsigned int i;
+    int rc = 0;
+    GC_INIT(ctx);
+
+    for (i = 0; i < q->num_quota; i++) {
+        if (!func(ctx->xsh, domid, q->quota[i].name, q->quota[i].val)) {
+            rc = ERROR_FAIL;
+            break;
+        }
+    }
+
+    GC_FREE;
+    return rc;
+}
+
+static bool get_global_quota(struct xs_handle *h, unsigned int domid,
+                             char *quota, unsigned int *value)
+{
+    return xs_get_global_quota(h, quota, value);
+}
+
+int libxl_xsquota_global_get(libxl_ctx *ctx, libxl_xs_quota_set *q)
+{
+    return get_quota(ctx, 0, q, get_global_quota);
+}
+
+static bool set_global_quota(struct xs_handle *h, unsigned int domid,
+                             char *quota, unsigned int value)
+{
+    return xs_set_global_quota(h, quota, value);
+}
+
+int libxl_xsquota_global_set(libxl_ctx *ctx, libxl_xs_quota_set *q)
+{
+    return set_quota(ctx, 0, q, set_global_quota);;
+}
+
+int libxl_xsquota_domain_get(libxl_ctx *ctx, uint32_t domid,
+                             libxl_xs_quota_set *q)
+{
+    return get_quota(ctx, domid, q, xs_get_domain_quota);
+}
+
+int libxl_xsquota_domain_set(libxl_ctx *ctx, uint32_t domid,
+                             libxl_xs_quota_set *q)
+{
+    return set_quota(ctx, domid, q, xs_set_domain_quota);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.53.0
Re: [PATCH 08/11] tools/libxl: add functions for retrieving and setting xenstore quota
Posted by Anthony PERARD 3 weeks, 3 days ago
On Thu, Mar 05, 2026 at 02:52:05PM +0100, Juergen Gross wrote:
> diff --git a/tools/include/libxl.h b/tools/include/libxl.h
> index bc35e412da..a70d9d347f 100644
> --- a/tools/include/libxl.h
> +++ b/tools/include/libxl.h
> @@ -1537,6 +1537,18 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src);
>   */
>  #define LIBXL_HAVE_XEN_PLATFORM_PCI_BAR_UC
>  
> +/*
> + * LIBXL_HAVE_XENSTORE_QUOTA
> + *
> + * If this is defined the Xenstore quota related functions
> + * libxl_xsquota_global_get()
> + * libxl_xsquota_global_set()
> + * libxl_xsquota_domain_get()
> + * libxl_xsquota_domain_set()
> + * are available.
> + */
> +#define LIBXL_HAVE_XENSTORE_QUOTA
> +
>  typedef char **libxl_string_list;
>  void libxl_string_list_dispose(libxl_string_list *sl);
>  int libxl_string_list_length(const libxl_string_list *sl);
> @@ -3011,6 +3023,14 @@ static inline int libxl_qemu_monitor_command_0x041200(libxl_ctx *ctx,
>  #define libxl_qemu_monitor_command libxl_qemu_monitor_command_0x041200
>  #endif
>  
> +/* Get/set global and per-domain Xenstore quota. */
> +int libxl_xsquota_global_get(libxl_ctx *ctx, libxl_xs_quota_set *q);

Could you rename the second arg as "q_r" or "q_out" ?

> +int libxl_xsquota_global_set(libxl_ctx *ctx, libxl_xs_quota_set *q);
> +int libxl_xsquota_domain_get(libxl_ctx *ctx, uint32_t domid,
> +                             libxl_xs_quota_set *q);

Same here.

> +int libxl_xsquota_domain_set(libxl_ctx *ctx, uint32_t domid,
> +                             libxl_xs_quota_set *q);

Could we prefix them all with "libxl_xs_quota_" ? I would rather that we
only use "xs_quota" or "xsquota".

> +
>  #include <libxl_event.h>
>  
>  /*
> diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
> index bc60c46558..ca22a40c6c 100644
> --- a/tools/libs/light/Makefile
> +++ b/tools/libs/light/Makefile
> @@ -106,6 +106,7 @@ OBJS-y += libxl_pvcalls.o
>  OBJS-y += libxl_vsnd.o
>  OBJS-y += libxl_vkb.o
>  OBJS-y += libxl_virtio.o
> +OBJS-y += libxl_xsquota.o
>  OBJS-y += libxl_genid.o
>  OBJS-y += _libxl_types.o
>  OBJS-y += libxl_flask.o
> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
> index d64a573ff3..c5ddc40f35 100644
> --- a/tools/libs/light/libxl_types.idl
> +++ b/tools/libs/light/libxl_types.idl
> @@ -574,6 +574,15 @@ libxl_altp2m_mode = Enumeration("altp2m_mode", [
>      (3, "limited"),
>      ], init_val = "LIBXL_ALTP2M_MODE_DISABLED")
>  
> +libxl_xs_quota_item = Struct("xs_quota_item", [
> +    ("name", string),
> +    ("val",  uint32),
> +    ])
> +
> +libxl_xs_quota_set = Struct("xs_quota_set", [

Could you use "_list" as a suffix instead? It's a bit confusing to have
the word "set" as a double meaning, with a _set() function that takes a
set.

> +    ("quota", Array(libxl_xs_quota_item, "num_quota"))
> +    ])
> +
>  libxl_domain_build_info = Struct("domain_build_info",[
>      ("max_vcpus",       integer),
>      ("avail_vcpus",     libxl_bitmap),
> diff --git a/tools/libs/light/libxl_xsquota.c b/tools/libs/light/libxl_xsquota.c
> new file mode 100644
> index 0000000000..b9afa1c914
> --- /dev/null
> +++ b/tools/libs/light/libxl_xsquota.c
> @@ -0,0 +1,102 @@
> +/* SPDX-License-Identifier: LGPL-2.1-only */
> +
> +/* Xenstore quota handling functions. */
> +
> +#include "libxl_internal.h"
> +
> +static int get_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
> +                     bool (func)(struct xs_handle *h, unsigned int domid,
> +                                 char *quota, unsigned int *value))
> +{
> +    char **names;
> +    unsigned int num, i;
> +    int rc = 0;

We don't init `rc` variable in libxl function. Set `rc` to 0 just before
the "out" label.

> +    GC_INIT(ctx);
> +
> +    names = xs_get_quota_names(ctx->xsh, &num);
> +    if (!names) {
> +        /* Xenstore quota support is optional! */
> +        if (errno != ENOSYS)
> +            rc = ERROR_FAIL;
> +        q->num_quota = 0;

It feels wrong to make changes to the output argument on error, if we
can avoid it. And here, I don't see any reason to change `q`.

> +        goto out;
> +    }
> +

Can you call libxl_xs_quota_set_init() first? As you call _dispose()
later.

> +    q->num_quota = num;
> +    q->quota = libxl__calloc(NOGC, num, sizeof(*q->quota));
> +    for (i = 0; i < num; i++) {
> +        q->quota[i].name = libxl__strdup(NOGC, names[i]);
> +        if (!func(ctx->xsh, domid, q->quota[i].name, &q->quota[i].val)) {

Could you store the return value of `func()` in `ok`, and test `ok` in the
if instead?

> +            libxl_xs_quota_set_dispose(q);
> +            rc = ERROR_FAIL;
> +            break;

This can be `goto out` once free(names) is moved to the out label.

> +        }
> +    }
> +
> +    free(names);

Could you do that after the "out" label? And init `names` to NULL.

> +
> + out:
> +    GC_FREE;
> +    return rc;
> +}
> +
> +static int set_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
> +                     bool (func)(struct xs_handle *h, unsigned int domid,
> +                                 char *quota, unsigned int value))
> +{
> +    unsigned int i;
> +    int rc = 0;
> +    GC_INIT(ctx);
> +
> +    for (i = 0; i < q->num_quota; i++) {
> +        if (!func(ctx->xsh, domid, q->quota[i].name, q->quota[i].val)) {
> +            rc = ERROR_FAIL;
> +            break;

It would be better to write `goto out` instead.

> +        }
> +    }
> +
> +    GC_FREE;
> +    return rc;
> +}

Thanks,


--
 | Vates

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech
Re: [PATCH 08/11] tools/libxl: add functions for retrieving and setting xenstore quota
Posted by Jürgen Groß 3 weeks, 3 days ago
On 19.03.26 10:11, Anthony PERARD wrote:
> On Thu, Mar 05, 2026 at 02:52:05PM +0100, Juergen Gross wrote:
>> diff --git a/tools/include/libxl.h b/tools/include/libxl.h
>> index bc35e412da..a70d9d347f 100644
>> --- a/tools/include/libxl.h
>> +++ b/tools/include/libxl.h
>> @@ -1537,6 +1537,18 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src);
>>    */
>>   #define LIBXL_HAVE_XEN_PLATFORM_PCI_BAR_UC
>>   
>> +/*
>> + * LIBXL_HAVE_XENSTORE_QUOTA
>> + *
>> + * If this is defined the Xenstore quota related functions
>> + * libxl_xsquota_global_get()
>> + * libxl_xsquota_global_set()
>> + * libxl_xsquota_domain_get()
>> + * libxl_xsquota_domain_set()
>> + * are available.
>> + */
>> +#define LIBXL_HAVE_XENSTORE_QUOTA
>> +
>>   typedef char **libxl_string_list;
>>   void libxl_string_list_dispose(libxl_string_list *sl);
>>   int libxl_string_list_length(const libxl_string_list *sl);
>> @@ -3011,6 +3023,14 @@ static inline int libxl_qemu_monitor_command_0x041200(libxl_ctx *ctx,
>>   #define libxl_qemu_monitor_command libxl_qemu_monitor_command_0x041200
>>   #endif
>>   
>> +/* Get/set global and per-domain Xenstore quota. */
>> +int libxl_xsquota_global_get(libxl_ctx *ctx, libxl_xs_quota_set *q);
> 
> Could you rename the second arg as "q_r" or "q_out" ?
> 
>> +int libxl_xsquota_global_set(libxl_ctx *ctx, libxl_xs_quota_set *q);
>> +int libxl_xsquota_domain_get(libxl_ctx *ctx, uint32_t domid,
>> +                             libxl_xs_quota_set *q);
> 
> Same here.
> 
>> +int libxl_xsquota_domain_set(libxl_ctx *ctx, uint32_t domid,
>> +                             libxl_xs_quota_set *q);
> 
> Could we prefix them all with "libxl_xs_quota_" ? I would rather that we
> only use "xs_quota" or "xsquota".
> 
>> +
>>   #include <libxl_event.h>
>>   
>>   /*
>> diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
>> index bc60c46558..ca22a40c6c 100644
>> --- a/tools/libs/light/Makefile
>> +++ b/tools/libs/light/Makefile
>> @@ -106,6 +106,7 @@ OBJS-y += libxl_pvcalls.o
>>   OBJS-y += libxl_vsnd.o
>>   OBJS-y += libxl_vkb.o
>>   OBJS-y += libxl_virtio.o
>> +OBJS-y += libxl_xsquota.o
>>   OBJS-y += libxl_genid.o
>>   OBJS-y += _libxl_types.o
>>   OBJS-y += libxl_flask.o
>> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
>> index d64a573ff3..c5ddc40f35 100644
>> --- a/tools/libs/light/libxl_types.idl
>> +++ b/tools/libs/light/libxl_types.idl
>> @@ -574,6 +574,15 @@ libxl_altp2m_mode = Enumeration("altp2m_mode", [
>>       (3, "limited"),
>>       ], init_val = "LIBXL_ALTP2M_MODE_DISABLED")
>>   
>> +libxl_xs_quota_item = Struct("xs_quota_item", [
>> +    ("name", string),
>> +    ("val",  uint32),
>> +    ])
>> +
>> +libxl_xs_quota_set = Struct("xs_quota_set", [
> 
> Could you use "_list" as a suffix instead? It's a bit confusing to have
> the word "set" as a double meaning, with a _set() function that takes a
> set.
> 
>> +    ("quota", Array(libxl_xs_quota_item, "num_quota"))
>> +    ])
>> +
>>   libxl_domain_build_info = Struct("domain_build_info",[
>>       ("max_vcpus",       integer),
>>       ("avail_vcpus",     libxl_bitmap),
>> diff --git a/tools/libs/light/libxl_xsquota.c b/tools/libs/light/libxl_xsquota.c
>> new file mode 100644
>> index 0000000000..b9afa1c914
>> --- /dev/null
>> +++ b/tools/libs/light/libxl_xsquota.c
>> @@ -0,0 +1,102 @@
>> +/* SPDX-License-Identifier: LGPL-2.1-only */
>> +
>> +/* Xenstore quota handling functions. */
>> +
>> +#include "libxl_internal.h"
>> +
>> +static int get_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
>> +                     bool (func)(struct xs_handle *h, unsigned int domid,
>> +                                 char *quota, unsigned int *value))
>> +{
>> +    char **names;
>> +    unsigned int num, i;
>> +    int rc = 0;
> 
> We don't init `rc` variable in libxl function. Set `rc` to 0 just before
> the "out" label.
> 
>> +    GC_INIT(ctx);
>> +
>> +    names = xs_get_quota_names(ctx->xsh, &num);
>> +    if (!names) {
>> +        /* Xenstore quota support is optional! */
>> +        if (errno != ENOSYS)
>> +            rc = ERROR_FAIL;
>> +        q->num_quota = 0;
> 
> It feels wrong to make changes to the output argument on error, if we
> can avoid it. And here, I don't see any reason to change `q`.
> 
>> +        goto out;
>> +    }
>> +
> 
> Can you call libxl_xs_quota_set_init() first? As you call _dispose()
> later.
> 
>> +    q->num_quota = num;
>> +    q->quota = libxl__calloc(NOGC, num, sizeof(*q->quota));
>> +    for (i = 0; i < num; i++) {
>> +        q->quota[i].name = libxl__strdup(NOGC, names[i]);
>> +        if (!func(ctx->xsh, domid, q->quota[i].name, &q->quota[i].val)) {
> 
> Could you store the return value of `func()` in `ok`, and test `ok` in the
> if instead?
> 
>> +            libxl_xs_quota_set_dispose(q);
>> +            rc = ERROR_FAIL;
>> +            break;
> 
> This can be `goto out` once free(names) is moved to the out label.
> 
>> +        }
>> +    }
>> +
>> +    free(names);
> 
> Could you do that after the "out" label? And init `names` to NULL.
> 
>> +
>> + out:
>> +    GC_FREE;
>> +    return rc;
>> +}
>> +
>> +static int set_quota(libxl_ctx *ctx, unsigned int domid, libxl_xs_quota_set *q,
>> +                     bool (func)(struct xs_handle *h, unsigned int domid,
>> +                                 char *quota, unsigned int value))
>> +{
>> +    unsigned int i;
>> +    int rc = 0;
>> +    GC_INIT(ctx);
>> +
>> +    for (i = 0; i < q->num_quota; i++) {
>> +        if (!func(ctx->xsh, domid, q->quota[i].name, q->quota[i].val)) {
>> +            rc = ERROR_FAIL;
>> +            break;
> 
> It would be better to write `goto out` instead.
> 
>> +        }
>> +    }
>> +
>> +    GC_FREE;
>> +    return rc;
>> +}

To all your remarks: yes, will do.


Thanks,

Juergen
Re: [PATCH 08/11] tools/libxl: add functions for retrieving and setting xenstore quota
Posted by Nick Rosbrook 1 month ago
On Thu, Mar 5, 2026 at 8:52 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add some functions allowing to retrieve and set Xenstore quota (either
> global or domain specific).
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
>  tools/golang/xenlight/helpers.gen.go |  78 ++++++++++++++++++++
>  tools/golang/xenlight/types.gen.go   |   9 +++
>  tools/include/libxl.h                |  20 ++++++
>  tools/libs/light/Makefile            |   1 +
>  tools/libs/light/libxl_types.idl     |   9 +++
>  tools/libs/light/libxl_xsquota.c     | 102 +++++++++++++++++++++++++++
>  6 files changed, 219 insertions(+)
>  create mode 100644 tools/libs/light/libxl_xsquota.c
>
> diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
> index 8909fe8a1b..6c9af904c5 100644
> --- a/tools/golang/xenlight/helpers.gen.go
> +++ b/tools/golang/xenlight/helpers.gen.go
> @@ -998,6 +998,84 @@ xc.policy = C.libxl_rdm_reserve_policy(x.Policy)
>   return nil
>   }
>
> +// NewXsQuotaItem returns an instance of XsQuotaItem initialized with defaults.
> +func NewXsQuotaItem() (*XsQuotaItem, error) {
> +var (
> +x XsQuotaItem
> +xc C.libxl_xs_quota_item)
> +
> +C.libxl_xs_quota_item_init(&xc)
> +defer C.libxl_xs_quota_item_dispose(&xc)
> +
> +if err := x.fromC(&xc); err != nil {
> +return nil, err }
> +
> +return &x, nil}
> +
> +func (x *XsQuotaItem) fromC(xc *C.libxl_xs_quota_item) error {
> + x.Name = C.GoString(xc.name)
> +x.Val = uint32(xc.val)
> +
> + return nil}
> +
> +func (x *XsQuotaItem) toC(xc *C.libxl_xs_quota_item) (err error){defer func(){
> +if err != nil{
> +C.libxl_xs_quota_item_dispose(xc)}
> +}()
> +
> +if x.Name != "" {
> +xc.name = C.CString(x.Name)}
> +xc.val = C.uint32_t(x.Val)
> +
> + return nil
> + }
> +
> +// NewXsQuotaSet returns an instance of XsQuotaSet initialized with defaults.
> +func NewXsQuotaSet() (*XsQuotaSet, error) {
> +var (
> +x XsQuotaSet
> +xc C.libxl_xs_quota_set)
> +
> +C.libxl_xs_quota_set_init(&xc)
> +defer C.libxl_xs_quota_set_dispose(&xc)
> +
> +if err := x.fromC(&xc); err != nil {
> +return nil, err }
> +
> +return &x, nil}
> +
> +func (x *XsQuotaSet) fromC(xc *C.libxl_xs_quota_set) error {
> + x.Quota = nil
> +if n := int(xc.num_quota); n > 0 {
> +cQuota := (*[1<<28]C.libxl_xs_quota_item)(unsafe.Pointer(xc.quota))[:n:n]
> +x.Quota = make([]XsQuotaItem, n)
> +for i, v := range cQuota {
> +if err := x.Quota[i].fromC(&v); err != nil {
> +return fmt.Errorf("converting field Quota: %v", err) }
> +}
> +}
> +
> + return nil}
> +
> +func (x *XsQuotaSet) toC(xc *C.libxl_xs_quota_set) (err error){defer func(){
> +if err != nil{
> +C.libxl_xs_quota_set_dispose(xc)}
> +}()
> +
> +if numQuota := len(x.Quota); numQuota > 0 {
> +xc.quota = (*C.libxl_xs_quota_item)(C.malloc(C.ulong(numQuota)*C.sizeof_libxl_xs_quota_item))
> +xc.num_quota = C.int(numQuota)
> +cQuota := (*[1<<28]C.libxl_xs_quota_item)(unsafe.Pointer(xc.quota))[:numQuota:numQuota]
> +for i,v := range x.Quota {
> +if err := v.toC(&cQuota[i]); err != nil {
> +return fmt.Errorf("converting field Quota: %v", err)
> +}
> +}
> +}
> +
> + return nil
> + }
> +
>  // NewDomainBuildInfo returns an instance of DomainBuildInfo initialized with defaults.
>  func NewDomainBuildInfo(dtype DomainType) (*DomainBuildInfo, error) {
>  var (
> diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go
> index ab9d4ca7b4..5393277190 100644
> --- a/tools/golang/xenlight/types.gen.go
> +++ b/tools/golang/xenlight/types.gen.go
> @@ -543,6 +543,15 @@ Altp2MModeExternal Altp2MMode = 2
>  Altp2MModeLimited Altp2MMode = 3
>  )
>
> +type XsQuotaItem struct {
> +Name string
> +Val uint32
> +}
> +
> +type XsQuotaSet struct {
> +Quota []XsQuotaItem
> +}
> +
>  type DomainBuildInfo struct {
>  MaxVcpus int
>  AvailVcpus Bitmap

For the golang stuff:

Acked-by: Nick Rosbrook <enr0n@ubuntu.com