diff options
| author | Varun Prakash <varun@chelsio.com> | 2017-07-29 21:01:49 +0530 | 
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2017-07-30 15:35:34 -0700 | 
| commit | d96adb9b076a12d30500347e2e667689062f44a0 (patch) | |
| tree | f9c294b8c5824a197899a712869eb425a1c8c688 | |
| parent | 310d40a973c560a24c79f84cb5f16dc540a05686 (diff) | |
cxgbit: fix sg_nents calculation
The current logic of calculating sg_nents can fail
if data_offset % PAGE_SIZE is not zero.
For example -
PAGE_SIZE = 4096
data_len = 3072
data_offset = 3072
As per current logic
sg_nents = max(1UL, DIV_ROUND_UP(data_len, PAGE_SIZE));
sg_nents = max(1UL, DIV_ROUND_UP(3072, 4096));
sg_nents = 1
But as data_offset % PAGE_SIZE = 3072 we should skip 3072 bytes
skip = 3K
sg_nents = max(1UL, DIV_ROUND_UP(3K(skip) + 3K(data_len), 4K(PAGE_SIZE));
sg_nents = 2;
This patch fixes this issue by adding skip to data_len.
Signed-off-by: Varun Prakash <varun@chelsio.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
| -rw-r--r-- | drivers/target/iscsi/cxgbit/cxgbit_target.c | 12 | 
1 files changed, 7 insertions, 5 deletions
| diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index dda13f1af38e..514986b57c2d 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -827,7 +827,7 @@ cxgbit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,  static void  cxgbit_skb_copy_to_sg(struct sk_buff *skb, struct scatterlist *sg, -		      unsigned int nents) +		      unsigned int nents, u32 skip)  {  	struct skb_seq_state st;  	const u8 *buf; @@ -846,7 +846,7 @@ cxgbit_skb_copy_to_sg(struct sk_buff *skb, struct scatterlist *sg,  		}  		consumed += sg_pcopy_from_buffer(sg, nents, (void *)buf, -						 buf_len, consumed); +						 buf_len, skip + consumed);  	}  } @@ -912,7 +912,7 @@ cxgbit_handle_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,  		struct scatterlist *sg = &cmd->se_cmd.t_data_sg[0];  		u32 sg_nents = max(1UL, DIV_ROUND_UP(pdu_cb->dlen, PAGE_SIZE)); -		cxgbit_skb_copy_to_sg(csk->skb, sg, sg_nents); +		cxgbit_skb_copy_to_sg(csk->skb, sg, sg_nents, 0);  	}  	cmd->write_data_done += pdu_cb->dlen; @@ -1069,11 +1069,13 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)  		  cmd->se_cmd.data_length);  	if (!(pdu_cb->flags & PDUCBF_RX_DATA_DDPD)) { +		u32 skip = data_offset % PAGE_SIZE; +  		sg_off = data_offset / PAGE_SIZE;  		sg_start = &cmd->se_cmd.t_data_sg[sg_off]; -		sg_nents = max(1UL, DIV_ROUND_UP(data_len, PAGE_SIZE)); +		sg_nents = max(1UL, DIV_ROUND_UP(skip + data_len, PAGE_SIZE)); -		cxgbit_skb_copy_to_sg(csk->skb, sg_start, sg_nents); +		cxgbit_skb_copy_to_sg(csk->skb, sg_start, sg_nents, skip);  	}  check_payload: | 
