Re: [libvirt] [PATCHv2 2/5] Add functions to track virtio-serial addresses

2015-03-24 Thread Ján Tomko
On Mon, Mar 23, 2015 at 05:46:19PM -0400, John Ferlan wrote:
> 
> 
> On 03/17/2015 07:41 AM, Ján Tomko wrote:
> > Create a sorted array of virtio-serial controllers.
> > Each of the elements contains the controller index
> > and a bitmap of available ports.
> > 
> > Buses are not tracked, because they aren't supported by QEMU.
> > ---
> >  src/conf/domain_addr.c   | 348 
> > +++
> >  src/conf/domain_addr.h   |  56 
> >  src/libvirt_private.syms |   9 ++
> >  3 files changed, 413 insertions(+)
> > 
> 
> I assumed the ACK to 1/5 sticks...

> > +
> > +static void
> > +virDomainVirtioSerialControllerFree(virDomainVirtioSerialControllerPtr 
> > cont)
> 
> Should the Free routine take a pointer so that when we VIR_FREE the
> pointer the caller doesn't have to "worry" about setting their copy to NULL?

None of the callers worry about that for this function. For the other
function, I like sticking to the existing convention:
*Free routines usually take a copy of the address, just like
virBitmapFree below.

I think
virFuncFree(foo->ptr);
looks more tidy than
virFuncFree(&(foo->ptr));

And in most of the cases, foo gets freed anyway.

> 
> > +{
> > +if (cont) {
> > +virBitmapFree(cont->ports);
> > +VIR_FREE(cont);
> > +}
> > +}
> > +
> > +static ssize_t
> > +virDomainVirtioSerialAddrPlaceController(virDomainVirtioSerialAddrSetPtr 
> > addrs,
> > + 
> > virDomainVirtioSerialControllerPtr cont)
> > +{
> > +size_t i;
> > +
> > +for (i = 0; i < addrs->ncontrollers; i++) {
> > +if (addrs->controllers[i]->idx >= cont->idx)
> > +return i;
> > +}
> 
> Would entries ""
> and " be rejected elsewhere?
> I would think "index" would be unique but this algorithm seems to be
> fine and happy with it.

For user-specified controllers, duplicate indexes are rejected by
virDomainDefRejectDuplicateControllers, so adding a controller
with a non-unique index would be a bug in the auto-allocation logic.

I'll squash this in:
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index d9d01fc..cda9ad2 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -754,7 +754,14 @@ 
virDomainVirtioSerialAddrPlaceController(virDomainVirtioSerialAddrSetPtr addrs,
 size_t i;
 
 for (i = 0; i < addrs->ncontrollers; i++) {
-if (addrs->controllers[i]->idx >= cont->idx)
+if (addrs->controllers[i]->idx == cont->idx) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("virtio serial controller with index %u already 
exists"
+ " in the address set"),
+   cont->idx);
+return -2;
+}
+if (addrs->controllers[i]->idx > cont->idx)
 return i;
 }
 return -1;
@@ -804,7 +811,8 @@ 
virDomainVirtioSerialAddrSetAddController(virDomainVirtioSerialAddrSetPtr addrs,
 goto cleanup;
 cnt->idx = cont->idx;
 
-insertAt = virDomainVirtioSerialAddrPlaceController(addrs, cnt);
+if ((insertAt = virDomainVirtioSerialAddrPlaceController(addrs, cnt)) < -1)
+goto cleanup;
 if (VIR_INSERT_ELEMENT(addrs->controllers, insertAt,
addrs->ncontrollers, cnt) < 0)
 goto cleanup;


> > +/* virDomainVirtioSerialAddrSetRemoveController
> > + *
> > + * Removes a virtio serial controller from the address set.
> > + */
> > +int
> > +virDomainVirtioSerialAddrSetRemoveController(virDomainVirtioSerialAddrSetPtr
> >  addrs,
> > + virDomainControllerDefPtr 
> > cont)
> > +{
> > +int ret = -1;
> > +ssize_t pos;
> > +
> > +if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
> > +return 0;
> > +
> > +VIR_DEBUG("Removing virtio serial controller index %u "
> > +  "from the address set", cont->idx);
> > +
> > +pos = virDomainVirtioSerialAddrFindController(addrs, cont->idx);
> > +
> > +if (pos >= 0 &&
> > +VIR_DELETE_ELEMENT(addrs->controllers, pos, addrs->ncontrollers) < 
> > 0)
> > +goto cleanup;
> > +
> 
> If 'pos' < 0, we return 0 (and perhaps leak something). OTOH, the
> controller was never added and the caller never checks status, maybe
> this should just be void (wonder why Coverity didn't whine)...
> 

There's nothing to be leaked. Coverity only whines if some callers check
the return value and some don't.

I'll change the return type to void.

> > +
> > +/* virDomainVirtioSerialAddrRelease
> > + *
> > + * Release the virtio serial address of the device
> > + */
> > +int
> > +virDomainVirtioSerialAddrRelease(virDomainVirtioSerialAddrSetPtr addrs,
> > + virDomainDeviceInfoPtr info)
> > +{
> > +virBitmapPtr map;
> > +char *str = NULL;
> > +int ret = -1;
> > +ssize_t i;
> > +
> > +if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL ||
> > +i

Re: [libvirt] [PATCHv2 2/5] Add functions to track virtio-serial addresses

2015-03-23 Thread John Ferlan


On 03/17/2015 07:41 AM, Ján Tomko wrote:
> Create a sorted array of virtio-serial controllers.
> Each of the elements contains the controller index
> and a bitmap of available ports.
> 
> Buses are not tracked, because they aren't supported by QEMU.
> ---
>  src/conf/domain_addr.c   | 348 
> +++
>  src/conf/domain_addr.h   |  56 
>  src/libvirt_private.syms |   9 ++
>  3 files changed, 413 insertions(+)
> 

I assumed the ACK to 1/5 sticks...

> diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
> index fb4a76f..d9d01fc 100644
> --- a/src/conf/domain_addr.c
> +++ b/src/conf/domain_addr.c
> @@ -718,3 +718,351 @@ virDomainCCWAddressSetCreate(void)
>  virDomainCCWAddressSetFree(addrs);
>  return NULL;
>  }
> +
> +
> +#define VIR_DOMAIN_DEFAULT_VIRTIO_SERIAL_PORTS 31
> +
> +
> +/* virDomainVirtioSerialAddrSetCreate
> + *
> + * Allocates an address set for virtio serial addresses
> + */
> +virDomainVirtioSerialAddrSetPtr
> +virDomainVirtioSerialAddrSetCreate(void)
> +{
> +virDomainVirtioSerialAddrSetPtr ret = NULL;
> +
> +if (VIR_ALLOC(ret) < 0)
> +return NULL;
> +
> +return ret;
> +}
> +
> +static void
> +virDomainVirtioSerialControllerFree(virDomainVirtioSerialControllerPtr cont)

Should the Free routine take a pointer so that when we VIR_FREE the
pointer the caller doesn't have to "worry" about setting their copy to NULL?

> +{
> +if (cont) {
> +virBitmapFree(cont->ports);
> +VIR_FREE(cont);
> +}
> +}
> +
> +static ssize_t
> +virDomainVirtioSerialAddrPlaceController(virDomainVirtioSerialAddrSetPtr 
> addrs,
> + virDomainVirtioSerialControllerPtr 
> cont)
> +{
> +size_t i;
> +
> +for (i = 0; i < addrs->ncontrollers; i++) {
> +if (addrs->controllers[i]->idx >= cont->idx)
> +return i;
> +}

Would entries ""
and " be rejected elsewhere?
I would think "index" would be unique but this algorithm seems to be
fine and happy with it.

> +return -1;
> +}
> +
> +static ssize_t
> +virDomainVirtioSerialAddrFindController(virDomainVirtioSerialAddrSetPtr 
> addrs,
> +unsigned int idx)
> +{
> +size_t i;
> +
> +for (i = 0; i < addrs->ncontrollers; i++) {
> +if (addrs->controllers[i]->idx == idx)
> +return i;
> +}
> +return -1;
> +}
> +
> +/* virDomainVirtioSerialAddrSetAddController
> + *
> + * Adds virtio serial ports of the existing controller
> + * to the address set.
> + */
> +int
> +virDomainVirtioSerialAddrSetAddController(virDomainVirtioSerialAddrSetPtr 
> addrs,
> +  virDomainControllerDefPtr cont)
> +{
> +int ret = -1;
> +int ports;
> +virDomainVirtioSerialControllerPtr cnt = NULL;
> +ssize_t insertAt;
> +
> +if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
> +return 0;
> +
> +ports = cont->opts.vioserial.ports;
> +if (ports == -1)
> +ports = VIR_DOMAIN_DEFAULT_VIRTIO_SERIAL_PORTS;
> +
> +VIR_DEBUG("Adding virtio serial controller index %u with %d"
> +  " ports to the address set", cont->idx, ports);
> +
> +if (VIR_ALLOC(cnt) < 0)
> +goto cleanup;
> +
> +if (!(cnt->ports = virBitmapNew(ports)))
> +goto cleanup;
> +cnt->idx = cont->idx;
> +
> +insertAt = virDomainVirtioSerialAddrPlaceController(addrs, cnt);
> +if (VIR_INSERT_ELEMENT(addrs->controllers, insertAt,
> +   addrs->ncontrollers, cnt) < 0)
> +goto cleanup;
> +
> +ret = 0;
> +
> + cleanup:
> +virDomainVirtioSerialControllerFree(cnt);
> +return ret;
> +}
> +
> +/* virDomainVirtioSerialAddrSetAddControllers
> + *
> + * Adds virtio serial ports of controllers present in the domain definition
> + * to the address set.
> + */
> +int
> +virDomainVirtioSerialAddrSetAddControllers(virDomainVirtioSerialAddrSetPtr 
> addrs,
> +   virDomainDefPtr def)
> +{
> +size_t i;
> +
> +for (i = 0; i < def->ncontrollers; i++) {
> +if (virDomainVirtioSerialAddrSetAddController(addrs,
> +  def->controllers[i]) < 
> 0)
> +return -1;
> +}
> +
> +return 0;
> +}
> +
> +/* virDomainVirtioSerialAddrSetRemoveController
> + *
> + * Removes a virtio serial controller from the address set.
> + */
> +int
> +virDomainVirtioSerialAddrSetRemoveController(virDomainVirtioSerialAddrSetPtr 
> addrs,
> + virDomainControllerDefPtr cont)
> +{
> +int ret = -1;
> +ssize_t pos;
> +
> +if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
> +return 0;
> +
> +VIR_DEBUG("Removing virtio serial controller index %u "
> +  "from the address set", cont->idx);
> +
> +pos = virDomainVirtioSerialAddrFindController(addrs, cont->idx);
> +
> +if (pos >=

[libvirt] [PATCHv2 2/5] Add functions to track virtio-serial addresses

2015-03-17 Thread Ján Tomko
Create a sorted array of virtio-serial controllers.
Each of the elements contains the controller index
and a bitmap of available ports.

Buses are not tracked, because they aren't supported by QEMU.
---
 src/conf/domain_addr.c   | 348 +++
 src/conf/domain_addr.h   |  56 
 src/libvirt_private.syms |   9 ++
 3 files changed, 413 insertions(+)

diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index fb4a76f..d9d01fc 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -718,3 +718,351 @@ virDomainCCWAddressSetCreate(void)
 virDomainCCWAddressSetFree(addrs);
 return NULL;
 }
+
+
+#define VIR_DOMAIN_DEFAULT_VIRTIO_SERIAL_PORTS 31
+
+
+/* virDomainVirtioSerialAddrSetCreate
+ *
+ * Allocates an address set for virtio serial addresses
+ */
+virDomainVirtioSerialAddrSetPtr
+virDomainVirtioSerialAddrSetCreate(void)
+{
+virDomainVirtioSerialAddrSetPtr ret = NULL;
+
+if (VIR_ALLOC(ret) < 0)
+return NULL;
+
+return ret;
+}
+
+static void
+virDomainVirtioSerialControllerFree(virDomainVirtioSerialControllerPtr cont)
+{
+if (cont) {
+virBitmapFree(cont->ports);
+VIR_FREE(cont);
+}
+}
+
+static ssize_t
+virDomainVirtioSerialAddrPlaceController(virDomainVirtioSerialAddrSetPtr addrs,
+ virDomainVirtioSerialControllerPtr 
cont)
+{
+size_t i;
+
+for (i = 0; i < addrs->ncontrollers; i++) {
+if (addrs->controllers[i]->idx >= cont->idx)
+return i;
+}
+return -1;
+}
+
+static ssize_t
+virDomainVirtioSerialAddrFindController(virDomainVirtioSerialAddrSetPtr addrs,
+unsigned int idx)
+{
+size_t i;
+
+for (i = 0; i < addrs->ncontrollers; i++) {
+if (addrs->controllers[i]->idx == idx)
+return i;
+}
+return -1;
+}
+
+/* virDomainVirtioSerialAddrSetAddController
+ *
+ * Adds virtio serial ports of the existing controller
+ * to the address set.
+ */
+int
+virDomainVirtioSerialAddrSetAddController(virDomainVirtioSerialAddrSetPtr 
addrs,
+  virDomainControllerDefPtr cont)
+{
+int ret = -1;
+int ports;
+virDomainVirtioSerialControllerPtr cnt = NULL;
+ssize_t insertAt;
+
+if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
+return 0;
+
+ports = cont->opts.vioserial.ports;
+if (ports == -1)
+ports = VIR_DOMAIN_DEFAULT_VIRTIO_SERIAL_PORTS;
+
+VIR_DEBUG("Adding virtio serial controller index %u with %d"
+  " ports to the address set", cont->idx, ports);
+
+if (VIR_ALLOC(cnt) < 0)
+goto cleanup;
+
+if (!(cnt->ports = virBitmapNew(ports)))
+goto cleanup;
+cnt->idx = cont->idx;
+
+insertAt = virDomainVirtioSerialAddrPlaceController(addrs, cnt);
+if (VIR_INSERT_ELEMENT(addrs->controllers, insertAt,
+   addrs->ncontrollers, cnt) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+virDomainVirtioSerialControllerFree(cnt);
+return ret;
+}
+
+/* virDomainVirtioSerialAddrSetAddControllers
+ *
+ * Adds virtio serial ports of controllers present in the domain definition
+ * to the address set.
+ */
+int
+virDomainVirtioSerialAddrSetAddControllers(virDomainVirtioSerialAddrSetPtr 
addrs,
+   virDomainDefPtr def)
+{
+size_t i;
+
+for (i = 0; i < def->ncontrollers; i++) {
+if (virDomainVirtioSerialAddrSetAddController(addrs,
+  def->controllers[i]) < 0)
+return -1;
+}
+
+return 0;
+}
+
+/* virDomainVirtioSerialAddrSetRemoveController
+ *
+ * Removes a virtio serial controller from the address set.
+ */
+int
+virDomainVirtioSerialAddrSetRemoveController(virDomainVirtioSerialAddrSetPtr 
addrs,
+ virDomainControllerDefPtr cont)
+{
+int ret = -1;
+ssize_t pos;
+
+if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
+return 0;
+
+VIR_DEBUG("Removing virtio serial controller index %u "
+  "from the address set", cont->idx);
+
+pos = virDomainVirtioSerialAddrFindController(addrs, cont->idx);
+
+if (pos >= 0 &&
+VIR_DELETE_ELEMENT(addrs->controllers, pos, addrs->ncontrollers) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+return ret;
+}
+
+void
+virDomainVirtioSerialAddrSetFree(virDomainVirtioSerialAddrSetPtr addrs)
+{
+size_t i;
+if (addrs) {
+for (i = 0; i < addrs->ncontrollers; i++)
+virDomainVirtioSerialControllerFree(addrs->controllers[i]);
+VIR_FREE(addrs);
+}
+}
+
+static int
+virDomainVirtioSerialAddrNext(virDomainVirtioSerialAddrSetPtr addrs,
+  virDomainDeviceVirtioSerialAddress *addr,
+  bool allowZero)
+{
+int ret = -1;
+ssize_t port, start = 0;
+ssize_t