aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-01-13 19:05:47 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-14 11:55:18 -0500
commit7cae5159dd2623300cf9820865bfbf6dcdb7c1b9 (patch)
tree68cd331b75515e90f79f4902de0620b293adcfd4
parent56851698c23430f0f291d6e50da344e6b414f3b9 (diff)
[SCSI] iscsi: add high mem support
From Mike Christie <michaelc@cs.wisc.edu> and FUJITA Tomonori <tomof@acm.org>: We cannot use page_address becuase some pages could be highmem. Instead, we can use sock_no_sendpage which does kmap for us. 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.c84
-rw-r--r--drivers/scsi/iscsi_tcp.h2
2 files changed, 31 insertions, 55 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 5e8b3135574c..0acc4b235d9b 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -87,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
87{ 87{
88 sg_init_one(&ibuf->sg, (u8 *)vbuf, size); 88 sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
89 ibuf->sent = 0; 89 ibuf->sent = 0;
90 ibuf->use_sendmsg = 0;
90} 91}
91 92
92static inline void 93static inline void
93iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) 94iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
94{ 95{
95 ibuf->sg.page = (void*)vbuf; 96 ibuf->sg.page = virt_to_page(vbuf);
96 ibuf->sg.offset = (unsigned int)-1; 97 ibuf->sg.offset = offset_in_page(vbuf);
97 ibuf->sg.length = size; 98 ibuf->sg.length = size;
98 ibuf->sent = 0; 99 ibuf->sent = 0;
99} 100 ibuf->use_sendmsg = 1;
100
101static inline void*
102iscsi_buf_iov_base(struct iscsi_buf *ibuf)
103{
104 return (char*)ibuf->sg.page + ibuf->sent;
105} 101}
106 102
107static inline void 103static inline void
108iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) 104iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
109{ 105{
106 ibuf->sg.page = sg->page;
107 ibuf->sg.offset = sg->offset;
108 ibuf->sg.length = sg->length;
110 /* 109 /*
111 * Fastpath: sg element fits into single page 110 * Fastpath: sg element fits into single page
112 */ 111 */
113 if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { 112 if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2)
114 ibuf->sg.page = sg->page; 113 ibuf->use_sendmsg = 0;
115 ibuf->sg.offset = sg->offset; 114 else
116 ibuf->sg.length = sg->length; 115 ibuf->use_sendmsg = 1;
117 } else
118 iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
119 ibuf->sent = 0; 116 ibuf->sent = 0;
120} 117}
121 118
@@ -1311,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
1311 * @buf: buffer to write from 1308 * @buf: buffer to write from
1312 * @size: actual size to write 1309 * @size: actual size to write
1313 * @flags: socket's flags 1310 * @flags: socket's flags
1314 *
1315 * Notes:
1316 * depending on buffer will use tcp_sendpage() or tcp_sendmsg().
1317 * buf->sg.offset == -1 tells us that buffer is non S/G and forces
1318 * to use tcp_sendmsg().
1319 */ 1311 */
1320static inline int 1312static inline int
1321iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) 1313iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
1322{ 1314{
1323 struct socket *sk = conn->sock; 1315 struct socket *sk = conn->sock;
1324 int res; 1316 int offset = buf->sg.offset + buf->sent;
1325
1326 if ((int)buf->sg.offset >= 0) {
1327 int offset = buf->sg.offset + buf->sent;
1328
1329 res = conn->sendpage(sk, buf->sg.page, offset, size, flags);
1330 } else {
1331 struct msghdr msg;
1332
1333 buf->iov.iov_base = iscsi_buf_iov_base(buf);
1334 buf->iov.iov_len = size;
1335
1336 memset(&msg, 0, sizeof(struct msghdr));
1337
1338 /* tcp_sendmsg */
1339 res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
1340 }
1341 1317
1342 return res; 1318 /*
1319 * if we got use_sg=0 or are sending something we kmallocd
1320 * then we did not have to do kmap (kmap returns page_address)
1321 *
1322 * if we got use_sg > 0, but had to drop down, we do not
1323 * set clustering so this should only happen for that
1324 * slab case.
1325 */
1326 if (buf->use_sendmsg)
1327 return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
1328 else
1329 return conn->sendpage(sk, buf->sg.page, offset, size, flags);
1343} 1330}
1344 1331
1345/** 1332/**
@@ -1431,19 +1418,6 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1431 ctask->digest_count = 4; 1418 ctask->digest_count = 4;
1432} 1419}
1433 1420
1434static inline void
1435iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
1436{
1437 struct scatterlist sg;
1438
1439 if (buf->sg.offset != -1)
1440 crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
1441 else {
1442 sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
1443 crypto_digest_update(conn->data_tx_tfm, &sg, 1);
1444 }
1445}
1446
1447static inline int 1421static inline int
1448iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, 1422iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1449 struct iscsi_buf *buf, uint32_t *digest, int final) 1423 struct iscsi_buf *buf, uint32_t *digest, int final)
@@ -1806,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1806 return -EAGAIN; 1780 return -EAGAIN;
1807 } 1781 }
1808 if (conn->datadgst_en) 1782 if (conn->datadgst_en)
1809 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 1783 crypto_digest_update(conn->data_tx_tfm,
1784 &ctask->sendbuf.sg, 1);
1810 1785
1811 if (!ctask->imm_count) 1786 if (!ctask->imm_count)
1812 break; 1787 break;
@@ -1891,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1891 * so pass it 1866 * so pass it
1892 */ 1867 */
1893 if (conn->datadgst_en && ctask->sent - start > 0) 1868 if (conn->datadgst_en && ctask->sent - start > 0)
1894 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 1869 crypto_digest_update(conn->data_tx_tfm,
1870 &ctask->sendbuf.sg, 1);
1895 1871
1896 if (!ctask->data_count) 1872 if (!ctask->data_count)
1897 break; 1873 break;
@@ -1969,7 +1945,7 @@ solicit_again:
1969 1945
1970 BUG_ON(r2t->data_count < 0); 1946 BUG_ON(r2t->data_count < 0);
1971 if (conn->datadgst_en) 1947 if (conn->datadgst_en)
1972 iscsi_buf_data_digest_update(conn, &r2t->sendbuf); 1948 crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
1973 1949
1974 if (r2t->data_count) { 1950 if (r2t->data_count) {
1975 BUG_ON(ctask->sc->use_sg == 0); 1951 BUG_ON(ctask->sc->use_sg == 0);
@@ -2051,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
2051 } 2027 }
2052 2028
2053 if (conn->datadgst_en) { 2029 if (conn->datadgst_en) {
2054 iscsi_buf_data_digest_update(conn, &ctask->sendbuf); 2030 crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
2055 /* imm data? */ 2031 /* imm data? */
2056 if (!dtask) { 2032 if (!dtask) {
2057 if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, 2033 if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index c8bb5b0bcb4b..f95e61b76f70 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -242,8 +242,8 @@ struct iscsi_session {
242 242
243struct iscsi_buf { 243struct iscsi_buf {
244 struct scatterlist sg; 244 struct scatterlist sg;
245 struct kvec iov;
246 unsigned int sent; 245 unsigned int sent;
246 char use_sendmsg;
247}; 247};
248 248
249struct iscsi_data_task { 249struct iscsi_data_task {