ia64/xen-unstable

changeset 7887:f6fdb6e0d3c9

Fix race in blkfront resume path (watch thread could fire watch during the
(short-ish) time that we were in BLKIF_STATE_DISCONNECTED).

Signed-off-by: Steven Hand <steven@xensource.com>
author smh22@firebug.cl.cam.ac.uk
date Thu Nov 17 14:56:50 2005 +0100 (2005-11-17)
parents 51f91ef6c3b5
children 5b5f1b0aca33
files linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Thu Nov 17 13:32:05 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Thu Nov 17 14:56:50 2005 +0100
     1.3 @@ -57,6 +57,7 @@
     1.4  
     1.5  #define BLKIF_STATE_DISCONNECTED 0
     1.6  #define BLKIF_STATE_CONNECTED    1
     1.7 +#define BLKIF_STATE_SUSPENDED    2
     1.8  
     1.9  #define MAXIMUM_OUTSTANDING_BLOCK_REQS \
    1.10      (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
    1.11 @@ -75,7 +76,7 @@ static irqreturn_t blkif_int(int irq, vo
    1.12  static void blkif_restart_queue(void *arg);
    1.13  static void blkif_recover(struct blkfront_info *);
    1.14  static void blkif_completion(struct blk_shadow *);
    1.15 -static void blkif_free(struct blkfront_info *);
    1.16 +static void blkif_free(struct blkfront_info *, int);
    1.17  
    1.18  
    1.19  /**
    1.20 @@ -144,7 +145,7 @@ static int blkfront_resume(struct xenbus
    1.21  
    1.22  	DPRINTK("blkfront_resume: %s\n", dev->nodename);
    1.23  
    1.24 -	blkif_free(info);
    1.25 +	blkif_free(info, 1);
    1.26  
    1.27  	err = talk_to_backend(dev, info);
    1.28  	if (!err)
    1.29 @@ -207,7 +208,7 @@ again:
    1.30  	if (message)
    1.31  		xenbus_dev_fatal(dev, err, "%s", message);
    1.32   destroy_blkring:
    1.33 -	blkif_free(info);
    1.34 +	blkif_free(info, 0);
    1.35   out:
    1.36  	return err;
    1.37  }
    1.38 @@ -252,7 +253,7 @@ static int setup_blkring(struct xenbus_d
    1.39  
    1.40  	return 0;
    1.41  fail:
    1.42 -	blkif_free(info);
    1.43 +	blkif_free(info, 0);
    1.44  	return err;
    1.45  }
    1.46  
    1.47 @@ -295,7 +296,8 @@ static void connect(struct blkfront_info
    1.48  	unsigned int binfo;
    1.49  	int err;
    1.50  
    1.51 -        if (info->connected == BLKIF_STATE_CONNECTED)
    1.52 +        if( (info->connected == BLKIF_STATE_CONNECTED) || 
    1.53 +	    (info->connected == BLKIF_STATE_SUSPENDED) ) 
    1.54  		return;
    1.55  
    1.56  	DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend);
    1.57 @@ -354,7 +356,7 @@ static int blkfront_remove(struct xenbus
    1.58  
    1.59  	DPRINTK("blkfront_remove: %s removed\n", dev->nodename);
    1.60  
    1.61 -	blkif_free(info);
    1.62 +	blkif_free(info, 0);
    1.63  
    1.64  	kfree(info);
    1.65  
    1.66 @@ -569,6 +571,7 @@ void do_blkif_request(request_queue_t *r
    1.67  			req->nr_sectors, req->buffer,
    1.68  			rq_data_dir(req) ? "write" : "read");
    1.69  
    1.70 +
    1.71  		blkdev_dequeue_request(req);
    1.72  		if (blkif_queue_request(req)) {
    1.73  			blk_requeue_request(rq, req);
    1.74 @@ -643,11 +646,12 @@ static irqreturn_t blkif_int(int irq, vo
    1.75  	return IRQ_HANDLED;
    1.76  }
    1.77  
    1.78 -static void blkif_free(struct blkfront_info *info)
    1.79 +static void blkif_free(struct blkfront_info *info, int suspend)
    1.80  {
    1.81  	/* Prevent new requests being issued until we fix things up. */
    1.82  	spin_lock_irq(&blkif_io_lock);
    1.83 -	info->connected = BLKIF_STATE_DISCONNECTED;
    1.84 +	info->connected = suspend ? 
    1.85 +		BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; 
    1.86  	spin_unlock_irq(&blkif_io_lock);
    1.87  
    1.88  	/* Free resources associated with old device channel. */