This patch makes the flexarray function libxl__gc aware.
It also updates every function that use a flexarray to pass the gc and removes
every memory allocation check and free.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
#include "libxl_internal.h"
#include <stdarg.h>
-flexarray_t *flexarray_make(int size, int autogrow)
+/*
+ * It is safe to store gc in the struct because:
+ * - If it an actual gc, then the flexarray should not be used after the gc
+ * have been freed.
+ * - If it is a NOGC, then this point to a structure embedded in libxl_ctx,
+ * therefore will survive across several libxl calls.
+ */
+
+flexarray_t *flexarray_make(libxl__gc *gc, int size, int autogrow)
{
- flexarray_t *array = malloc(sizeof(struct flexarray));
- if (array) {
- array->size = size;
- array->autogrow = autogrow;
- array->count = 0;
- array->data = calloc(size, sizeof(void *));
- }
+ flexarray_t *array;
+
+ GCNEW(array);
+ array->size = size;
+ array->autogrow = autogrow;
+ array->count = 0;
+ array->gc = gc;
+ GCNEW_ARRAY(array->data, size);
+
return array;
}
void flexarray_free(flexarray_t *array)
{
+ assert(!libxl__gc_is_real(array->gc));
free(array->data);
free(array);
}
-int flexarray_grow(flexarray_t *array, int extents)
+void flexarray_grow(flexarray_t *array, int extents)
{
- void **data;
int newsize;
+ libxl__gc *gc = array->gc;
newsize = array->size + extents;
- data = realloc(array->data, sizeof(void *) * newsize);
- if (!data)
- return 1;
+ GCREALLOC_ARRAY(array->data, newsize);
array->size += extents;
- array->data = data;
- return 0;
}
int flexarray_set(flexarray_t *array, unsigned int idx, void *ptr)
if (!array->autogrow)
return 1;
newsize = (array->size * 2 < idx) ? idx + 1 : array->size * 2;
- if (flexarray_grow(array, newsize - array->size))
- return 2;
+ flexarray_grow(array, newsize - array->size);
}
if ( idx + 1 > array->count )
array->count = idx + 1;
{
void **data;
data = array->data;
- free(array);
+ if (!libxl__gc_is_real(array->gc))
+ free(array);
return data;
}
#ifndef FLEXARRAY_H
#define FLEXARRAY_H
+struct libxl__gc;
+
typedef struct flexarray {
int size;
int autogrow;
unsigned int count;
void **data; /* array of pointer */
+ struct libxl__gc *gc;
} flexarray_t;
-_hidden flexarray_t *flexarray_make(int size, int autogrow);
+_hidden flexarray_t *flexarray_make(struct libxl__gc *gc, int size, int autogrow);
_hidden void flexarray_free(flexarray_t *array);
-_hidden int flexarray_grow(flexarray_t *array, int extents);
+_hidden void flexarray_grow(flexarray_t *array, int extents);
_hidden int flexarray_set(flexarray_t *array, unsigned int index, void *ptr);
_hidden int flexarray_append(flexarray_t *array, void *ptr);
_hidden int flexarray_append_pair(flexarray_t *array, void *ptr1, void *ptr2);
rc = libxl__device_disk_setdefault(gc, disk);
if (rc) goto out;
- if (front)
- flexarray_free(front);
- front = flexarray_make(16, 1);
- if (!front) {
- rc = ERROR_NOMEM;
- goto out;
- }
- if (back)
- flexarray_free(back);
- back = flexarray_make(16, 1);
- if (!back) {
- rc = ERROR_NOMEM;
- goto out_free;
- }
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
GCNEW(device);
rc = libxl__device_from_disk(gc, domid, disk, device);
if (rc != 0) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
" virtual disk identifier %s", disk->vdev);
- goto out_free;
+ goto out;
}
switch (disk->backend) {
LOG(ERROR, "failed to get blktap devpath for %p\n",
disk->pdev_path);
rc = ERROR_FAIL;
- goto out_free;
+ goto out;
}
flexarray_append(back, "tapdisk-params");
flexarray_append(back, libxl__sprintf(gc, "%s:%s",
default:
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: %d\n", disk->backend);
rc = ERROR_INVAL;
- goto out_free;
+ goto out;
}
flexarray_append(back, "frontend-id");
rc = libxl__xs_transaction_commit(gc, &t);
if (!rc) break;
- if (rc < 0) goto out_free;
+ if (rc < 0) goto out;
}
aodev->dev = device;
rc = 0;
-out_free:
- flexarray_free(back);
- flexarray_free(front);
out:
libxl__xs_transaction_abort(gc, &t);
aodev->rc = rc;
if (rc) goto out;
path = libxl__device_backend_path(gc, &device);
- insert = flexarray_make(4, 1);
+ insert = flexarray_make(gc, 4, 1);
flexarray_append_pair(insert, "type",
libxl__device_disk_string_of_backend(disk->backend));
libxl_device_disk_dispose(&disks[i]);
free(disks);
- if (insert) flexarray_free(insert);
-
if (rc) return AO_ABORT(rc);
return AO_INPROGRESS;
}
rc = libxl__device_nic_setdefault(gc, nic, domid);
if (rc) goto out;
- front = flexarray_make(16, 1);
- if (!front) {
- rc = ERROR_NOMEM;
- goto out;
- }
- back = flexarray_make(16, 1);
- if (!back) {
- rc = ERROR_NOMEM;
- goto out_free;
- }
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
if (nic->devid == -1) {
if (!(dompath = libxl__xs_get_dompath(gc, domid))) {
rc = ERROR_FAIL;
- goto out_free;
+ goto out;
}
if (!(l = libxl__xs_directory(gc, XBT_NULL,
libxl__sprintf(gc, "%s/device/vif", dompath), &nb))) {
GCNEW(device);
rc = libxl__device_from_nic(gc, domid, nic, device);
- if ( rc != 0 ) goto out_free;
+ if ( rc != 0 ) goto out;
flexarray_append(back, "frontend-id");
flexarray_append(back, libxl__sprintf(gc, "%d", domid));
libxl__wait_device_connection(egc, aodev);
rc = 0;
-out_free:
- flexarray_free(back);
- flexarray_free(front);
out:
aodev->rc = rc;
if (rc) aodev->callback(egc, aodev);
goto out;
}
- front = flexarray_make(16, 1);
- if (!front) {
- rc = ERROR_NOMEM;
- goto out;
- }
- back = flexarray_make(16, 1);
- if (!back) {
- rc = ERROR_NOMEM;
- goto out_free;
- }
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
device.backend_devid = console->devid;
device.backend_domid = console->backend_domid;
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count));
rc = 0;
-out_free:
- flexarray_free(back);
- flexarray_free(front);
out:
return rc;
}
rc = libxl__device_vkb_setdefault(gc, vkb);
if (rc) goto out;
- front = flexarray_make(16, 1);
- if (!front) {
- rc = ERROR_NOMEM;
- goto out;
- }
- back = flexarray_make(16, 1);
- if (!back) {
- rc = ERROR_NOMEM;
- goto out_free;
- }
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
rc = libxl__device_from_vkb(gc, domid, vkb, &device);
- if (rc != 0) goto out_free;
+ if (rc != 0) goto out;
flexarray_append(back, "frontend-id");
flexarray_append(back, libxl__sprintf(gc, "%d", domid));
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count));
rc = 0;
-out_free:
- flexarray_free(back);
- flexarray_free(front);
out:
return rc;
}
rc = libxl__device_vfb_setdefault(gc, vfb);
if (rc) goto out;
- front = flexarray_make(16, 1);
- if (!front) {
- rc = ERROR_NOMEM;
- goto out;
- }
- back = flexarray_make(16, 1);
- if (!back) {
- rc = ERROR_NOMEM;
- goto out_free;
- }
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
rc = libxl__device_from_vfb(gc, domid, vfb, &device);
- if (rc != 0) goto out_free;
+ if (rc != 0) goto out;
flexarray_append_pair(back, "frontend-id", libxl__sprintf(gc, "%d", domid));
flexarray_append_pair(back, "online", "1");
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count));
rc = 0;
-out_free:
- flexarray_free(front);
- flexarray_free(back);
out:
return rc;
}
const char *keymap = dm_keymap(guest_config);
int i;
flexarray_t *dm_args;
- dm_args = flexarray_make(16, 1);
-
- if (!dm_args)
- return NULL;
+ dm_args = flexarray_make(gc, 16, 1);
flexarray_vappend(dm_args, dm,
"-d", libxl__sprintf(gc, "%d", domid), NULL);
int i;
uint64_t ram_size;
- dm_args = flexarray_make(16, 1);
- if (!dm_args)
- return NULL;
+ dm_args = flexarray_make(gc, 16, 1);
flexarray_vappend(dm_args, dm,
"-xen-domid",
"setting target domain %d -> %d",
dm_domid, guest_domid);
ret = ERROR_FAIL;
- goto out_free;
+ goto out;
}
xs_set_target(ctx->xsh, dm_domid, guest_domid);
libxl__add_disks(egc, ao, dm_domid, dm_config, &sdss->multidev);
libxl__multidev_prepared(egc, &sdss->multidev, 0);
- free(args);
return;
-out_free:
- free(args);
out:
assert(ret);
spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret);
out_close:
close(null);
close(logfile_w);
- free(args);
out:
if (rc)
device_model_spawn_outcome(egc, dmss, rc);
obj->type = type;
if (type == JSON_MAP || type == JSON_ARRAY) {
- flexarray_t *array = flexarray_make(1, 1);
- if (array == NULL) {
- LIBXL__LOG_ERRNO(libxl__gc_owner(gc), LIBXL__LOG_ERROR,
- "Failed to allocate a flexarray");
- free(obj);
- return NULL;
- }
+ flexarray_t *array = flexarray_make(NOGC, 1, 1);
if (type == JSON_MAP)
obj->u.map = array;
else
libxl__device device;
int ret = ERROR_NOMEM, i;
- front = flexarray_make(16, 1);
- if (!front)
- goto out;
- back = flexarray_make(16, 1);
- if (!back)
- goto out;
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
ret = 0;
libxl__xs_kvs_of_flexarray(gc, back, back->count),
libxl__xs_kvs_of_flexarray(gc, front, front->count));
-out:
- if (back)
- flexarray_free(back);
- if (front)
- flexarray_free(front);
return 0;
}
return ERROR_FAIL;
}
- back = flexarray_make(16, 1);
- if (!back)
- return ERROR_NOMEM;
+ back = flexarray_make(gc, 16, 1);
LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Adding new pci device to xenstore");
num = atoi(num_devs);
if (errno == EAGAIN)
goto retry_transaction;
- flexarray_free(back);
return 0;
}
if (!hostaddr)
return -1;
- parameters = flexarray_make(6, 1);
+ parameters = flexarray_make(gc, 6, 1);
flexarray_append_pair(parameters, "driver", "xen-pci-passthrough");
flexarray_append_pair(parameters, "id",
libxl__sprintf(gc, PCI_PT_QDEV_ID,
PCI_FUNC(pcidev->vdevfn)));
}
args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count);
- if (!args)
- return -1;
rc = qmp_synchronous_send(qmp, "device_add", &args,
NULL, NULL, qmp->timeout);
pci_add_callback, pcidev, qmp->timeout);
}
- flexarray_free(parameters);
libxl__qmp_close(qmp);
return rc;
}
if (!qmp)
return ERROR_FAIL;
- parameters = flexarray_make(2, 1);
+ parameters = flexarray_make(gc, 2, 1);
flexarray_append_pair(parameters, "id", id);
args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count);
- if (!args)
- return ERROR_NOMEM;
rc = qmp_synchronous_send(qmp, "device_del", &args,
NULL, NULL, qmp->timeout);
- flexarray_free(parameters);
libxl__qmp_close(qmp);
return rc;
}
if (!qmp)
return ERROR_FAIL;
- parameters = flexarray_make(2, 1);
- if (!parameters) {
- rc = ERROR_NOMEM;
- goto out;
- }
+ parameters = flexarray_make(gc, 2, 1);
flexarray_append_pair(parameters, "filename", (char *)filename);
args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count);
- if (!args) {
- rc = ERROR_NOMEM;
- goto out2;
- }
rc = qmp_synchronous_send(qmp, "xen-save-devices-state", &args,
NULL, NULL, qmp->timeout);
-out2:
- flexarray_free(parameters);
-out:
libxl__qmp_close(qmp);
return rc;
}
libxl_key_value_list args = NULL;
int rc = 0;
- parameters = flexarray_make(6, 1);
+ parameters = flexarray_make(gc, 6, 1);
flexarray_append_pair(parameters, "device", device);
flexarray_append_pair(parameters, "target", target);
if (arg)
flexarray_append_pair(parameters, "arg", arg);
args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count);
- if (!args)
- return ERROR_NOMEM;
rc = qmp_synchronous_send(qmp, "change", &args,
NULL, NULL, qmp->timeout);
- flexarray_free(parameters);
return rc;
}