# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 5552bc2c3716e9e0f57dbba80f61332b895a0f2a
# Parent b0ba792f393520a4262aa06f5ab2395efa1a32c2
[LINUX][BLK] front: More care over device teardown.
1. We must ensure gnttab callbacks are disabled and all work
flushed before tearing down device state. A new gnttab interface
call is added for this purpose.
2. blkif_free() must check for a request_queue before deref'ing it.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 19 ++++++++++++++++++-
linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 15 +++++++++++++++
linux-2.6-xen-sparse/include/xen/gnttab.h | 1 +
3 files changed, 34 insertions(+), 1 deletion(-)
diff -r b0ba792f3935 -r 5552bc2c3716
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Jun 13
17:30:30 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Jun 14
11:19:53 2006 +0100
@@ -342,8 +342,20 @@ static void blkfront_closing(struct xenb
static void blkfront_closing(struct xenbus_device *dev)
{
struct blkfront_info *info = dev->dev.driver_data;
+ unsigned long flags;
DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
+
+ if (info->rq == NULL)
+ return;
+
+ spin_lock_irqsave(&blkif_io_lock, flags);
+ /* No more blkif_request(). */
+ blk_stop_queue(info->rq);
+ /* No more gnttab callback work. */
+ gnttab_cancel_free_callback(&info->callback);
+ flush_scheduled_work();
+ spin_unlock_irqrestore(&blkif_io_lock, flags);
xlvbd_del(info);
@@ -696,7 +708,12 @@ static void blkif_free(struct blkfront_i
spin_lock_irq(&blkif_io_lock);
info->connected = suspend ?
BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
- blk_stop_queue(info->rq); /* no more blkif_request() */
+ /* No more blkif_request(). */
+ if (info->rq)
+ blk_stop_queue(info->rq);
+ /* No more gnttab callback work. */
+ gnttab_cancel_free_callback(&info->callback);
+ flush_scheduled_work();
spin_unlock_irq(&blkif_io_lock);
/* Free resources associated with old device channel. */
diff -r b0ba792f3935 -r 5552bc2c3716
linux-2.6-xen-sparse/drivers/xen/core/gnttab.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Tue Jun 13 17:30:30
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Wed Jun 14 11:19:53
2006 +0100
@@ -334,6 +334,21 @@ out:
}
EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
+void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
+{
+ struct gnttab_free_callback **pcb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gnttab_list_lock, flags);
+ for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
+ if (*pcb == callback) {
+ *pcb = callback->next;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+
#ifndef __ia64__
static int map_pte_fn(pte_t *pte, struct page *pmd_page,
unsigned long addr, void *data)
diff -r b0ba792f3935 -r 5552bc2c3716 linux-2.6-xen-sparse/include/xen/gnttab.h
--- a/linux-2.6-xen-sparse/include/xen/gnttab.h Tue Jun 13 17:30:30 2006 +0100
+++ b/linux-2.6-xen-sparse/include/xen/gnttab.h Wed Jun 14 11:19:53 2006 +0100
@@ -100,6 +100,7 @@ void gnttab_release_grant_reference(gran
void gnttab_request_free_callback(struct gnttab_free_callback *callback,
void (*fn)(void *), void *arg, u16 count);
+void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
unsigned long frame, int readonly);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|