[Spice-devel] [RFC PATCH spice-server v5 01/22] Avoid using global variable for channel IDs
Frediano Ziglio
fziglio at redhat.com
Mon Sep 4 10:27:11 UTC 2017
>
> Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
>
> On Wed, 2017-08-30 at 16:28 +0100, Frediano Ziglio wrote:
> > This patch allocates VMC IDs by finding the first ID not used
> > instead of using a global variable and incrementing the value
> > for each channel created.
> > This solves some potential issues:
> > - remove the global state potentially making possible
> > to use multiple SpiceServer on the same process;
> > - don't potentially overflow the variable. This can happen if
> > channels are allocated/deallocated multiple times
> > (currently not done by Qemu).
> >
> > Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> > ---
> > server/reds.c | 32 ++++++++++++++++++++++++++++++++
> > server/reds.h | 1 +
> > server/spicevmc.c | 10 ++++++++--
> > 3 files changed, 41 insertions(+), 2 deletions(-)
> >
> > diff --git a/server/reds.c b/server/reds.c
> > index a738afc3..b6ecc6c6 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -408,6 +408,38 @@ RedChannel *reds_find_channel(RedsState *reds,
> > uint32_t type, uint32_t id)
> > return NULL;
> > }
> >
> > +/* Search for first free channel id for a specific channel type.
> > + * Return first id free or <0 if not found. */
> > +int reds_get_free_channel_id(RedsState *reds, uint32_t type)
> > +{
> > + RedChannel *channel;
> > +
> > + // this mark if some IDs are used.
> > + // The size of the array limits the possible id returned but
> > + // usually the IDs used for a channel type are not much.
> > + bool used_ids[256];
> > +
I just realized due to protocol implementation that this
size is actually not a restriction, we are limited to
256 IDs in any case (a uint8 is used).
> > + unsigned n;
> > +
> > + // mark id used for the specific channel type
> > + memset(used_ids, 0, sizeof(used_ids));
> > + GLIST_FOREACH(reds->channels, RedChannel, channel) {
> > + uint32_t this_type, this_id;
> > + g_object_get(channel, "channel-type", &this_type, "id",
> > &this_id, NULL);
> > + if (this_type == type && this_id <
> > SPICE_N_ELEMENTS(used_ids)) {
> > + used_ids[this_id] = true;
> > + }
> > + }
> > +
> > + // find first ID not marked as used
> > + for (n = 0; n < SPICE_N_ELEMENTS(used_ids); ++n) {
> > + if (!used_ids[n]) {
> > + return n;
> > + }
> > + }
> > + return -1;
> > +}
> > +
> > static void reds_mig_cleanup(RedsState *reds)
> > {
> > if (reds->mig_inprogress) {
> > diff --git a/server/reds.h b/server/reds.h
> > index ee5a46c0..4f5fc28c 100644
> > --- a/server/reds.h
> > +++ b/server/reds.h
> > @@ -48,6 +48,7 @@ uint32_t reds_get_mm_time(void);
> > void reds_register_channel(RedsState *reds, RedChannel *channel);
> > void reds_unregister_channel(RedsState *reds, RedChannel *channel);
> > RedChannel *reds_find_channel(RedsState *reds, uint32_t type,
> > uint32_t id);
> > +int reds_get_free_channel_id(RedsState *reds, uint32_t type);
> > SpiceMouseMode reds_get_mouse_mode(RedsState *reds); // used by
> > inputs_channel
> > gboolean reds_config_get_agent_mouse(const RedsState *reds); // used
> > by inputs_channel
> > int reds_has_vdagent(RedsState *reds); // used by inputs channel
> > diff --git a/server/spicevmc.c b/server/spicevmc.c
> > index 9305c9b4..08d9954b 100644
> > --- a/server/spicevmc.c
> > +++ b/server/spicevmc.c
> > @@ -272,7 +272,6 @@ red_vmc_channel_finalize(GObject *object)
> > static RedVmcChannel *red_vmc_channel_new(RedsState *reds, uint8_t
> > channel_type)
> > {
> > GType gtype = G_TYPE_NONE;
> > - static uint8_t id[SPICE_END_CHANNEL] = { 0, };
> >
> > switch (channel_type) {
> > case SPICE_CHANNEL_USBREDIR:
> > @@ -288,11 +287,18 @@ static RedVmcChannel
> > *red_vmc_channel_new(RedsState *reds, uint8_t channel_type)
> > g_error("Unsupported channel_type for
> > red_vmc_channel_new(): %u", channel_type);
> > return NULL;
> > }
> > +
> > + int id = reds_get_free_channel_id(reds, channel_type);
> > + if (id < 0) {
> > + g_warning("Free ID not found creating new VMC channel");
> > + return NULL;
> > + }
> > +
> > return g_object_new(gtype,
> > "spice-server", reds,
> > "core-interface",
> > reds_get_core_interface(reds),
> > "channel-type", channel_type,
> > - "id", id[channel_type]++,
> > + "id", id,
> > "handle-acks", FALSE,
> > "migration-flags",
> > (SPICE_MIGRATE_NEED_FLUSH |
> > SPICE_MIGRATE_NEED_DATA_TRANSFER),
>
2 missing global variables to remove!
Frediano
More information about the Spice-devel
mailing list