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>
This commit is contained in:
parent
310d40a973
commit
d96adb9b07
|
@ -827,7 +827,7 @@ cxgbit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cxgbit_skb_copy_to_sg(struct sk_buff *skb, struct scatterlist *sg,
|
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;
|
struct skb_seq_state st;
|
||||||
const u8 *buf;
|
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,
|
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];
|
struct scatterlist *sg = &cmd->se_cmd.t_data_sg[0];
|
||||||
u32 sg_nents = max(1UL, DIV_ROUND_UP(pdu_cb->dlen, PAGE_SIZE));
|
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;
|
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);
|
cmd->se_cmd.data_length);
|
||||||
|
|
||||||
if (!(pdu_cb->flags & PDUCBF_RX_DATA_DDPD)) {
|
if (!(pdu_cb->flags & PDUCBF_RX_DATA_DDPD)) {
|
||||||
|
u32 skip = data_offset % PAGE_SIZE;
|
||||||
|
|
||||||
sg_off = data_offset / PAGE_SIZE;
|
sg_off = data_offset / PAGE_SIZE;
|
||||||
sg_start = &cmd->se_cmd.t_data_sg[sg_off];
|
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:
|
check_payload:
|
||||||
|
|
Loading…
Reference in New Issue