# 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
|