ia64/linux-2.6.18-xen.hg

changeset 589:920abc7b20ac

pvSCSI: Fix many points of backend/frontend driver

Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 03 13:36:53 2008 +0100 (2008-07-03)
parents 9c4a15e54814
children c4134d1a3e3f
files drivers/xen/scsiback/common.h drivers/xen/scsiback/interface.c drivers/xen/scsiback/scsiback.c drivers/xen/scsiback/translate.c drivers/xen/scsiback/xenbus.c drivers/xen/scsifront/scsifront.c drivers/xen/scsifront/xenbus.c
line diff
     1.1 --- a/drivers/xen/scsiback/common.h	Thu Jul 03 13:35:40 2008 +0100
     1.2 +++ b/drivers/xen/scsiback/common.h	Thu Jul 03 13:36:53 2008 +0100
     1.3 @@ -92,7 +92,7 @@ struct vscsibk_info {
     1.4  	grant_ref_t shmem_ref;
     1.5  
     1.6  	spinlock_t ring_lock;
     1.7 -	atomic_t refcnt;
     1.8 +	atomic_t nr_unreplied_reqs;
     1.9  
    1.10  	spinlock_t v2p_lock;
    1.11  	struct list_head v2p_entry_lists;
    1.12 @@ -133,10 +133,10 @@ typedef struct {
    1.13  
    1.14  
    1.15  
    1.16 -#define scsiback_get(_b) (atomic_inc(&(_b)->refcnt))
    1.17 +#define scsiback_get(_b) (atomic_inc(&(_b)->nr_unreplied_reqs))
    1.18  #define scsiback_put(_b)				\
    1.19  	do {						\
    1.20 -		if (atomic_dec_and_test(&(_b)->refcnt))	\
    1.21 +		if (atomic_dec_and_test(&(_b)->nr_unreplied_reqs))	\
    1.22  			wake_up(&(_b)->waiting_to_free);\
    1.23  	} while (0)
    1.24  
     2.1 --- a/drivers/xen/scsiback/interface.c	Thu Jul 03 13:35:40 2008 +0100
     2.2 +++ b/drivers/xen/scsiback/interface.c	Thu Jul 03 13:36:53 2008 +0100
     2.3 @@ -52,7 +52,7 @@ struct vscsibk_info *vscsibk_info_alloc(
     2.4  	memset(info, 0, sizeof(*info));
     2.5  	info->domid = domid;
     2.6  	spin_lock_init(&info->ring_lock);
     2.7 -	atomic_set(&info->refcnt, 1);
     2.8 +	atomic_set(&info->nr_unreplied_reqs, 0);
     2.9  	init_waitqueue_head(&info->wq);
    2.10  	init_waitqueue_head(&info->waiting_to_free);
    2.11  
    2.12 @@ -104,7 +104,7 @@ int scsiback_init_sring(struct vscsibk_i
    2.13  
    2.14  	if (info->irq) {
    2.15  		printk(KERN_ERR "scsiback: Already connected through?\n");
    2.16 -		return 0;
    2.17 +		return -1;
    2.18  	}
    2.19  
    2.20  	info->ring_area = alloc_vm_area(PAGE_SIZE);
    2.21 @@ -126,7 +126,7 @@ int scsiback_init_sring(struct vscsibk_i
    2.22  		goto unmap_page;
    2.23  		
    2.24  	info->irq = err;
    2.25 -	
    2.26 +
    2.27  	return 0;
    2.28  
    2.29  unmap_page:
    2.30 @@ -144,9 +144,8 @@ void scsiback_disconnect(struct vscsibk_
    2.31  		info->kthread = NULL;
    2.32  	}
    2.33  
    2.34 -	atomic_dec(&info->refcnt);
    2.35 -	wait_event(info->waiting_to_free, atomic_read(&info->refcnt) == 0);
    2.36 -	atomic_inc(&info->refcnt);
    2.37 +	wait_event(info->waiting_to_free, 
    2.38 +		atomic_read(&info->nr_unreplied_reqs) == 0);
    2.39  
    2.40  	if (info->irq) {
    2.41  		unbind_from_irqhandler(info->irq, info);
    2.42 @@ -162,8 +161,7 @@ void scsiback_disconnect(struct vscsibk_
    2.43  
    2.44  void scsiback_free(struct vscsibk_info *info)
    2.45  {
    2.46 -	if (atomic_dec_and_test(&info->refcnt))
    2.47 -		kmem_cache_free(scsiback_cachep, info);
    2.48 +	kmem_cache_free(scsiback_cachep, info);
    2.49  }
    2.50  
    2.51  int __init scsiback_interface_init(void)
     3.1 --- a/drivers/xen/scsiback/scsiback.c	Thu Jul 03 13:35:40 2008 +0100
     3.2 +++ b/drivers/xen/scsiback/scsiback.c	Thu Jul 03 13:36:53 2008 +0100
     3.3 @@ -56,6 +56,8 @@ int vscsiif_reqs = VSCSIIF_BACK_MAX_PEND
     3.4  module_param_named(reqs, vscsiif_reqs, int, 0);
     3.5  MODULE_PARM_DESC(reqs, "Number of scsiback requests to allocate");
     3.6  
     3.7 +static unsigned int log_print_stat = 0;
     3.8 +module_param(log_print_stat, int, 0644);
     3.9  
    3.10  #define SCSIBACK_INVALID_HANDLE (~0)
    3.11  
    3.12 @@ -154,7 +156,6 @@ void scsiback_do_resp_with_sense(char *s
    3.13  
    3.14  	spin_lock_irqsave(&info->ring_lock, flags);
    3.15  
    3.16 -	rmb();
    3.17  	ring_res = RING_GET_RESPONSE(&info->ring, info->ring.rsp_prod_pvt);
    3.18  	info->ring.rsp_prod_pvt++;
    3.19  
    3.20 @@ -184,49 +185,53 @@ void scsiback_do_resp_with_sense(char *s
    3.21  	if (notify)
    3.22  		notify_remote_via_irq(info->irq);
    3.23  
    3.24 -	scsiback_put(pending_req->info);
    3.25  	free_req(pending_req);
    3.26  }
    3.27  
    3.28 +static void scsiback_print_status(char *sense_buffer, int errors,
    3.29 +					pending_req_t *pending_req)
    3.30 +{
    3.31 +	struct scsi_device *sdev = pending_req->sdev;
    3.32 +	
    3.33 +	printk(KERN_ERR "scsiback: %d:%d:%d:%d ",sdev->host->host_no,
    3.34 +			sdev->channel, sdev->id, sdev->lun);
    3.35 +	printk(KERN_ERR "status = 0x%02x, message = 0x%02x, host = 0x%02x, driver = 0x%02x\n",
    3.36 +			status_byte(errors), msg_byte(errors),
    3.37 +			host_byte(errors), driver_byte(errors));
    3.38 +
    3.39 +	printk(KERN_ERR "scsiback: cmnd[0]=0x%02X\n",
    3.40 +			pending_req->cmnd[0]);
    3.41 +
    3.42 +	if (CHECK_CONDITION & status_byte(errors))
    3.43 +		__scsi_print_sense("scsiback", sense_buffer, SCSI_SENSE_BUFFERSIZE);
    3.44 +}
    3.45 +
    3.46 +
    3.47  #ifdef NO_ASYNC /*!async*/
    3.48  static void scsiback_cmd_done(struct request *req, int errors)
    3.49  {
    3.50  	pending_req_t *pending_req = req->end_io_data;
    3.51 -	struct scsi_device *sdev = pending_req->sdev;
    3.52  	unsigned char *sense_buffer;
    3.53  
    3.54  	sense_buffer = req->sense;
    3.55 -
    3.56  #else
    3.57  static void scsiback_cmd_done(void *data, char *sense_buffer,
    3.58  				int errors, int resid)
    3.59  {
    3.60  	pending_req_t *pending_req = data;
    3.61  	struct scsi_device *sdev = pending_req->sdev;
    3.62 -
    3.63 -	DPRINTK("%s\n",__FUNCTION__);
    3.64  #endif
    3.65  
    3.66 -	if ((errors != 0) && (pending_req->cmnd[0] != TEST_UNIT_READY)) {
    3.67 -
    3.68 -		printk(KERN_ERR "scsiback: %d:%d:%d:%d ",sdev->host->host_no,
    3.69 -				sdev->channel, sdev->id, sdev->lun);
    3.70 -		printk(KERN_ERR "status = 0x%02x, message = 0x%02x, host = 0x%02x, driver = 0x%02x\n",
    3.71 -				status_byte(errors), msg_byte(errors),
    3.72 -				host_byte(errors), driver_byte(errors));
    3.73 -
    3.74 -		printk(KERN_ERR "scsiback: cmnd[0]=0x%02X nr_segments=%d\n",
    3.75 -				pending_req->cmnd[0],
    3.76 -				pending_req->nr_segments);
    3.77 -
    3.78 -		if (CHECK_CONDITION & status_byte(errors))
    3.79 -			__scsi_print_sense("scsiback", sense_buffer, SCSI_SENSE_BUFFERSIZE);
    3.80 +	if (errors != 0) {
    3.81 +		if (log_print_stat)
    3.82 +			scsiback_print_status(sense_buffer, errors, pending_req);
    3.83  	}
    3.84  
    3.85  	scsiback_rsp_emulation(pending_req);
    3.86 +
    3.87  	scsiback_fast_flush_area(pending_req);
    3.88  	scsiback_do_resp_with_sense(sense_buffer, errors, pending_req);
    3.89 -
    3.90 +	scsiback_put(pending_req->info);
    3.91  
    3.92  #ifdef NO_ASYNC /*!async*/
    3.93  	__blk_put_request(req->q, req);
    3.94 @@ -305,7 +310,6 @@ fail_flush:
    3.95  	return -ENOMEM;
    3.96  }
    3.97  
    3.98 -
    3.99  #ifdef NO_ASYNC /*!async*/
   3.100  
   3.101  /* quoted scsi_lib.c/scsi_merge_bio */
   3.102 @@ -347,7 +351,7 @@ static int scsiback_bi_endio(struct bio 
   3.103  
   3.104  
   3.105  /* quoted scsi_lib.c/scsi_req_map_sg . */
   3.106 -static int requset_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count)
   3.107 +static int request_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count)
   3.108  {
   3.109  	struct request_queue *q = rq->q;
   3.110  	int nr_pages;
   3.111 @@ -422,16 +426,16 @@ free_bios:
   3.112  
   3.113  void scsiback_cmd_exec(pending_req_t *pending_req)
   3.114  {
   3.115 -	int err;
   3.116 -
   3.117  	int cmd_len  = (int)pending_req->cmd_len;
   3.118  	int data_dir = (int)pending_req->sc_data_direction;
   3.119  	unsigned int nr_segments = (unsigned int)pending_req->nr_segments;
   3.120  	unsigned int timeout;
   3.121 +
   3.122  #ifdef NO_ASYNC /*!async*/
   3.123  	struct request *rq;
   3.124  	int write;
   3.125  #else
   3.126 +	int err = 0;
   3.127  	unsigned int data_len = pending_req->request_bufflen;
   3.128  #endif
   3.129  
   3.130 @@ -439,12 +443,11 @@ void scsiback_cmd_exec(pending_req_t *pe
   3.131  
   3.132  	/* because it doesn't timeout backend earlier than frontend.*/
   3.133  	if (pending_req->timeout_per_command)
   3.134 -		timeout = (pending_req->timeout_per_command * HZ * 2);
   3.135 +		timeout = pending_req->timeout_per_command * HZ;
   3.136  	else
   3.137  		timeout = VSCSIIF_TIMEOUT;
   3.138  
   3.139  #ifdef NO_ASYNC /*!async*/
   3.140 -	err = 0;
   3.141  	write = (data_dir == DMA_TO_DEVICE);
   3.142  	rq = blk_get_request(pending_req->sdev->request_queue, write, GFP_KERNEL);
   3.143  
   3.144 @@ -456,31 +459,33 @@ void scsiback_cmd_exec(pending_req_t *pe
   3.145  	rq->sense       = pending_req->sense_buffer;
   3.146  	rq->sense_len = 0;
   3.147  
   3.148 +	/* not allowed to retry in backend.                   */
   3.149  	rq->retries   = 0;
   3.150  	rq->timeout   = timeout;
   3.151  	rq->end_io_data = pending_req;
   3.152  
   3.153  	if (nr_segments) {
   3.154  
   3.155 -		if (requset_map_sg(rq, pending_req, nr_segments)) {
   3.156 +		if (request_map_sg(rq, pending_req, nr_segments)) {
   3.157  			printk(KERN_ERR "scsiback: SG Request Map Error\n");
   3.158  			return;
   3.159  		}
   3.160  	}
   3.161  
   3.162 +	scsiback_get(pending_req->info);
   3.163  	blk_execute_rq_nowait(rq->q, NULL, rq, 1, scsiback_cmd_done);
   3.164 +#else   /*async*/
   3.165  
   3.166 -#else   /*async*/
   3.167 -	/* not allowed to retry in backend.                   */
   3.168 -	/* timeout of backend is longer than that of brontend.*/
   3.169 +	scsiback_get(pending_req->info);
   3.170  	err = scsi_execute_async(pending_req->sdev, &(pending_req->cmnd[0]),
   3.171 -		cmd_len, data_dir, &(pending_req->sgl[0]), data_len, nr_segments, timeout, 0,
   3.172 -		pending_req, scsiback_cmd_done, GFP_ATOMIC);
   3.173 -		
   3.174 -#endif /*!async*/
   3.175 +		cmd_len, data_dir, pending_req->sgl, data_len, nr_segments, timeout, 0,
   3.176 +		pending_req, scsiback_cmd_done, GFP_KERNEL);
   3.177  
   3.178 -	if (err) 
   3.179 +	if (err) {
   3.180  		scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24), pending_req);
   3.181 +	}
   3.182 +
   3.183 +#endif    /*async*/
   3.184  
   3.185  	return ;
   3.186  }
   3.187 @@ -493,12 +498,11 @@ static void scsiback_device_reset_exec(p
   3.188  	struct scsi_device *sdev = pending_req->sdev;
   3.189  
   3.190  	scsiback_get(info);
   3.191 -
   3.192  	err = scsi_reset_provider(sdev, SCSI_TRY_RESET_DEVICE);
   3.193  
   3.194  	scsiback_do_resp_with_sense(NULL, err, pending_req);
   3.195 +	scsiback_put(info);
   3.196  
   3.197 -	notify_remote_via_irq(info->irq);
   3.198  	return;
   3.199  }
   3.200  
   3.201 @@ -530,7 +534,7 @@ static int prepare_pending_reqs(struct v
   3.202  	sdev = scsiback_do_translation(info, &vir);
   3.203  	if (!sdev) {
   3.204  		pending_req->sdev = NULL;
   3.205 -		printk(KERN_ERR "scsiback: doesn't exist.\n");
   3.206 +		DPRINTK("scsiback: doesn't exist.\n");
   3.207  		err = -ENODEV;
   3.208  		goto invald_value;
   3.209  	}
   3.210 @@ -541,14 +545,14 @@ static int prepare_pending_reqs(struct v
   3.211  		(ring_req->sc_data_direction != DMA_TO_DEVICE) &&
   3.212  		(ring_req->sc_data_direction != DMA_FROM_DEVICE) &&
   3.213  		(ring_req->sc_data_direction != DMA_NONE)) {
   3.214 -		printk(KERN_ERR "scsiback: invalid parameter data_dir = %d\n",
   3.215 +		DPRINTK("scsiback: invalid parameter data_dir = %d\n",
   3.216  			ring_req->sc_data_direction);
   3.217  		err = -EINVAL;
   3.218  		goto invald_value;
   3.219  	}
   3.220  
   3.221  	if (ring_req->nr_segments > VSCSIIF_SG_TABLESIZE) {
   3.222 -		printk(KERN_ERR "scsiback: invalid parameter nr_seg = %d\n",
   3.223 +		DPRINTK("scsiback: invalid parameter nr_seg = %d\n",
   3.224  			ring_req->nr_segments);
   3.225  		err = -EINVAL;
   3.226  		goto invald_value;
   3.227 @@ -556,7 +560,7 @@ static int prepare_pending_reqs(struct v
   3.228  	pending_req->nr_segments = ring_req->nr_segments;
   3.229  
   3.230  	if (ring_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
   3.231 -		printk(KERN_ERR "scsiback: invalid parameter cmd_len = %d\n",
   3.232 +		DPRINTK("scsiback: invalid parameter cmd_len = %d\n",
   3.233  			ring_req->cmd_len);
   3.234  		err = -EINVAL;
   3.235  		goto invald_value;
   3.236 @@ -568,7 +572,7 @@ static int prepare_pending_reqs(struct v
   3.237  	pending_req->timeout_per_command = ring_req->timeout_per_command;
   3.238  
   3.239  	if(scsiback_gnttab_data_map(ring_req, pending_req)) {
   3.240 -		printk(KERN_ERR "scsiback: invalid buffer\n");
   3.241 +		DPRINTK("scsiback: invalid buffer\n");
   3.242  		err = -EINVAL;
   3.243  		goto invald_value;
   3.244  	}
   3.245 @@ -607,7 +611,6 @@ static int scsiback_do_cmd_fn(struct vsc
   3.246  		ring_req = RING_GET_REQUEST(ring, rc);
   3.247  		ring->req_cons = ++rc;
   3.248  
   3.249 -		scsiback_get(info);
   3.250  		err = prepare_pending_reqs(info, ring_req,
   3.251  						pending_req);
   3.252  		if (err == -EINVAL) {
   3.253 @@ -616,7 +619,8 @@ static int scsiback_do_cmd_fn(struct vsc
   3.254  			continue;
   3.255  		} else if (err == -ENODEV) {
   3.256  			scsiback_do_resp_with_sense(NULL, (DID_NO_CONNECT << 16),
   3.257 -				pending_req);			
   3.258 +				pending_req);
   3.259 +			continue;
   3.260  		}
   3.261  
   3.262  		if (pending_req->act == VSCSIIF_ACT_SCSI_CDB) {
   3.263 @@ -634,6 +638,9 @@ static int scsiback_do_cmd_fn(struct vsc
   3.264  	if (RING_HAS_UNCONSUMED_REQUESTS(ring))
   3.265  		more_to_do = 1;
   3.266  
   3.267 +	/* Yield point for this unbounded loop. */
   3.268 +	cond_resched();
   3.269 +
   3.270  	return more_to_do;
   3.271  }
   3.272  
   3.273 @@ -644,8 +651,6 @@ int scsiback_schedule(void *data)
   3.274  
   3.275  	DPRINTK("%s\n",__FUNCTION__);
   3.276  
   3.277 -	scsiback_get(info);
   3.278 -
   3.279  	while (!kthread_should_stop()) {
   3.280  		wait_event_interruptible(
   3.281  			info->wq,
   3.282 @@ -661,9 +666,6 @@ int scsiback_schedule(void *data)
   3.283  			info->waiting_reqs = 1;
   3.284  	}
   3.285  
   3.286 -	info->kthread = NULL;
   3.287 -	scsiback_put(info);
   3.288 -
   3.289  	return 0;
   3.290  }
   3.291  
     4.1 --- a/drivers/xen/scsiback/translate.c	Thu Jul 03 13:35:40 2008 +0100
     4.2 +++ b/drivers/xen/scsiback/translate.c	Thu Jul 03 13:36:53 2008 +0100
     4.3 @@ -71,14 +71,14 @@ int scsiback_add_translation_entry(struc
     4.4  	}
     4.5  
     4.6  	/* Create a new translation entry and add to the list */
     4.7 -	if ((new = kmalloc(sizeof(struct v2p_entry), GFP_KERNEL)) == NULL) {
     4.8 +	if ((new = kmalloc(sizeof(struct v2p_entry), GFP_ATOMIC)) == NULL) {
     4.9  		printk(KERN_ERR "scsiback: %s: kmalloc() error.\n", __FUNCTION__);
    4.10  		err = -ENOMEM;
    4.11  		goto out;
    4.12  	}
    4.13  	new->v = *v;
    4.14  	new->sdev = sdev;
    4.15 -	list_add(&new->l, head);
    4.16 +	list_add_tail(&new->l, head);
    4.17  
    4.18  out:	
    4.19  	spin_unlock_irqrestore(&info->v2p_lock, flags);
    4.20 @@ -111,6 +111,7 @@ int scsiback_del_translation_entry(struc
    4.21  
    4.22  found:
    4.23  	/* Delete the translation entry specfied */
    4.24 +	scsi_device_put(entry->sdev);
    4.25  	list_del(&entry->l);
    4.26  	kfree(entry);
    4.27  
    4.28 @@ -156,6 +157,7 @@ void scsiback_release_translation_entry(
    4.29  
    4.30  	spin_lock_irqsave(&info->v2p_lock, flags);
    4.31  	list_for_each_entry_safe(entry, tmp, head, l) {
    4.32 +		scsi_device_put(entry->sdev);
    4.33  		list_del(&entry->l);
    4.34  		kfree(entry);
    4.35  	}
     5.1 --- a/drivers/xen/scsiback/xenbus.c	Thu Jul 03 13:35:40 2008 +0100
     5.2 +++ b/drivers/xen/scsiback/xenbus.c	Thu Jul 03 13:36:53 2008 +0100
     5.3 @@ -113,11 +113,42 @@ struct scsi_device *scsiback_get_scsi_de
     5.4  		goto invald_value;
     5.5  	}
     5.6  
     5.7 +	scsi_host_put(shost);
     5.8  invald_value:
     5.9  	return (sdev);
    5.10  }
    5.11  
    5.12  #define VSCSIBACK_OP_ADD_OR_DEL_LUN	1
    5.13 +#define VSCSIBACK_OP_UPDATEDEV_STATE	2
    5.14 +
    5.15 +static int scsiback_change_device_state(struct xenbus_device *dev,
    5.16 +			char *state_path, enum xenbus_state set_state)
    5.17 +{
    5.18 +	struct xenbus_transaction tr;
    5.19 +	int err;
    5.20 +	
    5.21 +	do {
    5.22 +		err = xenbus_transaction_start(&tr);
    5.23 +		if (err != 0) { 
    5.24 +			printk(KERN_ERR "scsiback: transaction start failed\n");
    5.25 +			return err;
    5.26 +		}
    5.27 +		err = xenbus_printf(tr, dev->nodename, state_path, 
    5.28 +				    "%d", set_state);
    5.29 +		if (err != 0) {
    5.30 +			printk(KERN_ERR "scsiback: xenbus_printf failed\n");
    5.31 +			xenbus_transaction_end(tr, 1);
    5.32 +			return err;
    5.33 +		}
    5.34 +		err = xenbus_transaction_end(tr, 0);
    5.35 +	} while (err == -EAGAIN);
    5.36 +	
    5.37 +	if (err != 0) {
    5.38 +		printk(KERN_ERR "scsiback: failed to end %s.\n", __FUNCTION__);
    5.39 +		return err;
    5.40 +	}
    5.41 +	return 0;	
    5.42 +}
    5.43  
    5.44  static void scsiback_do_lun_hotplug(struct backend_info *be, int op)
    5.45  {
    5.46 @@ -132,12 +163,7 @@ static void scsiback_do_lun_hotplug(stru
    5.47  	struct xenbus_transaction xbt;
    5.48  
    5.49  
    5.50 -	err = xenbus_transaction_start(&xbt);
    5.51 -	if (err) {
    5.52 -		xenbus_dev_fatal(dev, err, "starting transaction");
    5.53 -	}
    5.54 -
    5.55 -	dir = xenbus_directory(xbt, dev->nodename, "vscsi-devs", &dir_n);
    5.56 +	dir = xenbus_directory(XBT_NIL, dev->nodename, "vscsi-devs", &dir_n);
    5.57  	if (IS_ERR(dir))
    5.58  		return;
    5.59  
    5.60 @@ -145,14 +171,14 @@ static void scsiback_do_lun_hotplug(stru
    5.61  		
    5.62  		/* read status */
    5.63  		snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]);
    5.64 -		err = xenbus_scanf(xbt, dev->nodename, state_str, "%u",
    5.65 +		err = xenbus_scanf(XBT_NIL, dev->nodename, state_str, "%u",
    5.66  			&device_state);
    5.67  		if (XENBUS_EXIST_ERR(err))
    5.68  			continue;
    5.69  
    5.70  		/* physical SCSI device */
    5.71  		snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", dir[i]);
    5.72 -		err = xenbus_scanf(xbt, dev->nodename, str,
    5.73 +		err = xenbus_scanf(XBT_NIL, dev->nodename, str,
    5.74  			"%u:%u:%u:%u", &phy.hst, &phy.chn, &phy.tgt, &phy.lun);
    5.75  		if (XENBUS_EXIST_ERR(err)) {
    5.76  			xenbus_printf(xbt, dev->nodename, state_str,
    5.77 @@ -162,7 +188,7 @@ static void scsiback_do_lun_hotplug(stru
    5.78  
    5.79  		/* virtual SCSI device */
    5.80  		snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]);
    5.81 -		err = xenbus_scanf(xbt, dev->nodename, str,
    5.82 +		err = xenbus_scanf(XBT_NIL, dev->nodename, str,
    5.83  			"%u:%u:%u:%u", &vir.hst, &vir.chn, &vir.tgt, &vir.lun);
    5.84  		if (XENBUS_EXIST_ERR(err)) {
    5.85  			xenbus_printf(xbt, dev->nodename, state_str,
    5.86 @@ -175,16 +201,22 @@ static void scsiback_do_lun_hotplug(stru
    5.87  			if (device_state == XenbusStateInitialising) {
    5.88  				sdev = scsiback_get_scsi_device(&phy);
    5.89  				if (!sdev) {
    5.90 -					xenbus_printf(xbt, dev->nodename, state_str,
    5.91 -							"%d", XenbusStateClosing);
    5.92 +					err = scsiback_change_device_state(dev,
    5.93 +						state_str, XenbusStateClosing);
    5.94 +					if (err)
    5.95 +						goto fail;
    5.96  				} else {
    5.97  					err = scsiback_add_translation_entry(be->info, sdev, &vir);
    5.98  					if (!err) {
    5.99 -						xenbus_printf(xbt, dev->nodename, state_str,
   5.100 -							"%d", XenbusStateInitialised);
   5.101 +						err = scsiback_change_device_state(dev,
   5.102 +							state_str, XenbusStateInitialised);
   5.103 +						if (err)
   5.104 +							goto fail;
   5.105  					} else {
   5.106 -						xenbus_printf(xbt, dev->nodename, state_str,
   5.107 -							"%d", XenbusStateClosing);						
   5.108 +						err = scsiback_change_device_state(dev,
   5.109 +							state_str, XenbusStateClosing);
   5.110 +						if (err)
   5.111 +							goto fail;
   5.112  					}
   5.113  				}
   5.114  			}
   5.115 @@ -194,11 +226,22 @@ static void scsiback_do_lun_hotplug(stru
   5.116  				if (err)
   5.117  					goto fail;
   5.118  				else {
   5.119 -					xenbus_printf(xbt, dev->nodename, state_str,
   5.120 -						"%d", XenbusStateClosed);						
   5.121 +					err = scsiback_change_device_state(dev,
   5.122 +						state_str, XenbusStateClosed);
   5.123 +					if (err)
   5.124 +						goto fail;
   5.125  				}
   5.126  			}
   5.127 +			break;
   5.128  
   5.129 +		case VSCSIBACK_OP_UPDATEDEV_STATE:
   5.130 +			if (device_state == XenbusStateInitialised) {
   5.131 +				/* modify vscsi-devs/dev-x/state */
   5.132 +				err = scsiback_change_device_state(dev,
   5.133 +					state_str, XenbusStateConnected);
   5.134 +				if (err)
   5.135 +					goto fail;
   5.136 +			}
   5.137  			break;
   5.138  		/*When it is necessary, processing is added here.*/
   5.139  		default:
   5.140 @@ -206,11 +249,9 @@ static void scsiback_do_lun_hotplug(stru
   5.141  		}
   5.142  	}
   5.143  
   5.144 -	xenbus_transaction_end(xbt, 0);
   5.145  	kfree(dir);
   5.146  	return ;
   5.147  fail :
   5.148 -	xenbus_transaction_end(xbt, 1);
   5.149  	kfree(dir);
   5.150  	xenbus_dev_fatal(dev, err, "read or write %s ", str);
   5.151  	return;
   5.152 @@ -232,19 +273,18 @@ static void scsiback_frontend_changed(st
   5.153  			break;
   5.154  
   5.155  		scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN);
   5.156 -		err = xenbus_switch_state(dev, XenbusStateConnected);
   5.157 -		if (err)
   5.158 -			xenbus_dev_fatal(dev, err, "switching to Connected state",
   5.159 -					dev->nodename);
   5.160 +		xenbus_switch_state(dev, XenbusStateConnected);
   5.161 +
   5.162  		break;
   5.163  	case XenbusStateConnected:
   5.164 +
   5.165 +		scsiback_do_lun_hotplug(be, VSCSIBACK_OP_UPDATEDEV_STATE);
   5.166 +
   5.167  		if (dev->state == XenbusStateConnected)
   5.168  			break;
   5.169 -			
   5.170 -		err = xenbus_switch_state(dev, XenbusStateConnected);
   5.171 -		if (err)
   5.172 -			xenbus_dev_fatal(dev, err, "switching to Connected state",
   5.173 -					dev->nodename);
   5.174 +
   5.175 +		xenbus_switch_state(dev, XenbusStateConnected);
   5.176 +
   5.177  		break;
   5.178  
   5.179  	case XenbusStateClosing:
   5.180 @@ -256,18 +296,18 @@ static void scsiback_frontend_changed(st
   5.181  		xenbus_switch_state(dev, XenbusStateClosed);
   5.182  		if (xenbus_dev_is_online(dev))
   5.183  			break;
   5.184 +		/* fall through if not online */
   5.185 +	case XenbusStateUnknown:
   5.186 +		device_unregister(&dev->dev);
   5.187 +		break;
   5.188  
   5.189  	case XenbusStateReconfiguring:
   5.190  		scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN);
   5.191 -		err = xenbus_switch_state(dev, XenbusStateReconfigured);
   5.192 -		if (err)
   5.193 -			xenbus_dev_fatal(dev, err, "switching to Reconfigured state",
   5.194 -					dev->nodename);
   5.195 +
   5.196 +		xenbus_switch_state(dev, XenbusStateReconfigured);
   5.197 +
   5.198  		break;
   5.199  
   5.200 -	case XenbusStateUnknown:
   5.201 -		device_unregister(&dev->dev);
   5.202 -		break;
   5.203  	default:
   5.204  		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
   5.205  					frontend_state);
     6.1 --- a/drivers/xen/scsifront/scsifront.c	Thu Jul 03 13:35:40 2008 +0100
     6.2 +++ b/drivers/xen/scsifront/scsifront.c	Thu Jul 03 13:36:53 2008 +0100
     6.3 @@ -216,6 +216,10 @@ int scsifront_cmd_done(struct vscsifrnt_
     6.4  
     6.5  	spin_unlock_irqrestore(&info->io_lock, flags);
     6.6  
     6.7 +
     6.8 +	/* Yield point for this unbounded loop. */
     6.9 +	cond_resched();
    6.10 +
    6.11  	return more_to_do;
    6.12  }
    6.13  
    6.14 @@ -238,8 +242,6 @@ int scsifront_schedule(void *data)
    6.15  			info->waiting_resp = 1;
    6.16  	}
    6.17  
    6.18 -	info->kthread = NULL;
    6.19 -
    6.20  	return 0;
    6.21  }
    6.22  
     7.1 --- a/drivers/xen/scsifront/xenbus.c	Thu Jul 03 13:35:40 2008 +0100
     7.2 +++ b/drivers/xen/scsifront/xenbus.c	Thu Jul 03 13:36:53 2008 +0100
     7.3 @@ -44,8 +44,13 @@ static void scsifront_free(struct vscsif
     7.4  {
     7.5  	struct Scsi_Host *host = info->host;
     7.6  
     7.7 -	if (scsi_host_get(host) != NULL)
     7.8 -		scsi_host_put(host);
     7.9 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
    7.10 +	if (host->shost_state != SHOST_DEL) {
    7.11 +#else
    7.12 +	if (!test_bit(SHOST_DEL, &host->shost_state)) {
    7.13 +#endif
    7.14 +		scsi_remove_host(info->host);
    7.15 +	}
    7.16  
    7.17  	if (info->ring_ref != GRANT_INVALID_REF) {
    7.18  		gnttab_end_foreign_access(info->ring_ref,
    7.19 @@ -57,6 +62,8 @@ static void scsifront_free(struct vscsif
    7.20  	if (info->irq)
    7.21  		unbind_from_irqhandler(info->irq, info);
    7.22  	info->irq = 0;
    7.23 +
    7.24 +	scsi_host_put(info->host);
    7.25  }
    7.26  
    7.27  
    7.28 @@ -141,25 +148,19 @@ again:
    7.29  		goto fail;
    7.30  	}
    7.31  
    7.32 -	err = xenbus_printf(xbt, dev->nodename, "vhostno", "%u",
    7.33 -				info->host->host_no);
    7.34 -	if (err) {
    7.35 -		xenbus_dev_fatal(dev, err, "%s", "writing vhostno");
    7.36 -		goto fail;
    7.37 -	}
    7.38 -
    7.39  	err = xenbus_transaction_end(xbt, 0);
    7.40  	if (err) {
    7.41  		if (err == -EAGAIN)
    7.42  			goto again;
    7.43  		xenbus_dev_fatal(dev, err, "completing transaction");
    7.44 -	} else
    7.45 -		xenbus_switch_state(dev, XenbusStateInitialised);
    7.46 +		goto free_sring;
    7.47 +	}
    7.48  
    7.49  	return 0;
    7.50  
    7.51  fail:
    7.52  	xenbus_transaction_end(xbt, 1);
    7.53 +free_sring:
    7.54  	/* free resource */
    7.55  	scsifront_free(info);
    7.56  	
    7.57 @@ -212,33 +213,29 @@ static int scsifront_probe(struct xenbus
    7.58  	if (IS_ERR(info->kthread)) {
    7.59  		err = PTR_ERR(info->kthread);
    7.60  		info->kthread = NULL;
    7.61 +		printk(KERN_ERR "scsifront: kthread start err %d\n", err);
    7.62 +		goto free_sring;
    7.63  	}
    7.64  
    7.65  	host->max_id      = VSCSIIF_MAX_TARGET;
    7.66  	host->max_channel = 0;
    7.67  	host->max_lun     = VSCSIIF_MAX_LUN;
    7.68 -	host->max_sectors = (VSCSIIF_SG_TABLESIZE * PAGE_SIZE / 512);
    7.69 +	host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512;
    7.70  
    7.71  	err = scsi_add_host(host, &dev->dev);
    7.72  	if (err) {
    7.73  		printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err);
    7.74 -		return err;
    7.75 +		goto free_sring;
    7.76  	}
    7.77  
    7.78  	xenbus_switch_state(dev, XenbusStateInitialised);
    7.79  
    7.80 - #if 0
    7.81 -	/* All SCSI device scan */
    7.82 -	scsi_scan_host(host);
    7.83 +	return 0;
    7.84  
    7.85 -	err = xenbus_printf(XBT_NIL, dev->nodename, "hotplug-status", "%s",
    7.86 -								"connected");
    7.87 -	if (err) {
    7.88 -		xenbus_dev_fatal(dev, err, "%s", "writing hotplug-status");
    7.89 -		return err;
    7.90 -	}
    7.91 - #endif
    7.92 -	return 0;
    7.93 +free_sring:
    7.94 +	/* free resource */
    7.95 +	scsifront_free(info);
    7.96 +	return err;
    7.97  }
    7.98  
    7.99  static int scsifront_remove(struct xenbus_device *dev)
   7.100 @@ -263,26 +260,15 @@ static int scsifront_disconnect(struct v
   7.101  	struct xenbus_device *dev = info->dev;
   7.102  	struct Scsi_Host *host = info->host;
   7.103  
   7.104 -	unsigned long flags;
   7.105 -
   7.106  	DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename);
   7.107  
   7.108 -	spin_lock_irqsave(host->host_lock, flags);
   7.109 -	while (RING_HAS_UNCONSUMED_RESPONSES(&info->ring)) {
   7.110 -		if (!scsifront_cmd_done(info))
   7.111 -			break;
   7.112 -	}
   7.113 -
   7.114 -	spin_unlock_irqrestore(host->host_lock, flags);
   7.115 -
   7.116 -	spin_lock(&info->io_lock);
   7.117 +	/* 
   7.118 +	  When this function is executed,  all devices of 
   7.119 +	  Frontend have been deleted. 
   7.120 +	  Therefore, it need not block I/O before remove_host.
   7.121 +	*/
   7.122  
   7.123  	scsi_remove_host(host);
   7.124 -	scsi_host_put(host);
   7.125 -
   7.126 -	spin_unlock(&info->io_lock);
   7.127 -
   7.128 -
   7.129  	xenbus_frontend_closed(dev);
   7.130  
   7.131  	return 0;
   7.132 @@ -329,12 +315,14 @@ static void scsifront_do_lun_hotplug(str
   7.133  			if (device_state == XenbusStateInitialised) {
   7.134  				sdev = scsi_device_lookup(info->host, chn, tgt, lun);
   7.135  				if (sdev) {
   7.136 +					printk(KERN_ERR "scsifront: Device already in use.\n");
   7.137 +					scsi_device_put(sdev);
   7.138  					xenbus_printf(XBT_NIL, dev->nodename,
   7.139 -						state_str, "%d", XenbusStateClosing);
   7.140 +						state_str, "%d", XenbusStateClosed);
   7.141  				} else {
   7.142  					scsi_add_device(info->host, chn, tgt, lun);
   7.143  					xenbus_printf(XBT_NIL, dev->nodename,
   7.144 -						state_str, "%d", XenbusStateInitialised);
   7.145 +						state_str, "%d", XenbusStateConnected);
   7.146  				}
   7.147  			}
   7.148  			break;
   7.149 @@ -345,10 +333,7 @@ static void scsifront_do_lun_hotplug(str
   7.150  					scsi_remove_device(sdev);
   7.151  					scsi_device_put(sdev);
   7.152  					xenbus_printf(XBT_NIL, dev->nodename,
   7.153 -						state_str, "%d", XenbusStateClosing);
   7.154 -				} else {
   7.155 -					err = PTR_ERR(sdev);
   7.156 -					goto scsi_del_fail;
   7.157 +						state_str, "%d", XenbusStateClosed);
   7.158  				}
   7.159  			}
   7.160  			break;
   7.161 @@ -365,12 +350,6 @@ fail:
   7.162  	kfree(dir);
   7.163  	xenbus_dev_fatal(dev, err, "read or write %s ", str);
   7.164  	return;
   7.165 -
   7.166 -scsi_del_fail:
   7.167 -	kfree(dir);
   7.168 -	printk(KERN_ERR "scsifront: fail to del scsi lun %d\n", err);
   7.169 -	return;
   7.170 -
   7.171  }
   7.172  
   7.173  
   7.174 @@ -398,6 +377,10 @@ static void scsifront_backend_changed(st
   7.175  			XenbusStateInitialised) {
   7.176  			scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
   7.177  		}
   7.178 +		
   7.179 +		if (dev->state == XenbusStateConnected)
   7.180 +			break;
   7.181 +			
   7.182  		xenbus_switch_state(dev, XenbusStateConnected);
   7.183  		break;
   7.184