[Spice-devel] [spice-server] cursor: Delay release of QXL guest cursor resources
Frediano Ziglio
fziglio at redhat.com
Tue Apr 10 12:16:32 UTC 2018
> >
> > Ping? I would like to move forward with having this fix temporarily in
> > spice-server even if in the long run, we'll be fixing QEMU too.
> > This would ease the upgrade path, as having this patch means we don't
> > tie upgrades to spice-server 0.14 with QEMU upgrades, it does not matter
> > if you upgrade both at once or not, spice-server will have the same
> > behaviour as in the 0.12 branch.
> >
> > Christophe
> >
>
> When do you plan to remove this patch from spice-server?
>
> > On Thu, Apr 05, 2018 at 10:36:27AM +0200, Christophe Fergeau wrote:
> > > There's an implicit API/ABI contract between QEMU and SPICE that SPICE
> > > will keep the guest QXL resources alive as long as QEMU can hold a
> > > pointer to them. This implicit contract was broken in 1c6e7cf7 "Release
> > > cursor as soon as possible", causing crashes at migration time.
> > > While the proper fix would be in QEMU so that spice-server does not need
> > > to have that kind of knowledge regarding QEMU internal implementation,
> > > this commit reverts to the pre-1c6e7cf7 behaviour to avoid a regression
> > > while QEMU is being fixed.
> > >
> > > https://bugzilla.redhat.com/show_bug.cgi?id=1540919
> > >
> > > Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>
>
> Would not be better to add a qxl field in RedCursorCmd and free the resource
> in red_put_cursor_cmd?
> This patch looks pretty invasive.
>
Like:
diff --git a/server/red-parse-qxl.c b/server/red-parse-qxl.c
index 69748698..f421a35b 100644
--- a/server/red-parse-qxl.c
+++ b/server/red-parse-qxl.c
@@ -26,6 +26,7 @@
#include "red-common.h"
#include "memslot.h"
#include "red-parse-qxl.h"
+#include "red-qxl.h"
/* Max size in bytes for any data field used in a QXL command.
* This will for example be useful to prevent the guest from saturating the
@@ -1495,6 +1496,9 @@ void red_put_cursor_cmd(RedCursorCmd *red)
{
switch (red->type) {
case QXL_CURSOR_SET:
+ if (red->qxl) {
+ red_qxl_release_resource(red->qxl, red->release_info_ext);
+ }
red_put_cursor(&red->u.set.shape);
break;
}
diff --git a/server/red-parse-qxl.h b/server/red-parse-qxl.h
index ce7d8b05..a33f36ad 100644
--- a/server/red-parse-qxl.h
+++ b/server/red-parse-qxl.h
@@ -99,6 +99,7 @@ typedef struct RedSurfaceCmd {
} RedSurfaceCmd;
typedef struct RedCursorCmd {
+ QXLInstance *qxl;
QXLReleaseInfoExt release_info_ext;
uint8_t type;
union {
diff --git a/server/red-worker.c b/server/red-worker.c
index 387f500e..eb927f3e 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -118,7 +118,7 @@ static gboolean red_process_cursor_cmd(RedWorker *worker, const QXLCommandExt *e
g_free(cursor_cmd);
return FALSE;
}
- red_qxl_release_resource(worker->qxl, cursor_cmd->release_info_ext);
+ cursor_cmd->qxl = worker->qxl;
cursor_channel_process_cmd(worker->cursor_channel, cursor_cmd);
return TRUE;
}
Frediano
> > > ---
> > > server/cursor-channel.c | 16 +++++++++++++---
> > > server/cursor-channel.h | 5 ++++-
> > > server/red-stream-device.c | 4 ++--
> > > server/red-worker.c | 10 ++++++++--
> > > 4 files changed, 27 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> > > index 522261e3f..a7bee9815 100644
> > > --- a/server/cursor-channel.c
> > > +++ b/server/cursor-channel.c
> > > @@ -31,6 +31,8 @@
> > > typedef struct RedCursorPipeItem {
> > > RedPipeItem base;
> > > RedCursorCmd *red_cursor;
> > > + ReleaseCommandCb release_command_cb;
> > > + gpointer user_data;
> > > } RedCursorPipeItem;
> > >
> > > struct CursorChannel
> > > @@ -54,7 +56,9 @@ G_DEFINE_TYPE(CursorChannel, cursor_channel,
> > > TYPE_COMMON_GRAPHICS_CHANNEL)
> > >
> > > static void cursor_pipe_item_free(RedPipeItem *pipe_item);
> > >
> > > -static RedCursorPipeItem *cursor_pipe_item_new(RedCursorCmd *cmd)
> > > +static RedCursorPipeItem *cursor_pipe_item_new(RedCursorCmd *cmd,
> > > + ReleaseCommandCb
> > > release_command_cb,
> > > + gpointer user_data)
> > > {
> > > RedCursorPipeItem *item = g_new0(RedCursorPipeItem, 1);
> > >
> > > @@ -63,6 +67,8 @@ static RedCursorPipeItem
> > > *cursor_pipe_item_new(RedCursorCmd *cmd)
> > > red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR,
> > > cursor_pipe_item_free);
> > > item->red_cursor = cmd;
> > > + item->release_command_cb = release_command_cb;
> > > + item->user_data = user_data;
> > >
> > > return item;
> > > }
> > > @@ -73,6 +79,9 @@ static void cursor_pipe_item_free(RedPipeItem *base)
> > > RedCursorPipeItem *pipe_item = SPICE_UPCAST(RedCursorPipeItem,
> > > base);
> > >
> > > cursor_cmd = pipe_item->red_cursor;
> > > + if (pipe_item->release_command_cb) {
> > > + pipe_item->release_command_cb(cursor_cmd, pipe_item->user_data);
> > > + }
> > > red_put_cursor_cmd(cursor_cmd);
> > > g_free(cursor_cmd);
> > >
> > > @@ -246,7 +255,8 @@ CursorChannel* cursor_channel_new(RedsState *server,
> > > int id,
> > > NULL);
> > > }
> > >
> > > -void cursor_channel_process_cmd(CursorChannel *cursor, RedCursorCmd
> > > *cursor_cmd)
> > > +void cursor_channel_process_cmd(CursorChannel *cursor, RedCursorCmd
> > > *cursor_cmd,
> > > + ReleaseCommandCb release_command_cb,
> > > gpointer user_data)
> > > {
> > > RedCursorPipeItem *cursor_pipe_item;
> > > bool cursor_show = false;
> > > @@ -254,7 +264,7 @@ void cursor_channel_process_cmd(CursorChannel
> > > *cursor,
> > > RedCursorCmd *cursor_cmd)
> > > spice_return_if_fail(cursor);
> > > spice_return_if_fail(cursor_cmd);
> > >
> > > - cursor_pipe_item = cursor_pipe_item_new(cursor_cmd);
> > > + cursor_pipe_item = cursor_pipe_item_new(cursor_cmd,
> > > release_command_cb, user_data);
> > >
> > > switch (cursor_cmd->type) {
> > > case QXL_CURSOR_SET:
> > > diff --git a/server/cursor-channel.h b/server/cursor-channel.h
> > > index 603c2c0ac..e41e52438 100644
> > > --- a/server/cursor-channel.h
> > > +++ b/server/cursor-channel.h
> > > @@ -44,6 +44,8 @@ typedef struct CursorChannelClass CursorChannelClass;
> > >
> > > GType cursor_channel_get_type(void) G_GNUC_CONST;
> > >
> > > +typedef void (*ReleaseCommandCb)(RedCursorCmd *command, gpointer
> > > user_data);
> > > +
> > > /**
> > > * Create CursorChannel.
> > > * Since CursorChannel is intended to be run in a separate thread,
> > > @@ -61,7 +63,8 @@ CursorChannel* cursor_channel_new(RedsState *server,
> > > int
> > > id,
> > >
> > > void cursor_channel_reset (CursorChannel *cursor);
> > > void cursor_channel_do_init (CursorChannel *cursor);
> > > -void cursor_channel_process_cmd (CursorChannel *cursor,
> > > RedCursorCmd *cursor_cmd);
> > > +void cursor_channel_process_cmd(CursorChannel *cursor,
> > > RedCursorCmd *cursor_cmd,
> > > + ReleaseCommandCb
> > > release_command_cb, gpointer user_data);
> > > void cursor_channel_set_mouse_mode(CursorChannel
> > > *cursor,
> > > uint32_t mode);
> > >
> > > /**
> > > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > > index e151de367..36f8b4b61 100644
> > > --- a/server/red-stream-device.c
> > > +++ b/server/red-stream-device.c
> > > @@ -386,7 +386,7 @@ handle_msg_cursor_set(StreamDevice *dev,
> > > SpiceCharDeviceInstance *sin)
> > > if (!cmd) {
> > > return handle_msg_invalid(dev, sin, NULL);
> > > }
> > > - cursor_channel_process_cmd(dev->cursor_channel, cmd);
> > > + cursor_channel_process_cmd(dev->cursor_channel, cmd, NULL, NULL);
> > >
> > > return true;
> > > }
> > > @@ -413,7 +413,7 @@ handle_msg_cursor_move(StreamDevice *dev,
> > > SpiceCharDeviceInstance *sin)
> > > cmd->u.position.x = move->x;
> > > cmd->u.position.y = move->y;
> > >
> > > - cursor_channel_process_cmd(dev->cursor_channel, cmd);
> > > + cursor_channel_process_cmd(dev->cursor_channel, cmd, NULL, NULL);
> > >
> > > return true;
> > > }
> > > diff --git a/server/red-worker.c b/server/red-worker.c
> > > index 387f500e8..a549becf0 100644
> > > --- a/server/red-worker.c
> > > +++ b/server/red-worker.c
> > > @@ -109,6 +109,13 @@ void red_drawable_unref(RedDrawable *red_drawable)
> > > g_free(red_drawable);
> > > }
> > >
> > > +static void release_cursor_cmd_cb(RedCursorCmd *cursor_cmd, gpointer
> > > user_data)
> > > +{
> > > + QXLInstance *qxl = user_data;
> > > +
> > > + red_qxl_release_resource(qxl, cursor_cmd->release_info_ext);
> > > +}
> > > +
> > > static gboolean red_process_cursor_cmd(RedWorker *worker, const
> > > QXLCommandExt *ext)
> > > {
> > > RedCursorCmd *cursor_cmd;
> > > @@ -118,8 +125,7 @@ static gboolean red_process_cursor_cmd(RedWorker
> > > *worker, const QXLCommandExt *e
> > > g_free(cursor_cmd);
> > > return FALSE;
> > > }
> > > - red_qxl_release_resource(worker->qxl, cursor_cmd->release_info_ext);
> > > - cursor_channel_process_cmd(worker->cursor_channel, cursor_cmd);
> > > + cursor_channel_process_cmd(worker->cursor_channel, cursor_cmd,
> > > release_cursor_cmd_cb, worker->qxl);
> > > return TRUE;
> > > }
> > >
More information about the Spice-devel
mailing list