[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] pvSCSI: Fix many points of backend/frontend driver
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1215088613 -3600 # Node ID 920abc7b20acaebabf844910e4b461378fae3007 # Parent 9c4a15e54814161d8909dd68e288bba50fe5c221 pvSCSI: Fix many points of backend/frontend driver Signed-off-by: Tomonari Horikoshi <t.horikoshi@xxxxxxxxxxxxxx> Signed-off-by: Jun Kamada <kama@xxxxxxxxxxxxxx> --- drivers/xen/scsiback/common.h | 6 - drivers/xen/scsiback/interface.c | 14 +--- drivers/xen/scsiback/scsiback.c | 106 +++++++++++++++++----------------- drivers/xen/scsiback/translate.c | 6 + drivers/xen/scsiback/xenbus.c | 116 +++++++++++++++++++++++++------------- drivers/xen/scsifront/scsifront.c | 6 + drivers/xen/scsifront/xenbus.c | 89 +++++++++++------------------ 7 files changed, 185 insertions(+), 158 deletions(-) diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsiback/common.h --- a/drivers/xen/scsiback/common.h Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsiback/common.h Thu Jul 03 13:36:53 2008 +0100 @@ -92,7 +92,7 @@ struct vscsibk_info { grant_ref_t shmem_ref; spinlock_t ring_lock; - atomic_t refcnt; + atomic_t nr_unreplied_reqs; spinlock_t v2p_lock; struct list_head v2p_entry_lists; @@ -133,10 +133,10 @@ typedef struct { -#define scsiback_get(_b) (atomic_inc(&(_b)->refcnt)) +#define scsiback_get(_b) (atomic_inc(&(_b)->nr_unreplied_reqs)) #define scsiback_put(_b) \ do { \ - if (atomic_dec_and_test(&(_b)->refcnt)) \ + if (atomic_dec_and_test(&(_b)->nr_unreplied_reqs)) \ wake_up(&(_b)->waiting_to_free);\ } while (0) diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsiback/interface.c --- a/drivers/xen/scsiback/interface.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsiback/interface.c Thu Jul 03 13:36:53 2008 +0100 @@ -52,7 +52,7 @@ struct vscsibk_info *vscsibk_info_alloc( memset(info, 0, sizeof(*info)); info->domid = domid; spin_lock_init(&info->ring_lock); - atomic_set(&info->refcnt, 1); + atomic_set(&info->nr_unreplied_reqs, 0); init_waitqueue_head(&info->wq); init_waitqueue_head(&info->waiting_to_free); @@ -104,7 +104,7 @@ int scsiback_init_sring(struct vscsibk_i if (info->irq) { printk(KERN_ERR "scsiback: Already connected through?\n"); - return 0; + return -1; } info->ring_area = alloc_vm_area(PAGE_SIZE); @@ -126,7 +126,7 @@ int scsiback_init_sring(struct vscsibk_i goto unmap_page; info->irq = err; - + return 0; unmap_page: @@ -144,9 +144,8 @@ void scsiback_disconnect(struct vscsibk_ info->kthread = NULL; } - atomic_dec(&info->refcnt); - wait_event(info->waiting_to_free, atomic_read(&info->refcnt) == 0); - atomic_inc(&info->refcnt); + wait_event(info->waiting_to_free, + atomic_read(&info->nr_unreplied_reqs) == 0); if (info->irq) { unbind_from_irqhandler(info->irq, info); @@ -162,8 +161,7 @@ void scsiback_disconnect(struct vscsibk_ void scsiback_free(struct vscsibk_info *info) { - if (atomic_dec_and_test(&info->refcnt)) - kmem_cache_free(scsiback_cachep, info); + kmem_cache_free(scsiback_cachep, info); } int __init scsiback_interface_init(void) diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsiback/scsiback.c --- a/drivers/xen/scsiback/scsiback.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsiback/scsiback.c Thu Jul 03 13:36:53 2008 +0100 @@ -56,6 +56,8 @@ module_param_named(reqs, vscsiif_reqs, i module_param_named(reqs, vscsiif_reqs, int, 0); MODULE_PARM_DESC(reqs, "Number of scsiback requests to allocate"); +static unsigned int log_print_stat = 0; +module_param(log_print_stat, int, 0644); #define SCSIBACK_INVALID_HANDLE (~0) @@ -154,7 +156,6 @@ void scsiback_do_resp_with_sense(char *s spin_lock_irqsave(&info->ring_lock, flags); - rmb(); ring_res = RING_GET_RESPONSE(&info->ring, info->ring.rsp_prod_pvt); info->ring.rsp_prod_pvt++; @@ -184,49 +185,53 @@ void scsiback_do_resp_with_sense(char *s if (notify) notify_remote_via_irq(info->irq); - scsiback_put(pending_req->info); free_req(pending_req); } + +static void scsiback_print_status(char *sense_buffer, int errors, + pending_req_t *pending_req) +{ + struct scsi_device *sdev = pending_req->sdev; + + printk(KERN_ERR "scsiback: %d:%d:%d:%d ",sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + printk(KERN_ERR "status = 0x%02x, message = 0x%02x, host = 0x%02x, driver = 0x%02x\n", + status_byte(errors), msg_byte(errors), + host_byte(errors), driver_byte(errors)); + + printk(KERN_ERR "scsiback: cmnd[0]=0x%02X\n", + pending_req->cmnd[0]); + + if (CHECK_CONDITION & status_byte(errors)) + __scsi_print_sense("scsiback", sense_buffer, SCSI_SENSE_BUFFERSIZE); +} + #ifdef NO_ASYNC /*!async*/ static void scsiback_cmd_done(struct request *req, int errors) { pending_req_t *pending_req = req->end_io_data; - struct scsi_device *sdev = pending_req->sdev; unsigned char *sense_buffer; sense_buffer = req->sense; - #else static void scsiback_cmd_done(void *data, char *sense_buffer, int errors, int resid) { pending_req_t *pending_req = data; struct scsi_device *sdev = pending_req->sdev; - - DPRINTK("%s\n",__FUNCTION__); #endif - if ((errors != 0) && (pending_req->cmnd[0] != TEST_UNIT_READY)) { - - printk(KERN_ERR "scsiback: %d:%d:%d:%d ",sdev->host->host_no, - sdev->channel, sdev->id, sdev->lun); - printk(KERN_ERR "status = 0x%02x, message = 0x%02x, host = 0x%02x, driver = 0x%02x\n", - status_byte(errors), msg_byte(errors), - host_byte(errors), driver_byte(errors)); - - printk(KERN_ERR "scsiback: cmnd[0]=0x%02X nr_segments=%d\n", - pending_req->cmnd[0], - pending_req->nr_segments); - - if (CHECK_CONDITION & status_byte(errors)) - __scsi_print_sense("scsiback", sense_buffer, SCSI_SENSE_BUFFERSIZE); + if (errors != 0) { + if (log_print_stat) + scsiback_print_status(sense_buffer, errors, pending_req); } scsiback_rsp_emulation(pending_req); + scsiback_fast_flush_area(pending_req); scsiback_do_resp_with_sense(sense_buffer, errors, pending_req); - + scsiback_put(pending_req->info); #ifdef NO_ASYNC /*!async*/ __blk_put_request(req->q, req); @@ -304,7 +309,6 @@ fail_flush: scsiback_fast_flush_area(pending_req); return -ENOMEM; } - #ifdef NO_ASYNC /*!async*/ @@ -347,7 +351,7 @@ static int scsiback_bi_endio(struct bio /* quoted scsi_lib.c/scsi_req_map_sg . */ -static int requset_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count) +static int request_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count) { struct request_queue *q = rq->q; int nr_pages; @@ -422,16 +426,16 @@ free_bios: void scsiback_cmd_exec(pending_req_t *pending_req) { - int err; - int cmd_len = (int)pending_req->cmd_len; int data_dir = (int)pending_req->sc_data_direction; unsigned int nr_segments = (unsigned int)pending_req->nr_segments; unsigned int timeout; + #ifdef NO_ASYNC /*!async*/ struct request *rq; int write; #else + int err = 0; unsigned int data_len = pending_req->request_bufflen; #endif @@ -439,12 +443,11 @@ void scsiback_cmd_exec(pending_req_t *pe /* because it doesn't timeout backend earlier than frontend.*/ if (pending_req->timeout_per_command) - timeout = (pending_req->timeout_per_command * HZ * 2); + timeout = pending_req->timeout_per_command * HZ; else timeout = VSCSIIF_TIMEOUT; #ifdef NO_ASYNC /*!async*/ - err = 0; write = (data_dir == DMA_TO_DEVICE); rq = blk_get_request(pending_req->sdev->request_queue, write, GFP_KERNEL); @@ -456,31 +459,33 @@ void scsiback_cmd_exec(pending_req_t *pe rq->sense = pending_req->sense_buffer; rq->sense_len = 0; + /* not allowed to retry in backend. */ rq->retries = 0; rq->timeout = timeout; rq->end_io_data = pending_req; if (nr_segments) { - if (requset_map_sg(rq, pending_req, nr_segments)) { + if (request_map_sg(rq, pending_req, nr_segments)) { printk(KERN_ERR "scsiback: SG Request Map Error\n"); return; } } + scsiback_get(pending_req->info); blk_execute_rq_nowait(rq->q, NULL, rq, 1, scsiback_cmd_done); - #else /*async*/ - /* not allowed to retry in backend. */ - /* timeout of backend is longer than that of brontend.*/ + + scsiback_get(pending_req->info); err = scsi_execute_async(pending_req->sdev, &(pending_req->cmnd[0]), - cmd_len, data_dir, &(pending_req->sgl[0]), data_len, nr_segments, timeout, 0, - pending_req, scsiback_cmd_done, GFP_ATOMIC); - -#endif /*!async*/ - - if (err) + cmd_len, data_dir, pending_req->sgl, data_len, nr_segments, timeout, 0, + pending_req, scsiback_cmd_done, GFP_KERNEL); + + if (err) { scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24), pending_req); + } + +#endif /*async*/ return ; } @@ -493,12 +498,11 @@ static void scsiback_device_reset_exec(p struct scsi_device *sdev = pending_req->sdev; scsiback_get(info); - err = scsi_reset_provider(sdev, SCSI_TRY_RESET_DEVICE); scsiback_do_resp_with_sense(NULL, err, pending_req); - - notify_remote_via_irq(info->irq); + scsiback_put(info); + return; } @@ -530,7 +534,7 @@ static int prepare_pending_reqs(struct v sdev = scsiback_do_translation(info, &vir); if (!sdev) { pending_req->sdev = NULL; - printk(KERN_ERR "scsiback: doesn't exist.\n"); + DPRINTK("scsiback: doesn't exist.\n"); err = -ENODEV; goto invald_value; } @@ -541,14 +545,14 @@ static int prepare_pending_reqs(struct v (ring_req->sc_data_direction != DMA_TO_DEVICE) && (ring_req->sc_data_direction != DMA_FROM_DEVICE) && (ring_req->sc_data_direction != DMA_NONE)) { - printk(KERN_ERR "scsiback: invalid parameter data_dir = %d\n", + DPRINTK("scsiback: invalid parameter data_dir = %d\n", ring_req->sc_data_direction); err = -EINVAL; goto invald_value; } if (ring_req->nr_segments > VSCSIIF_SG_TABLESIZE) { - printk(KERN_ERR "scsiback: invalid parameter nr_seg = %d\n", + DPRINTK("scsiback: invalid parameter nr_seg = %d\n", ring_req->nr_segments); err = -EINVAL; goto invald_value; @@ -556,7 +560,7 @@ static int prepare_pending_reqs(struct v pending_req->nr_segments = ring_req->nr_segments; if (ring_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) { - printk(KERN_ERR "scsiback: invalid parameter cmd_len = %d\n", + DPRINTK("scsiback: invalid parameter cmd_len = %d\n", ring_req->cmd_len); err = -EINVAL; goto invald_value; @@ -568,7 +572,7 @@ static int prepare_pending_reqs(struct v pending_req->timeout_per_command = ring_req->timeout_per_command; if(scsiback_gnttab_data_map(ring_req, pending_req)) { - printk(KERN_ERR "scsiback: invalid buffer\n"); + DPRINTK("scsiback: invalid buffer\n"); err = -EINVAL; goto invald_value; } @@ -607,7 +611,6 @@ static int scsiback_do_cmd_fn(struct vsc ring_req = RING_GET_REQUEST(ring, rc); ring->req_cons = ++rc; - scsiback_get(info); err = prepare_pending_reqs(info, ring_req, pending_req); if (err == -EINVAL) { @@ -616,7 +619,8 @@ static int scsiback_do_cmd_fn(struct vsc continue; } else if (err == -ENODEV) { scsiback_do_resp_with_sense(NULL, (DID_NO_CONNECT << 16), - pending_req); + pending_req); + continue; } if (pending_req->act == VSCSIIF_ACT_SCSI_CDB) { @@ -634,6 +638,9 @@ static int scsiback_do_cmd_fn(struct vsc if (RING_HAS_UNCONSUMED_REQUESTS(ring)) more_to_do = 1; + /* Yield point for this unbounded loop. */ + cond_resched(); + return more_to_do; } @@ -643,8 +650,6 @@ int scsiback_schedule(void *data) struct vscsibk_info *info = (struct vscsibk_info *)data; DPRINTK("%s\n",__FUNCTION__); - - scsiback_get(info); while (!kthread_should_stop()) { wait_event_interruptible( @@ -661,9 +666,6 @@ int scsiback_schedule(void *data) info->waiting_reqs = 1; } - info->kthread = NULL; - scsiback_put(info); - return 0; } diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsiback/translate.c --- a/drivers/xen/scsiback/translate.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsiback/translate.c Thu Jul 03 13:36:53 2008 +0100 @@ -71,14 +71,14 @@ int scsiback_add_translation_entry(struc } /* Create a new translation entry and add to the list */ - if ((new = kmalloc(sizeof(struct v2p_entry), GFP_KERNEL)) == NULL) { + if ((new = kmalloc(sizeof(struct v2p_entry), GFP_ATOMIC)) == NULL) { printk(KERN_ERR "scsiback: %s: kmalloc() error.\n", __FUNCTION__); err = -ENOMEM; goto out; } new->v = *v; new->sdev = sdev; - list_add(&new->l, head); + list_add_tail(&new->l, head); out: spin_unlock_irqrestore(&info->v2p_lock, flags); @@ -111,6 +111,7 @@ int scsiback_del_translation_entry(struc found: /* Delete the translation entry specfied */ + scsi_device_put(entry->sdev); list_del(&entry->l); kfree(entry); @@ -156,6 +157,7 @@ void scsiback_release_translation_entry( spin_lock_irqsave(&info->v2p_lock, flags); list_for_each_entry_safe(entry, tmp, head, l) { + scsi_device_put(entry->sdev); list_del(&entry->l); kfree(entry); } diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsiback/xenbus.c --- a/drivers/xen/scsiback/xenbus.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsiback/xenbus.c Thu Jul 03 13:36:53 2008 +0100 @@ -113,11 +113,42 @@ struct scsi_device *scsiback_get_scsi_de goto invald_value; } + scsi_host_put(shost); invald_value: return (sdev); } #define VSCSIBACK_OP_ADD_OR_DEL_LUN 1 +#define VSCSIBACK_OP_UPDATEDEV_STATE 2 + +static int scsiback_change_device_state(struct xenbus_device *dev, + char *state_path, enum xenbus_state set_state) +{ + struct xenbus_transaction tr; + int err; + + do { + err = xenbus_transaction_start(&tr); + if (err != 0) { + printk(KERN_ERR "scsiback: transaction start failed\n"); + return err; + } + err = xenbus_printf(tr, dev->nodename, state_path, + "%d", set_state); + if (err != 0) { + printk(KERN_ERR "scsiback: xenbus_printf failed\n"); + xenbus_transaction_end(tr, 1); + return err; + } + err = xenbus_transaction_end(tr, 0); + } while (err == -EAGAIN); + + if (err != 0) { + printk(KERN_ERR "scsiback: failed to end %s.\n", __FUNCTION__); + return err; + } + return 0; +} static void scsiback_do_lun_hotplug(struct backend_info *be, int op) { @@ -132,12 +163,7 @@ static void scsiback_do_lun_hotplug(stru struct xenbus_transaction xbt; - err = xenbus_transaction_start(&xbt); - if (err) { - xenbus_dev_fatal(dev, err, "starting transaction"); - } - - dir = xenbus_directory(xbt, dev->nodename, "vscsi-devs", &dir_n); + dir = xenbus_directory(XBT_NIL, dev->nodename, "vscsi-devs", &dir_n); if (IS_ERR(dir)) return; @@ -145,14 +171,14 @@ static void scsiback_do_lun_hotplug(stru /* read status */ snprintf(state_str, sizeof(state_str), "vscsi-devs/%s/state", dir[i]); - err = xenbus_scanf(xbt, dev->nodename, state_str, "%u", + err = xenbus_scanf(XBT_NIL, dev->nodename, state_str, "%u", &device_state); if (XENBUS_EXIST_ERR(err)) continue; /* physical SCSI device */ snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", dir[i]); - err = xenbus_scanf(xbt, dev->nodename, str, + err = xenbus_scanf(XBT_NIL, dev->nodename, str, "%u:%u:%u:%u", &phy.hst, &phy.chn, &phy.tgt, &phy.lun); if (XENBUS_EXIST_ERR(err)) { xenbus_printf(xbt, dev->nodename, state_str, @@ -162,7 +188,7 @@ static void scsiback_do_lun_hotplug(stru /* virtual SCSI device */ snprintf(str, sizeof(str), "vscsi-devs/%s/v-dev", dir[i]); - err = xenbus_scanf(xbt, dev->nodename, str, + err = xenbus_scanf(XBT_NIL, dev->nodename, str, "%u:%u:%u:%u", &vir.hst, &vir.chn, &vir.tgt, &vir.lun); if (XENBUS_EXIST_ERR(err)) { xenbus_printf(xbt, dev->nodename, state_str, @@ -175,16 +201,22 @@ static void scsiback_do_lun_hotplug(stru if (device_state == XenbusStateInitialising) { sdev = scsiback_get_scsi_device(&phy); if (!sdev) { - xenbus_printf(xbt, dev->nodename, state_str, - "%d", XenbusStateClosing); + err = scsiback_change_device_state(dev, + state_str, XenbusStateClosing); + if (err) + goto fail; } else { err = scsiback_add_translation_entry(be->info, sdev, &vir); if (!err) { - xenbus_printf(xbt, dev->nodename, state_str, - "%d", XenbusStateInitialised); + err = scsiback_change_device_state(dev, + state_str, XenbusStateInitialised); + if (err) + goto fail; } else { - xenbus_printf(xbt, dev->nodename, state_str, - "%d", XenbusStateClosing); + err = scsiback_change_device_state(dev, + state_str, XenbusStateClosing); + if (err) + goto fail; } } } @@ -194,11 +226,22 @@ static void scsiback_do_lun_hotplug(stru if (err) goto fail; else { - xenbus_printf(xbt, dev->nodename, state_str, - "%d", XenbusStateClosed); + err = scsiback_change_device_state(dev, + state_str, XenbusStateClosed); + if (err) + goto fail; } } - + break; + + case VSCSIBACK_OP_UPDATEDEV_STATE: + if (device_state == XenbusStateInitialised) { + /* modify vscsi-devs/dev-x/state */ + err = scsiback_change_device_state(dev, + state_str, XenbusStateConnected); + if (err) + goto fail; + } break; /*When it is necessary, processing is added here.*/ default: @@ -206,11 +249,9 @@ static void scsiback_do_lun_hotplug(stru } } - xenbus_transaction_end(xbt, 0); kfree(dir); return ; fail : - xenbus_transaction_end(xbt, 1); kfree(dir); xenbus_dev_fatal(dev, err, "read or write %s ", str); return; @@ -232,19 +273,18 @@ static void scsiback_frontend_changed(st break; scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN); - err = xenbus_switch_state(dev, XenbusStateConnected); - if (err) - xenbus_dev_fatal(dev, err, "switching to Connected state", - dev->nodename); + xenbus_switch_state(dev, XenbusStateConnected); + break; case XenbusStateConnected: + + scsiback_do_lun_hotplug(be, VSCSIBACK_OP_UPDATEDEV_STATE); + if (dev->state == XenbusStateConnected) break; - - err = xenbus_switch_state(dev, XenbusStateConnected); - if (err) - xenbus_dev_fatal(dev, err, "switching to Connected state", - dev->nodename); + + xenbus_switch_state(dev, XenbusStateConnected); + break; case XenbusStateClosing: @@ -256,18 +296,18 @@ static void scsiback_frontend_changed(st xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; + /* fall through if not online */ + case XenbusStateUnknown: + device_unregister(&dev->dev); + break; case XenbusStateReconfiguring: scsiback_do_lun_hotplug(be, VSCSIBACK_OP_ADD_OR_DEL_LUN); - err = xenbus_switch_state(dev, XenbusStateReconfigured); - if (err) - xenbus_dev_fatal(dev, err, "switching to Reconfigured state", - dev->nodename); - break; - - case XenbusStateUnknown: - device_unregister(&dev->dev); - break; + + xenbus_switch_state(dev, XenbusStateReconfigured); + + break; + default: xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", frontend_state); diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsifront/scsifront.c --- a/drivers/xen/scsifront/scsifront.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsifront/scsifront.c Thu Jul 03 13:36:53 2008 +0100 @@ -216,6 +216,10 @@ int scsifront_cmd_done(struct vscsifrnt_ spin_unlock_irqrestore(&info->io_lock, flags); + + /* Yield point for this unbounded loop. */ + cond_resched(); + return more_to_do; } @@ -237,8 +241,6 @@ int scsifront_schedule(void *data) if (scsifront_cmd_done(info)) info->waiting_resp = 1; } - - info->kthread = NULL; return 0; } diff -r 9c4a15e54814 -r 920abc7b20ac drivers/xen/scsifront/xenbus.c --- a/drivers/xen/scsifront/xenbus.c Thu Jul 03 13:35:40 2008 +0100 +++ b/drivers/xen/scsifront/xenbus.c Thu Jul 03 13:36:53 2008 +0100 @@ -44,8 +44,13 @@ static void scsifront_free(struct vscsif { struct Scsi_Host *host = info->host; - if (scsi_host_get(host) != NULL) - scsi_host_put(host); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + if (host->shost_state != SHOST_DEL) { +#else + if (!test_bit(SHOST_DEL, &host->shost_state)) { +#endif + scsi_remove_host(info->host); + } if (info->ring_ref != GRANT_INVALID_REF) { gnttab_end_foreign_access(info->ring_ref, @@ -57,6 +62,8 @@ static void scsifront_free(struct vscsif if (info->irq) unbind_from_irqhandler(info->irq, info); info->irq = 0; + + scsi_host_put(info->host); } @@ -141,25 +148,19 @@ again: goto fail; } - err = xenbus_printf(xbt, dev->nodename, "vhostno", "%u", - info->host->host_no); - if (err) { - xenbus_dev_fatal(dev, err, "%s", "writing vhostno"); - goto fail; - } - err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; xenbus_dev_fatal(dev, err, "completing transaction"); - } else - xenbus_switch_state(dev, XenbusStateInitialised); + goto free_sring; + } return 0; fail: xenbus_transaction_end(xbt, 1); +free_sring: /* free resource */ scsifront_free(info); @@ -212,33 +213,29 @@ static int scsifront_probe(struct xenbus if (IS_ERR(info->kthread)) { err = PTR_ERR(info->kthread); info->kthread = NULL; + printk(KERN_ERR "scsifront: kthread start err %d\n", err); + goto free_sring; } host->max_id = VSCSIIF_MAX_TARGET; host->max_channel = 0; host->max_lun = VSCSIIF_MAX_LUN; - host->max_sectors = (VSCSIIF_SG_TABLESIZE * PAGE_SIZE / 512); + host->max_sectors = (VSCSIIF_SG_TABLESIZE - 1) * PAGE_SIZE / 512; err = scsi_add_host(host, &dev->dev); if (err) { printk(KERN_ERR "scsifront: fail to add scsi host %d\n", err); - return err; + goto free_sring; } xenbus_switch_state(dev, XenbusStateInitialised); - #if 0 - /* All SCSI device scan */ - scsi_scan_host(host); - - err = xenbus_printf(XBT_NIL, dev->nodename, "hotplug-status", "%s", - "connected"); - if (err) { - xenbus_dev_fatal(dev, err, "%s", "writing hotplug-status"); - return err; - } - #endif - return 0; + return 0; + +free_sring: + /* free resource */ + scsifront_free(info); + return err; } static int scsifront_remove(struct xenbus_device *dev) @@ -263,26 +260,15 @@ static int scsifront_disconnect(struct v struct xenbus_device *dev = info->dev; struct Scsi_Host *host = info->host; - unsigned long flags; - DPRINTK("%s: %s disconnect\n",__FUNCTION__ ,dev->nodename); - spin_lock_irqsave(host->host_lock, flags); - while (RING_HAS_UNCONSUMED_RESPONSES(&info->ring)) { - if (!scsifront_cmd_done(info)) - break; - } - - spin_unlock_irqrestore(host->host_lock, flags); - - spin_lock(&info->io_lock); + /* + When this function is executed, all devices of + Frontend have been deleted. + Therefore, it need not block I/O before remove_host. + */ scsi_remove_host(host); - scsi_host_put(host); - - spin_unlock(&info->io_lock); - - xenbus_frontend_closed(dev); return 0; @@ -329,12 +315,14 @@ static void scsifront_do_lun_hotplug(str if (device_state == XenbusStateInitialised) { sdev = scsi_device_lookup(info->host, chn, tgt, lun); if (sdev) { + printk(KERN_ERR "scsifront: Device already in use.\n"); + scsi_device_put(sdev); xenbus_printf(XBT_NIL, dev->nodename, - state_str, "%d", XenbusStateClosing); + state_str, "%d", XenbusStateClosed); } else { scsi_add_device(info->host, chn, tgt, lun); xenbus_printf(XBT_NIL, dev->nodename, - state_str, "%d", XenbusStateInitialised); + state_str, "%d", XenbusStateConnected); } } break; @@ -345,10 +333,7 @@ static void scsifront_do_lun_hotplug(str scsi_remove_device(sdev); scsi_device_put(sdev); xenbus_printf(XBT_NIL, dev->nodename, - state_str, "%d", XenbusStateClosing); - } else { - err = PTR_ERR(sdev); - goto scsi_del_fail; + state_str, "%d", XenbusStateClosed); } } break; @@ -365,12 +350,6 @@ fail: kfree(dir); xenbus_dev_fatal(dev, err, "read or write %s ", str); return; - -scsi_del_fail: - kfree(dir); - printk(KERN_ERR "scsifront: fail to del scsi lun %d\n", err); - return; - } @@ -398,6 +377,10 @@ static void scsifront_backend_changed(st XenbusStateInitialised) { scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN); } + + if (dev->state == XenbusStateConnected) + break; + xenbus_switch_state(dev, XenbusStateConnected); break; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |