aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2019-10-01 11:03:55 -0400
committerBoris Ostrovsky <boris.ostrovsky@oracle.com>2019-10-02 16:40:11 -0400
commita8fabb38525c51a094607768bac3ba46b3f4a9d5 (patch)
tree2cd7beab8e2e789f2587ae722d28c4d908d50c02
parent09515706857a7d5a2ffb5ce6a44c0bc7859a745b (diff)
xen/xenbus: fix self-deadlock after killing user process
In case a user process using xenbus has open transactions and is killed e.g. via ctrl-C the following cleanup of the allocated resources might result in a deadlock due to trying to end a transaction in the xenbus worker thread: [ 2551.474706] INFO: task xenbus:37 blocked for more than 120 seconds. [ 2551.492215] Tainted: P OE 5.0.0-29-generic #5 [ 2551.510263] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 2551.528585] xenbus D 0 37 2 0x80000080 [ 2551.528590] Call Trace: [ 2551.528603] __schedule+0x2c0/0x870 [ 2551.528606] ? _cond_resched+0x19/0x40 [ 2551.528632] schedule+0x2c/0x70 [ 2551.528637] xs_talkv+0x1ec/0x2b0 [ 2551.528642] ? wait_woken+0x80/0x80 [ 2551.528645] xs_single+0x53/0x80 [ 2551.528648] xenbus_transaction_end+0x3b/0x70 [ 2551.528651] xenbus_file_free+0x5a/0x160 [ 2551.528654] xenbus_dev_queue_reply+0xc4/0x220 [ 2551.528657] xenbus_thread+0x7de/0x880 [ 2551.528660] ? wait_woken+0x80/0x80 [ 2551.528665] kthread+0x121/0x140 [ 2551.528667] ? xb_read+0x1d0/0x1d0 [ 2551.528670] ? kthread_park+0x90/0x90 [ 2551.528673] ret_from_fork+0x35/0x40 Fix this by doing the cleanup via a workqueue instead. Reported-by: James Dingwall <james@dingwall.me.uk> Fixes: fd8aa9095a95c ("xen: optimize xenbus driver for multiple concurrent xenstore accesses") Cc: <stable@vger.kernel.org> # 4.11 Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-rw-r--r--drivers/xen/xenbus/xenbus_dev_frontend.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 08adc590f631..597af455a522 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -55,6 +55,7 @@
55#include <linux/string.h> 55#include <linux/string.h>
56#include <linux/slab.h> 56#include <linux/slab.h>
57#include <linux/miscdevice.h> 57#include <linux/miscdevice.h>
58#include <linux/workqueue.h>
58 59
59#include <xen/xenbus.h> 60#include <xen/xenbus.h>
60#include <xen/xen.h> 61#include <xen/xen.h>
@@ -116,6 +117,8 @@ struct xenbus_file_priv {
116 wait_queue_head_t read_waitq; 117 wait_queue_head_t read_waitq;
117 118
118 struct kref kref; 119 struct kref kref;
120
121 struct work_struct wq;
119}; 122};
120 123
121/* Read out any raw xenbus messages queued up. */ 124/* Read out any raw xenbus messages queued up. */
@@ -300,14 +303,14 @@ static void watch_fired(struct xenbus_watch *watch,
300 mutex_unlock(&adap->dev_data->reply_mutex); 303 mutex_unlock(&adap->dev_data->reply_mutex);
301} 304}
302 305
303static void xenbus_file_free(struct kref *kref) 306static void xenbus_worker(struct work_struct *wq)
304{ 307{
305 struct xenbus_file_priv *u; 308 struct xenbus_file_priv *u;
306 struct xenbus_transaction_holder *trans, *tmp; 309 struct xenbus_transaction_holder *trans, *tmp;
307 struct watch_adapter *watch, *tmp_watch; 310 struct watch_adapter *watch, *tmp_watch;
308 struct read_buffer *rb, *tmp_rb; 311 struct read_buffer *rb, *tmp_rb;
309 312
310 u = container_of(kref, struct xenbus_file_priv, kref); 313 u = container_of(wq, struct xenbus_file_priv, wq);
311 314
312 /* 315 /*
313 * No need for locking here because there are no other users, 316 * No need for locking here because there are no other users,
@@ -333,6 +336,18 @@ static void xenbus_file_free(struct kref *kref)
333 kfree(u); 336 kfree(u);
334} 337}
335 338
339static void xenbus_file_free(struct kref *kref)
340{
341 struct xenbus_file_priv *u;
342
343 /*
344 * We might be called in xenbus_thread().
345 * Use workqueue to avoid deadlock.
346 */
347 u = container_of(kref, struct xenbus_file_priv, kref);
348 schedule_work(&u->wq);
349}
350
336static struct xenbus_transaction_holder *xenbus_get_transaction( 351static struct xenbus_transaction_holder *xenbus_get_transaction(
337 struct xenbus_file_priv *u, uint32_t tx_id) 352 struct xenbus_file_priv *u, uint32_t tx_id)
338{ 353{
@@ -650,6 +665,7 @@ static int xenbus_file_open(struct inode *inode, struct file *filp)
650 INIT_LIST_HEAD(&u->watches); 665 INIT_LIST_HEAD(&u->watches);
651 INIT_LIST_HEAD(&u->read_buffers); 666 INIT_LIST_HEAD(&u->read_buffers);
652 init_waitqueue_head(&u->read_waitq); 667 init_waitqueue_head(&u->read_waitq);
668 INIT_WORK(&u->wq, xenbus_worker);
653 669
654 mutex_init(&u->reply_mutex); 670 mutex_init(&u->reply_mutex);
655 mutex_init(&u->msgbuffer_mutex); 671 mutex_init(&u->msgbuffer_mutex);