WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] pvSCSI: Fix many points of backend/fr

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] pvSCSI: Fix many points of backend/frontend driver
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 04 Jul 2008 08:00:19 -0700
Delivery-date: Fri, 04 Jul 2008 08:01:34 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] pvSCSI: Fix many points of backend/frontend driver, Xen patchbot-linux-2.6.18-xen <=