Commit 56851698 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley

[SCSI] iscsi: data digest page cache usage fix

Users can write to a page while we are sending it and making
digest calculations. This ends up causing us to retry the command
when a digest error is later reported. By using sock_no_sendpage
when data digests are calculated we can avoid a lot of (not all but it
helps) the retries becuase sock_no_sendpage is not zero copy.
Signed-off-by: default avatarAlex Aizman <itn780@yahoo.com>
Signed-off-by: default avatarDmitry Yusupov <dmitry_yus@yahoo.com>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 3e97c7e6
...@@ -1318,15 +1318,15 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) ...@@ -1318,15 +1318,15 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
* to use tcp_sendmsg(). * to use tcp_sendmsg().
*/ */
static inline int static inline int
iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
{ {
struct socket *sk = conn->sock;
int res; int res;
if ((int)buf->sg.offset >= 0) { if ((int)buf->sg.offset >= 0) {
int offset = buf->sg.offset + buf->sent; int offset = buf->sg.offset + buf->sent;
/* tcp_sendpage */ res = conn->sendpage(sk, buf->sg.page, offset, size, flags);
res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags);
} else { } else {
struct msghdr msg; struct msghdr msg;
...@@ -1354,7 +1354,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) ...@@ -1354,7 +1354,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
static inline int static inline int
iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
{ {
struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */ int flags = 0; /* MSG_DONTWAIT; */
int res, size; int res, size;
...@@ -1363,7 +1362,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) ...@@ -1363,7 +1362,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
if (buf->sent + size != buf->sg.length || datalen) if (buf->sent + size != buf->sg.length || datalen)
flags |= MSG_MORE; flags |= MSG_MORE;
res = iscsi_send(sk, buf, size, flags); res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
if (res >= 0) { if (res >= 0) {
conn->txdata_octets += res; conn->txdata_octets += res;
...@@ -1394,7 +1393,6 @@ static inline int ...@@ -1394,7 +1393,6 @@ static inline int
iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
int *count, int *sent) int *count, int *sent)
{ {
struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */ int flags = 0; /* MSG_DONTWAIT; */
int res, size; int res, size;
...@@ -1405,7 +1403,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, ...@@ -1405,7 +1403,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
if (buf->sent + size != buf->sg.length || *count != size) if (buf->sent + size != buf->sg.length || *count != size)
flags |= MSG_MORE; flags |= MSG_MORE;
res = iscsi_send(sk, buf, size, flags); res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
size, buf->sent, *count, *sent, res); size, buf->sent, *count, *sent, res);
if (res >= 0) { if (res >= 0) {
...@@ -2713,6 +2711,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, ...@@ -2713,6 +2711,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
*/ */
iscsi_conn_set_callbacks(conn); iscsi_conn_set_callbacks(conn);
conn->sendpage = conn->sock->ops->sendpage;
/* /*
* set receive state machine into initial state * set receive state machine into initial state
*/ */
...@@ -3467,6 +3467,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, ...@@ -3467,6 +3467,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
if (conn->data_rx_tfm) if (conn->data_rx_tfm)
crypto_free_tfm(conn->data_rx_tfm); crypto_free_tfm(conn->data_rx_tfm);
} }
conn->sendpage = conn->datadgst_en ?
sock_no_sendpage : conn->sock->ops->sendpage;
break; break;
case ISCSI_PARAM_INITIAL_R2T_EN: case ISCSI_PARAM_INITIAL_R2T_EN:
session->initial_r2t_en = value; session->initial_r2t_en = value;
......
...@@ -191,6 +191,8 @@ struct iscsi_conn { ...@@ -191,6 +191,8 @@ struct iscsi_conn {
uint32_t sendpage_failures_cnt; uint32_t sendpage_failures_cnt;
uint32_t discontiguous_hdr_cnt; uint32_t discontiguous_hdr_cnt;
uint32_t eh_abort_cnt; uint32_t eh_abort_cnt;
ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
}; };
struct iscsi_session { struct iscsi_session {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment