diff options
-rw-r--r-- | drivers/xen/xenbus/xenbus_dev_frontend.c | 20 |
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 | ||
303 | static void xenbus_file_free(struct kref *kref) | 306 | static 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 | ||
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 | |||
336 | static struct xenbus_transaction_holder *xenbus_get_transaction( | 351 | static 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); |