[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.