ia64/linux-2.6.18-xen.hg

changeset 603:bd4b58143713

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@jp.fujitsu.com>
Signed-off-by: Jun Kamada <kama@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 16 11:19:14 2008 +0100 (2008-07-16)
parents a682229d0eac
children 5644f68a7912
files drivers/xen/scsiback/common.h drivers/xen/scsiback/emulate.c drivers/xen/scsiback/scsiback.c drivers/xen/scsifront/scsifront.c include/xen/interface/io/vscsiif.h
line diff
     1.1 --- a/drivers/xen/scsiback/common.h	Tue Jul 15 16:39:39 2008 +0100
     1.2 +++ b/drivers/xen/scsiback/common.h	Wed Jul 16 11:19:14 2008 +0100
     1.3 @@ -124,6 +124,7 @@ typedef struct {
     1.4  	grant_ref_t gref[VSCSIIF_SG_TABLESIZE];
     1.5  
     1.6  	int32_t rslt;
     1.7 +	uint32_t resid;
     1.8  	uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
     1.9  
    1.10  	struct list_head free_list;
    1.11 @@ -169,7 +170,7 @@ void scsiback_release_translation_entry(
    1.12  
    1.13  void scsiback_cmd_exec(pending_req_t *pending_req);
    1.14  void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
    1.15 -				pending_req_t *pending_req);
    1.16 +			uint32_t resid, pending_req_t *pending_req);
    1.17  void scsiback_fast_flush_area(pending_req_t *req);
    1.18  
    1.19  void scsiback_rsp_emulation(pending_req_t *pending_req);
     2.1 --- a/drivers/xen/scsiback/emulate.c	Tue Jul 15 16:39:39 2008 +0100
     2.2 +++ b/drivers/xen/scsiback/emulate.c	Wed Jul 16 11:19:14 2008 +0100
     2.3 @@ -73,6 +73,10 @@
     2.4  #define VSCSI_MAX_SCSI_OP_CODE		256
     2.5  static unsigned char bitmap[VSCSI_MAX_SCSI_OP_CODE];
     2.6  
     2.7 +/* REPORT LUNS Header*/
     2.8 +#define VSCSI_REPORT_LUNS_HEADER	8
     2.9 +
    2.10 +
    2.11  /*
    2.12    Emulation routines for each SCSI op_code.
    2.13  */
    2.14 @@ -97,7 +101,8 @@ static void resp_not_supported_cmd(pendi
    2.15  {
    2.16  	scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
    2.17  		INVALID_OPCODE, 0);
    2.18 -	pending_req->rslt = check_condition_result;
    2.19 +	pending_req->resid = 0;
    2.20 +	pending_req->rslt  = check_condition_result;
    2.21  }
    2.22  
    2.23  
    2.24 @@ -180,6 +185,21 @@ static int __copy_from_sg(struct scatter
    2.25  	return 0;
    2.26  }
    2.27  
    2.28 +static int __nr_luns_under_host(struct vscsibk_info *info)
    2.29 +{
    2.30 +	struct v2p_entry *entry;
    2.31 +	struct list_head *head = &(info->v2p_entry_lists);
    2.32 +	unsigned long flags;
    2.33 +	int lun_cnt = 0;
    2.34 +
    2.35 +	spin_lock_irqsave(&info->v2p_lock, flags);
    2.36 +	list_for_each_entry(entry, head, l) {
    2.37 +			lun_cnt++;
    2.38 +	}
    2.39 +	spin_unlock_irqrestore(&info->v2p_lock, flags);
    2.40 +
    2.41 +	return (lun_cnt);
    2.42 +}
    2.43  
    2.44  /* quoted scsi_debug.c/resp_report_luns() */
    2.45  static void __report_luns(pending_req_t *pending_req, void *data)
    2.46 @@ -190,9 +210,11 @@ static void __report_luns(pending_req_t 
    2.47  	unsigned int        nr_seg  = pending_req->nr_segments;
    2.48  	unsigned char *cmd = (unsigned char *)pending_req->cmnd;
    2.49  	
    2.50 -	unsigned char *rq_buff = NULL;
    2.51 +	unsigned char *buff = NULL;
    2.52  	unsigned char alloc_len;
    2.53 -	unsigned int buff_len = 0;
    2.54 +	unsigned int alloc_luns = 0;
    2.55 +	unsigned int req_bufflen = 0;
    2.56 +	unsigned int actual_len = 0;
    2.57  	int select_report = (int)cmd[2];
    2.58  	int i, lun_cnt = 0, lun, upper, err = 0;
    2.59  	
    2.60 @@ -202,25 +224,31 @@ static void __report_luns(pending_req_t 
    2.61  	
    2.62  	struct scsi_lun *one_lun;
    2.63  
    2.64 -	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
    2.65 -	if ((alloc_len < 4) || (select_report != 0))
    2.66 +	req_bufflen = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
    2.67 +	if ((req_bufflen < 4) || (select_report != 0))
    2.68  		goto fail;
    2.69 -	
    2.70 -	for (i = 0; i < nr_seg; i++)
    2.71 -		buff_len += pending_req->sgl[i].length;
    2.72  
    2.73 -	if ((rq_buff = kmalloc(buff_len, GFP_KERNEL)) == NULL) {
    2.74 +	alloc_luns = __nr_luns_under_host(info);
    2.75 +	alloc_len  = sizeof(struct scsi_lun) * alloc_luns
    2.76 +				+ VSCSI_REPORT_LUNS_HEADER;
    2.77 +
    2.78 +	if ((buff = kmalloc(alloc_len, GFP_KERNEL)) == NULL) {
    2.79  		printk(KERN_ERR "scsiback:%s kmalloc err\n", __FUNCTION__);
    2.80  		goto fail;
    2.81  	}
    2.82  
    2.83 -	memset(rq_buff, 0, buff_len);
    2.84 +	memset(buff, 0, alloc_len);
    2.85  
    2.86 -	one_lun = (struct scsi_lun *) &rq_buff[8];
    2.87 +	one_lun = (struct scsi_lun *) &buff[8];
    2.88  	spin_lock_irqsave(&info->v2p_lock, flags);
    2.89  	list_for_each_entry(entry, head, l) {
    2.90  		if ((entry->v.chn == channel) &&
    2.91  		    (entry->v.tgt == target)) {
    2.92 +			
    2.93 +			/* check overflow */
    2.94 +			if (lun_cnt >= alloc_luns)
    2.95 +				goto fail;
    2.96 +
    2.97  			lun = entry->v.lun;
    2.98  			upper = (lun >> 8) & 0x3f;
    2.99  			if (upper)
   2.100 @@ -232,25 +260,34 @@ static void __report_luns(pending_req_t 
   2.101  
   2.102  	spin_unlock_irqrestore(&info->v2p_lock, flags);
   2.103  
   2.104 -	rq_buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
   2.105 -	rq_buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
   2.106 +	buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
   2.107 +	buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
   2.108  
   2.109 -	err = __copy_to_sg(pending_req->sgl, nr_seg, rq_buff, buff_len);
   2.110 +	actual_len = lun_cnt * sizeof(struct scsi_lun) 
   2.111 +				+ VSCSI_REPORT_LUNS_HEADER;
   2.112 +	req_bufflen = 0;
   2.113 +	for (i = 0; i < nr_seg; i++)
   2.114 +		req_bufflen += pending_req->sgl[i].length;
   2.115 +
   2.116 +	err = __copy_to_sg(pending_req->sgl, nr_seg, buff, 
   2.117 +				min(req_bufflen, actual_len));
   2.118  	if (err)
   2.119  		goto fail;
   2.120  
   2.121  	memset(pending_req->sense_buffer, 0, VSCSIIF_SENSE_BUFFERSIZE);
   2.122  	pending_req->rslt = 0x00;
   2.123 +	pending_req->resid = req_bufflen - min(req_bufflen, actual_len);
   2.124  
   2.125 -	kfree(rq_buff);
   2.126 +	kfree(buff);
   2.127  	return;
   2.128  
   2.129  fail:
   2.130  	scsiback_mk_sense_buffer(pending_req->sense_buffer, ILLEGAL_REQUEST,
   2.131  		INVALID_FIELD_IN_CDB, 0);
   2.132 -	pending_req->rslt = check_condition_result;
   2.133 -	if (rq_buff)
   2.134 -		kfree(rq_buff);
   2.135 +	pending_req->rslt  = check_condition_result;
   2.136 +	pending_req->resid = 0;
   2.137 +	if (buff)
   2.138 +		kfree(buff);
   2.139  	return;
   2.140  }
   2.141  
   2.142 @@ -294,7 +331,7 @@ void scsiback_req_emulation_or_cmdexec(p
   2.143  	else {
   2.144  		scsiback_fast_flush_area(pending_req);
   2.145  		scsiback_do_resp_with_sense(pending_req->sense_buffer,
   2.146 -			pending_req->rslt, pending_req);
   2.147 +		  pending_req->rslt, pending_req->resid, pending_req);
   2.148  	}
   2.149  }
   2.150  
     3.1 --- a/drivers/xen/scsiback/scsiback.c	Tue Jul 15 16:39:39 2008 +0100
     3.2 +++ b/drivers/xen/scsiback/scsiback.c	Wed Jul 16 11:19:14 2008 +0100
     3.3 @@ -142,7 +142,7 @@ static void scsiback_notify_work(struct 
     3.4  }
     3.5  
     3.6  void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
     3.7 -				pending_req_t *pending_req)
     3.8 +			uint32_t resid, pending_req_t *pending_req)
     3.9  {
    3.10  	vscsiif_response_t *ring_res;
    3.11  	struct vscsibk_info *info = pending_req->info;
    3.12 @@ -168,6 +168,8 @@ void scsiback_do_resp_with_sense(char *s
    3.13  		ring_res->sense_len = 0;
    3.14  	}
    3.15  
    3.16 +	ring_res->residual_len = resid;
    3.17 +
    3.18  	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&info->ring, notify);
    3.19  	if (info->ring.rsp_prod_pvt == info->ring.req_cons) {
    3.20  		RING_FINAL_CHECK_FOR_REQUESTS(&info->ring, more_to_do);
    3.21 @@ -209,8 +211,10 @@ static void scsiback_cmd_done(struct req
    3.22  {
    3.23  	pending_req_t *pending_req = req->end_io_data;
    3.24  	unsigned char *sense_buffer;
    3.25 +	unsigned int resid;
    3.26  
    3.27  	sense_buffer = req->sense;
    3.28 +	resid        = req->data_len;
    3.29  
    3.30  	if (errors != 0) {
    3.31  		if (log_print_stat)
    3.32 @@ -220,7 +224,7 @@ static void scsiback_cmd_done(struct req
    3.33  	scsiback_rsp_emulation(pending_req);
    3.34  
    3.35  	scsiback_fast_flush_area(pending_req);
    3.36 -	scsiback_do_resp_with_sense(sense_buffer, errors, pending_req);
    3.37 +	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req);
    3.38  	scsiback_put(pending_req->info);
    3.39  
    3.40  	__blk_put_request(req->q, req);
    3.41 @@ -473,7 +477,7 @@ static void scsiback_device_reset_exec(p
    3.42  	scsiback_get(info);
    3.43  	err = scsi_reset_provider(sdev, SCSI_TRY_RESET_DEVICE);
    3.44  
    3.45 -	scsiback_do_resp_with_sense(NULL, err, pending_req);
    3.46 +	scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
    3.47  	scsiback_put(info);
    3.48  
    3.49  	return;
    3.50 @@ -592,11 +596,11 @@ static int scsiback_do_cmd_fn(struct vsc
    3.51  						pending_req);
    3.52  		if (err == -EINVAL) {
    3.53  			scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24),
    3.54 -				pending_req);
    3.55 +				0, pending_req);
    3.56  			continue;
    3.57  		} else if (err == -ENODEV) {
    3.58  			scsiback_do_resp_with_sense(NULL, (DID_NO_CONNECT << 16),
    3.59 -				pending_req);
    3.60 +				0, pending_req);
    3.61  			continue;
    3.62  		}
    3.63  
    3.64 @@ -607,7 +611,7 @@ static int scsiback_do_cmd_fn(struct vsc
    3.65  		} else {
    3.66  			printk(KERN_ERR "scsiback: invalid parameter for request\n");
    3.67  			scsiback_do_resp_with_sense(NULL, (DRIVER_ERROR << 24),
    3.68 -				pending_req);
    3.69 +				0, pending_req);
    3.70  			continue;
    3.71  		}
    3.72  	}
     4.1 --- a/drivers/xen/scsifront/scsifront.c	Tue Jul 15 16:39:39 2008 +0100
     4.2 +++ b/drivers/xen/scsifront/scsifront.c	Wed Jul 16 11:19:14 2008 +0100
     4.3 @@ -147,7 +147,7 @@ static void scsifront_cdb_cmd_done(struc
     4.4  	add_id_to_freelist(info, id);
     4.5  
     4.6  	sc->result = ring_res->rslt;
     4.7 -	sc->resid  = 0;
     4.8 +	sc->resid  = ring_res->residual_len;
     4.9  
    4.10  	if (ring_res->sense_len > VSCSIIF_SENSE_BUFFERSIZE)
    4.11  		sense_len = VSCSIIF_SENSE_BUFFERSIZE;
     5.1 --- a/include/xen/interface/io/vscsiif.h	Tue Jul 15 16:39:39 2008 +0100
     5.2 +++ b/include/xen/interface/io/vscsiif.h	Wed Jul 16 11:19:14 2008 +0100
     5.3 @@ -84,7 +84,9 @@ struct vscsiif_response {
     5.4      uint8_t sense_len;
     5.5      uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
     5.6      int32_t rslt;
     5.7 -    uint32_t reserved[37];
     5.8 +    uint32_t residual_len;     /* request bufflen - 
     5.9 +                                  return the value from physical device */
    5.10 +    uint32_t reserved[36];
    5.11  };
    5.12  typedef struct vscsiif_response vscsiif_response_t;
    5.13