diff options
author | FUJITA Tomonori <tomof@acm.org> | 2006-01-13 19:05:44 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2006-01-14 11:55:17 -0500 |
commit | 56851698c23430f0f291d6e50da344e6b414f3b9 (patch) | |
tree | e051fccf90003b6057c961b1b954725f38413d02 | |
parent | 3e97c7e6cda933e3a1b518a8100d155c532a3cfc (diff) |
[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: Alex Aizman <itn780@yahoo.com>
Signed-off-by: Dmitry Yusupov <dmitry_yus@yahoo.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 16 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 2 |
2 files changed, 11 insertions, 7 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index cd1491e52361..5e8b3135574c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -1318,15 +1318,15 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) | |||
1318 | * to use tcp_sendmsg(). | 1318 | * to use tcp_sendmsg(). |
1319 | */ | 1319 | */ |
1320 | static inline int | 1320 | static inline int |
1321 | iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | 1321 | iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) |
1322 | { | 1322 | { |
1323 | struct socket *sk = conn->sock; | ||
1323 | int res; | 1324 | int res; |
1324 | 1325 | ||
1325 | if ((int)buf->sg.offset >= 0) { | 1326 | if ((int)buf->sg.offset >= 0) { |
1326 | int offset = buf->sg.offset + buf->sent; | 1327 | int offset = buf->sg.offset + buf->sent; |
1327 | 1328 | ||
1328 | /* tcp_sendpage */ | 1329 | res = conn->sendpage(sk, buf->sg.page, offset, size, flags); |
1329 | res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags); | ||
1330 | } else { | 1330 | } else { |
1331 | struct msghdr msg; | 1331 | struct msghdr msg; |
1332 | 1332 | ||
@@ -1354,7 +1354,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | |||
1354 | static inline int | 1354 | static inline int |
1355 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | 1355 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) |
1356 | { | 1356 | { |
1357 | struct socket *sk = conn->sock; | ||
1358 | int flags = 0; /* MSG_DONTWAIT; */ | 1357 | int flags = 0; /* MSG_DONTWAIT; */ |
1359 | int res, size; | 1358 | int res, size; |
1360 | 1359 | ||
@@ -1363,7 +1362,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | |||
1363 | if (buf->sent + size != buf->sg.length || datalen) | 1362 | if (buf->sent + size != buf->sg.length || datalen) |
1364 | flags |= MSG_MORE; | 1363 | flags |= MSG_MORE; |
1365 | 1364 | ||
1366 | res = iscsi_send(sk, buf, size, flags); | 1365 | res = iscsi_send(conn, buf, size, flags); |
1367 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); | 1366 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); |
1368 | if (res >= 0) { | 1367 | if (res >= 0) { |
1369 | conn->txdata_octets += res; | 1368 | conn->txdata_octets += res; |
@@ -1394,7 +1393,6 @@ static inline int | |||
1394 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | 1393 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, |
1395 | int *count, int *sent) | 1394 | int *count, int *sent) |
1396 | { | 1395 | { |
1397 | struct socket *sk = conn->sock; | ||
1398 | int flags = 0; /* MSG_DONTWAIT; */ | 1396 | int flags = 0; /* MSG_DONTWAIT; */ |
1399 | int res, size; | 1397 | int res, size; |
1400 | 1398 | ||
@@ -1405,7 +1403,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
1405 | if (buf->sent + size != buf->sg.length || *count != size) | 1403 | if (buf->sent + size != buf->sg.length || *count != size) |
1406 | flags |= MSG_MORE; | 1404 | flags |= MSG_MORE; |
1407 | 1405 | ||
1408 | res = iscsi_send(sk, buf, size, flags); | 1406 | res = iscsi_send(conn, buf, size, flags); |
1409 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", | 1407 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", |
1410 | size, buf->sent, *count, *sent, res); | 1408 | size, buf->sent, *count, *sent, res); |
1411 | if (res >= 0) { | 1409 | if (res >= 0) { |
@@ -2713,6 +2711,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, | |||
2713 | */ | 2711 | */ |
2714 | iscsi_conn_set_callbacks(conn); | 2712 | iscsi_conn_set_callbacks(conn); |
2715 | 2713 | ||
2714 | conn->sendpage = conn->sock->ops->sendpage; | ||
2715 | |||
2716 | /* | 2716 | /* |
2717 | * set receive state machine into initial state | 2717 | * set receive state machine into initial state |
2718 | */ | 2718 | */ |
@@ -3467,6 +3467,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, | |||
3467 | if (conn->data_rx_tfm) | 3467 | if (conn->data_rx_tfm) |
3468 | crypto_free_tfm(conn->data_rx_tfm); | 3468 | crypto_free_tfm(conn->data_rx_tfm); |
3469 | } | 3469 | } |
3470 | conn->sendpage = conn->datadgst_en ? | ||
3471 | sock_no_sendpage : conn->sock->ops->sendpage; | ||
3470 | break; | 3472 | break; |
3471 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3473 | case ISCSI_PARAM_INITIAL_R2T_EN: |
3472 | session->initial_r2t_en = value; | 3474 | session->initial_r2t_en = value; |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 9badafe8820d..c8bb5b0bcb4b 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
@@ -191,6 +191,8 @@ struct iscsi_conn { | |||
191 | uint32_t sendpage_failures_cnt; | 191 | uint32_t sendpage_failures_cnt; |
192 | uint32_t discontiguous_hdr_cnt; | 192 | uint32_t discontiguous_hdr_cnt; |
193 | uint32_t eh_abort_cnt; | 193 | uint32_t eh_abort_cnt; |
194 | |||
195 | ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); | ||
194 | }; | 196 | }; |
195 | 197 | ||
196 | struct iscsi_session { | 198 | struct iscsi_session { |