Skip to content

Commit a8fabb3

Browse files
jgross1Boris Ostrovsky
authored and
Boris Ostrovsky
committed
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 <[email protected]> Fixes: fd8aa90 ("xen: optimize xenbus driver for multiple concurrent xenstore accesses") Cc: <[email protected]> # 4.11 Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Signed-off-by: Boris Ostrovsky <[email protected]>
1 parent 0951570 commit a8fabb3

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

drivers/xen/xenbus/xenbus_dev_frontend.c

+18-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <linux/string.h>
5656
#include <linux/slab.h>
5757
#include <linux/miscdevice.h>
58+
#include <linux/workqueue.h>
5859

5960
#include <xen/xenbus.h>
6061
#include <xen/xen.h>
@@ -116,6 +117,8 @@ struct xenbus_file_priv {
116117
wait_queue_head_t read_waitq;
117118

118119
struct kref kref;
120+
121+
struct work_struct wq;
119122
};
120123

121124
/* Read out any raw xenbus messages queued up. */
@@ -300,14 +303,14 @@ static void watch_fired(struct xenbus_watch *watch,
300303
mutex_unlock(&adap->dev_data->reply_mutex);
301304
}
302305

303-
static void xenbus_file_free(struct kref *kref)
306+
static void xenbus_worker(struct work_struct *wq)
304307
{
305308
struct xenbus_file_priv *u;
306309
struct xenbus_transaction_holder *trans, *tmp;
307310
struct watch_adapter *watch, *tmp_watch;
308311
struct read_buffer *rb, *tmp_rb;
309312

310-
u = container_of(kref, struct xenbus_file_priv, kref);
313+
u = container_of(wq, struct xenbus_file_priv, wq);
311314

312315
/*
313316
* No need for locking here because there are no other users,
@@ -333,6 +336,18 @@ static void xenbus_file_free(struct kref *kref)
333336
kfree(u);
334337
}
335338

339+
static 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+
336351
static struct xenbus_transaction_holder *xenbus_get_transaction(
337352
struct xenbus_file_priv *u, uint32_t tx_id)
338353
{
@@ -650,6 +665,7 @@ static int xenbus_file_open(struct inode *inode, struct file *filp)
650665
INIT_LIST_HEAD(&u->watches);
651666
INIT_LIST_HEAD(&u->read_buffers);
652667
init_waitqueue_head(&u->read_waitq);
668+
INIT_WORK(&u->wq, xenbus_worker);
653669

654670
mutex_init(&u->reply_mutex);
655671
mutex_init(&u->msgbuffer_mutex);

0 commit comments

Comments
 (0)