[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] pvSCSI: Sanity check for REPORT_LUN emulation
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1216203554 -3600 # Node ID bd4b58143713a9d379570707a755079c7cb4f62d # Parent a682229d0eacf0bdd25b87a27143d451792f251b pvSCSI: Sanity check for REPORT_LUN emulation - Sanity check for REPORT_LUN emulation. - Return "residual" value from backend to frontend. The residual value is used to represent difference between request size the frontend requested and size backend actually responded. Signed-off-by: Tomonari Horikoshi <t.horikoshi@xxxxxxxxxxxxxx> Signed-off-by: Jun Kamada <kama@xxxxxxxxxxxxxx> --- drivers/xen/scsiback/common.h | 3 - drivers/xen/scsiback/emulate.c | 83 ++++++++++++++++++++++++++----------- drivers/xen/scsiback/scsiback.c | 16 ++++--- drivers/xen/scsifront/scsifront.c | 2 include/xen/interface/io/vscsiif.h | 4 + 5 files changed, 76 insertions(+), 32 deletions(-) diff -r a682229d0eac -r bd4b58143713 drivers/xen/scsiback/common.h --- a/drivers/xen/scsiback/common.h Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/scsiback/common.h Wed Jul 16 11:19:14 2008 +0100 @@ -124,6 +124,7 @@ typedef struct { grant_ref_t gref[VSCSIIF_SG_TABLESIZE]; int32_t rslt; + uint32_t resid; uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE]; struct list_head free_list; @@ -169,7 +170,7 @@ void scsiback_release_translation_entry( void scsiback_cmd_exec(pending_req_t *pending_req); void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result, - pending_req_t *pending_req); + uint32_t resid, pending_req_t *pending_req); void scsiback_fast_flush_area(pending_req_t *req); void scsiback_rsp_emulation(pending_req_t *pending_req); diff -r a682229d0eac -r bd4b58143713 drivers/xen/scsiback/emulate.c --- a/drivers/xen/scsiback/emulate.c Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/scsiback/emulate.c Wed Jul 16 11:19:14 2008 +0100 @@ -73,6 +73,10 @@ #define VSCSI_MAX_SCSI_OP_CODE 256 static unsigned char bitmap[VSCSI_MAX_SCSI_OP_CODE]; +/* REPORT LUNS Header*/ +#define VSCSI_REPORT_LUNS_HEADER 8 + + /* Emulation routines for each SCSI op_code. */ @@ -97,7 +101,8 @@ static void resp_not_supported_cmd(pendi { scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST, INVALID_OPCODE, 0); - pending_req->rslt = check_condition_result; + pending_req->resid = 0; + pending_req->rslt = check_condition_result; } @@ -180,6 +185,21 @@ static int __copy_from_sg(struct scatter return 0; } +static int __nr_luns_under_host(struct vscsibk_info *info) +{ + struct v2p_entry *entry; + struct list_head *head = &(info->v2p_entry_lists); + unsigned long flags; + int lun_cnt = 0; + + spin_lock_irqsave(&info->v2p_lock, flags); + list_for_each_entry(entry, head, l) { + lun_cnt++; + } + spin_unlock_irqrestore(&info->v2p_lock, flags); + + return (lun_cnt); +} /* quoted scsi_debug.c/resp_report_luns() */ static void __report_luns(pending_req_t *pending_req, void *data) @@ -190,9 +210,11 @@ static void __report_luns(pending_req_t unsigned int nr_seg = pending_req->nr_segments; unsigned char *cmd = (unsigned char *)pending_req->cmnd; - unsigned char *rq_buff = NULL; + unsigned char *buff = NULL; unsigned char alloc_len; - unsigned int buff_len = 0; + unsigned int alloc_luns = 0; + unsigned int req_bufflen = 0; + unsigned int actual_len = 0; int select_report = (int)cmd[2]; int i, lun_cnt = 0, lun, upper, err = 0; @@ -202,25 +224,31 @@ static void __report_luns(pending_req_t struct scsi_lun *one_lun; - alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); - if ((alloc_len < 4) || (select_report != 0)) + req_bufflen = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); + if ((req_bufflen < 4) || (select_report != 0)) goto fail; - - for (i = 0; i < nr_seg; i++) - buff_len += pending_req->sgl[i].length; - - if ((rq_buff = kmalloc(buff_len, GFP_KERNEL)) == NULL) { + + alloc_luns = __nr_luns_under_host(info); + alloc_len = sizeof(struct scsi_lun) * alloc_luns + + VSCSI_REPORT_LUNS_HEADER; + + if ((buff = kmalloc(alloc_len, GFP_KERNEL)) == NULL) { printk(KERN_ERR "scsiback:%s kmalloc err\n", __FUNCTION__); goto fail; } - memset(rq_buff, 0, buff_len); - - one_lun = (struct scsi_lun *) &rq_buff[8]; + memset(buff, 0, alloc_len); + + one_lun = (struct scsi_lun *) &buff[8]; spin_lock_irqsave(&info->v2p_lock, flags); list_for_each_entry(entry, head, l) { if ((entry->v.chn == channel) && (entry->v.tgt == target)) { + + /* check overflow */ + if (lun_cnt >= alloc_luns) + goto fail; + lun = entry->v.lun; upper = (lun >> 8) & 0x3f; if (upper) @@ -232,25 +260,34 @@ static void __report_luns(pending_req_t spin_unlock_irqrestore(&info->v2p_lock, flags); - rq_buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff; - rq_buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff; - - err = __copy_to_sg(pending_req->sgl, nr_seg, rq_buff, buff_len); + buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff; + buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff; + + actual_len = lun_cnt * sizeof(struct scsi_lun) + + VSCSI_REPORT_LUNS_HEADER; + req_bufflen = 0; + for (i = 0; i < nr_seg; i++) + req_bufflen += pending_req->sgl[i].length; + + err = __copy_to_sg(pending_req->sgl, nr_seg, buff, + min(req_bufflen, actual_len)); if (err) goto fail; memset(pending_req->sense_buffer, 0, VSCSIIF_SENSE_BUFFERSIZE); pending_req->rslt = 0x00; - - kfree(rq_buff); + pending_req->resid = req_bufflen - min(req_bufflen, actual_len); + + kfree(buff); return; fail: scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); - pending_req->rslt = check_condition_result; - if (rq_buff) - kfree(rq_buff); + pending_req->rslt = check_condition_result; + pending_req->resid = 0; + if (buff) + kfree(buff); return; } @@ -294,7 +331,7 @@ void scsiback_req_emulation_or_cmdexec(p else { scsiback_fast_flush_area(pending_req); scsiback_do_resp_with_sense(pending_req->sense_buffer, - pending_req->rslt, pending_req); + pending_req->rslt, pending_req->resid, pending_req); } } diff -r a682229d0eac -r bd4b58143713 drivers/xen/scsiback/scsiback.c --- a/drivers/xen/scsiback/scsiback.c Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/scsiback/scsiback.c Wed Jul 16 11:19:14 2008 +0100 @@ -142,7 +142,7 @@ static void scsiback_notify_work(struct } void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result, - pending_req_t *pending_req) + uint32_t resid, pending_req_t *pending_req) { vscsiif_response_t *ring_res; struct vscsibk_info *info = pending_req->info; @@ -167,6 +167,8 @@ void scsiback_do_resp_with_sense(char *s } else { ring_res->sense_len = 0; } + + ring_res->residual_len = resid; RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&info->ring, notify); if (info->ring.rsp_prod_pvt == info->ring.req_cons) { @@ -209,8 +211,10 @@ static void scsiback_cmd_done(struct req { pending_req_t *pending_req = req->end_io_data; unsigned char *sense_buffer; + unsigned int resid; sense_buffer = req->sense; + resid = req->data_len; if (errors != 0) { if (log_print_stat) @@ -220,7 +224,7 @@ static void scsiback_cmd_done(struct req scsiback_rsp_emulation(pending_req); scsiback_fast_flush_area(pending_req); - scsiback_do_resp_with_sense(sense_buffer, errors, pending_req); + scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req); scsiback_put(pending_req->info); __blk_put_request(req->q, req); @@ -473,7 +477,7 @@ static void scsiback_device_reset_exec(p scsiback_get(info); err = scsi_reset_provider(sdev, SCSI_TRY_RESET_DEVICE); - scsiback_do_resp_with_sense(NULL, err, pending_req); + scsiback_do_resp_with_sense(NULL, err, 0, pending_req); scsiback_put(info); return; @@ -592,11 +596,11 @@ static int scsiback_do_cmd_fn(struct vsc pending_req); if (err == -EINVAL) { scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24), - pending_req); + 0, pending_req); continue; } else if (err == -ENODEV) { scsiback_do_resp_with_sense(NULL, (DID_NO_CONNECT << 16), - pending_req); + 0, pending_req); continue; } @@ -607,7 +611,7 @@ static int scsiback_do_cmd_fn(struct vsc } else { printk(KERN_ERR "scsiback: invalid parameter for request\n"); scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24), - pending_req); + 0, pending_req); continue; } } diff -r a682229d0eac -r bd4b58143713 drivers/xen/scsifront/scsifront.c --- a/drivers/xen/scsifront/scsifront.c Tue Jul 15 16:39:39 2008 +0100 +++ b/drivers/xen/scsifront/scsifront.c Wed Jul 16 11:19:14 2008 +0100 @@ -147,7 +147,7 @@ static void scsifront_cdb_cmd_done(struc add_id_to_freelist(info, id); sc->result = ring_res->rslt; - sc->resid = 0; + sc->resid = ring_res->residual_len; if (ring_res->sense_len > VSCSIIF_SENSE_BUFFERSIZE) sense_len = VSCSIIF_SENSE_BUFFERSIZE; diff -r a682229d0eac -r bd4b58143713 include/xen/interface/io/vscsiif.h --- a/include/xen/interface/io/vscsiif.h Tue Jul 15 16:39:39 2008 +0100 +++ b/include/xen/interface/io/vscsiif.h Wed Jul 16 11:19:14 2008 +0100 @@ -84,7 +84,9 @@ struct vscsiif_response { uint8_t sense_len; uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE]; int32_t rslt; - uint32_t reserved[37]; + uint32_t residual_len; /* request bufflen - + return the value from physical device */ + uint32_t reserved[36]; }; typedef struct vscsiif_response vscsiif_response_t; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |