From 731f3ab66a23dab28a359e87364f53d221b3d366 Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Fri, 7 Jan 2011 18:17:17 +0800 Subject: xen/fb: fix xenfb suspend/resume race. When migrating guests over a long period we hit this: <1>BUG: unable to handle kernel paging request at 0000000b819fdb98 <1>IP: [] notify_remote_via_irq+0x13/0x34 <4>PGD 94b10067 PUD 0 <0>Oops: 0000 [#1] SMP .. snip.. Call Trace: [] xenfb_send_event+0x5c/0x5e [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? _spin_unlock_irqrestore+0x16/0x18 [] xenfb_refresh+0x1b1/0x1d7 [] ? sys_imageblit+0x1ac/0x458 [] xenfb_imageblit+0x2f/0x34 [] soft_cursor+0x1b5/0x1c8 [] bit_cursor+0x4b6/0x4d7 [] ? xen_restore_fl_direct_end+0x0/0x1 [] ? _spin_unlock_irqrestore+0x16/0x18 [] ? bit_cursor+0x0/0x4d7 [] fb_flashcursor+0xff/0x111 [] ? fb_flashcursor+0x0/0x111 [] worker_thread+0x14d/0x1ed [] ? autoremove_wake_function+0x0/0x3d [] ? _spin_unlock_irqrestore+0x16/0x18 [] ? worker_thread+0x0/0x1ed [] kthread+0x6e/0x76 [] child_rip+0xa/0x20 [] ? int_ret_from_sys_call+0x7/0x1b [] ? retint_restore_args+0x5/0x6 [] ? child_rip+0x0/0x20 Code: 6b ff 0c 8b 87 a4 db 9f 81 66 85 c0 74 08 0f b7 f8 e8 3b ff ff ff c9 c3 55 48 89 e5 48 83 ec 10 0f 1f 44 00 00 89 ff 48 6b ff 0c <8b> 87 a4 db 9f 81 66 85 c0 74 14 48 8d 75 f0 0f b7 c0 bf 04 00 RIP [] notify_remote_via_irq+0x13/0x34 RSP CR2: 0000000b819fdb98 ---[ end trace 098b4b74827595d0 ]--- The root cause of the panic is the race between the resume and reconnect to the backend. Clearing the 'update_wanted' flag of xenfb before disconnecting from the backend fixes this issue. Signed-off-by: Joe Jin Signed-off-by: Konrad Rzeszutek Wilk Tested-by: Gurudas Pai Acked-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Andrew Morton --- drivers/video/xen-fbfront.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index 428d273be727..f92313d33e27 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -617,6 +617,8 @@ static int xenfb_connect_backend(struct xenbus_device *dev, static void xenfb_disconnect_backend(struct xenfb_info *info) { + /* Prevent xenfb refresh */ + info->update_wanted = 0; if (info->irq >= 0) unbind_from_irqhandler(info->irq, info); info->irq = -1; -- cgit v1.2.3 From fc550e95921e109f3778a6b2dc560d63388810ab Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Fri, 7 Jan 2011 18:20:54 +0800 Subject: xen/fb: fix potential memory leak This patch fixes a potential memory leak when xenfb connect to the backend fails. Thanks for Ian's review and comments. [v2: reworded the commit message a bit] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Joe Jin Tested-by: Gurudas Pai Acked-by: Ian Campbell Cc: Jeremy Fitzhardinge Cc: Andrew Morton --- drivers/video/xen-fbfront.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index f92313d33e27..95bbd0a1e5da 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -562,26 +562,24 @@ static void xenfb_init_shared_page(struct xenfb_info *info, static int xenfb_connect_backend(struct xenbus_device *dev, struct xenfb_info *info) { - int ret, evtchn; + int ret, evtchn, irq; struct xenbus_transaction xbt; ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) return ret; - ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, + irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, 0, dev->devicetype, info); - if (ret < 0) { + if (irq < 0) { xenbus_free_evtchn(dev, evtchn); xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); - return ret; + return irq; } - info->irq = ret; - again: ret = xenbus_transaction_start(&xbt); if (ret) { xenbus_dev_fatal(dev, ret, "starting transaction"); - return ret; + goto unbind_irq; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page)); @@ -603,15 +601,18 @@ static int xenfb_connect_backend(struct xenbus_device *dev, if (ret == -EAGAIN) goto again; xenbus_dev_fatal(dev, ret, "completing transaction"); - return ret; + goto unbind_irq; } xenbus_switch_state(dev, XenbusStateInitialised); + info->irq = irq; return 0; error_xenbus: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, ret, "writing xenstore"); + unbind_irq: + unbind_from_irqhandler(irq, info); return ret; } -- cgit v1.2.3