direct-io.hg

changeset 10346:5552bc2c3716

[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@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Jun 14 11:19:53 2006 +0100 (2006-06-14)
parents b0ba792f3935
children 8070050cc30f
files linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/core/gnttab.c linux-2.6-xen-sparse/include/xen/gnttab.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Tue Jun 13 17:30:30 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Wed Jun 14 11:19:53 2006 +0100
     1.3 @@ -342,9 +342,21 @@ static void connect(struct blkfront_info
     1.4  static void blkfront_closing(struct xenbus_device *dev)
     1.5  {
     1.6  	struct blkfront_info *info = dev->dev.driver_data;
     1.7 +	unsigned long flags;
     1.8  
     1.9  	DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
    1.10  
    1.11 +	if (info->rq == NULL)
    1.12 +		return;
    1.13 +
    1.14 +	spin_lock_irqsave(&blkif_io_lock, flags);
    1.15 +	/* No more blkif_request(). */
    1.16 +	blk_stop_queue(info->rq);
    1.17 +	/* No more gnttab callback work. */
    1.18 +	gnttab_cancel_free_callback(&info->callback);
    1.19 +	flush_scheduled_work();
    1.20 +	spin_unlock_irqrestore(&blkif_io_lock, flags);
    1.21 +
    1.22  	xlvbd_del(info);
    1.23  
    1.24  	xenbus_switch_state(dev, XenbusStateClosed);
    1.25 @@ -696,7 +708,12 @@ static void blkif_free(struct blkfront_i
    1.26  	spin_lock_irq(&blkif_io_lock);
    1.27  	info->connected = suspend ?
    1.28  		BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
    1.29 -	blk_stop_queue(info->rq); /* no more blkif_request() */
    1.30 +	/* No more blkif_request(). */
    1.31 +	if (info->rq)
    1.32 +		blk_stop_queue(info->rq);
    1.33 +	/* No more gnttab callback work. */
    1.34 +	gnttab_cancel_free_callback(&info->callback);
    1.35 +	flush_scheduled_work();
    1.36  	spin_unlock_irq(&blkif_io_lock);
    1.37  
    1.38  	/* Free resources associated with old device channel. */
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c	Tue Jun 13 17:30:30 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c	Wed Jun 14 11:19:53 2006 +0100
     2.3 @@ -334,6 +334,21 @@ out:
     2.4  }
     2.5  EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
     2.6  
     2.7 +void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
     2.8 +{
     2.9 +	struct gnttab_free_callback **pcb;
    2.10 +	unsigned long flags;
    2.11 +
    2.12 +	spin_lock_irqsave(&gnttab_list_lock, flags);
    2.13 +	for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
    2.14 +		if (*pcb == callback) {
    2.15 +			*pcb = callback->next;
    2.16 +			break;
    2.17 +		}
    2.18 +	}
    2.19 +	spin_unlock_irqrestore(&gnttab_list_lock, flags);
    2.20 +}
    2.21 +
    2.22  #ifndef __ia64__
    2.23  static int map_pte_fn(pte_t *pte, struct page *pmd_page,
    2.24  		      unsigned long addr, void *data)
     3.1 --- a/linux-2.6-xen-sparse/include/xen/gnttab.h	Tue Jun 13 17:30:30 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/include/xen/gnttab.h	Wed Jun 14 11:19:53 2006 +0100
     3.3 @@ -100,6 +100,7 @@ void gnttab_release_grant_reference(gran
     3.4  
     3.5  void gnttab_request_free_callback(struct gnttab_free_callback *callback,
     3.6  				  void (*fn)(void *), void *arg, u16 count);
     3.7 +void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
     3.8  
     3.9  void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
    3.10  				     unsigned long frame, int readonly);