From 46ada095476bc850daadb487e942d2c9a334437d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 11 Jun 2015 16:59:15 +0000 Subject: [PATCH] iscsi-scst: Update for kernel 3.19 (merge r6187 from the trunk) git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.0.x@6282 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/conn.c | 2 +- iscsi-scst/kernel/iscsi.c | 60 ++++++++++++++++++----------- iscsi-scst/kernel/iscsi.h | 6 ++- iscsi-scst/kernel/nthread.c | 77 +++++++++++++++++++++++-------------- 4 files changed, 92 insertions(+), 53 deletions(-) diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index fce3daa96..6f2f36b5a 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -932,7 +932,7 @@ int iscsi_conn_alloc(struct iscsi_session *session, conn->transport = t; /* Changing it, change ISCSI_CONN_IOV_MAX as well !! */ - conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL); + conn->read_iov = (void *)get_zeroed_page(GFP_KERNEL); if (conn->read_iov == NULL) { res = -ENOMEM; goto out_err_free_conn; diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index e4ad114ad..d96c03302 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -1451,7 +1451,7 @@ static void cmnd_prepare_get_rejected_immed_data(struct iscsi_cmnd *cmnd) struct iscsi_conn *conn = cmnd->conn; struct scatterlist *sg = cmnd->sg; char *addr; - u32 size; + u32 size, s, e; unsigned int i; TRACE_ENTRY(); @@ -1485,17 +1485,21 @@ static void cmnd_prepare_get_rejected_immed_data(struct iscsi_cmnd *cmnd) } addr = page_address(sg_page(&sg[0])); - conn->read_size = size; - for (i = 0; size > PAGE_SIZE; i++, size -= PAGE_SIZE) { + for (s = size, i = 0; s > 0; i++, s -= e) { /* We already checked pdu.datasize in check_segment_length() */ sBUG_ON(i >= ISCSI_CONN_IOV_MAX); - conn->read_iov[i].iov_base = (void __force __user *)addr; - conn->read_iov[i].iov_len = PAGE_SIZE; + conn->read_iov[i].iov_base = addr; + e = min_t(u32, s, PAGE_SIZE); + conn->read_iov[i].iov_len = e; } - conn->read_iov[i].iov_base = (void __force __user *)addr; - conn->read_iov[i].iov_len = size; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + iov_iter_kvec(&conn->read_msg.msg_iter, READ | ITER_KVEC, + conn->read_iov, i, size); +#else conn->read_msg.msg_iov = conn->read_iov; - conn->read_msg.msg_iovlen = ++i; + conn->read_msg.msg_iovlen = i; + conn->read_size = size; +#endif out: TRACE_EXIT(); @@ -1576,6 +1580,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, struct scatterlist *sg = cmd->sg; unsigned int bufflen = cmd->bufflen; unsigned int idx, i, buff_offs; + const u32 read_size = size; int res = 0; TRACE_ENTRY(); @@ -1590,9 +1595,6 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, idx = offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; - conn->read_msg.msg_iov = conn->read_iov; - conn->read_size = size; - i = 0; while (1) { unsigned int sg_len; @@ -1610,13 +1612,12 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, EXTRACHECKS_BUG_ON(addr == NULL); sg_len = sg[idx].offset + sg[idx].length - offset; - conn->read_iov[i].iov_base = (void __force __user *)addr + offset; + conn->read_iov[i].iov_base = addr + offset; if (size <= sg_len) { TRACE_DBG("idx=%d, i=%d, offset=%u, size=%d, addr=%p", idx, i, offset, size, addr); conn->read_iov[i].iov_len = size; - conn->read_msg.msg_iovlen = i+1; break; } conn->read_iov[i].iov_len = sg_len; @@ -1635,16 +1636,26 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn, size); mark_conn_closed(conn); res = -EINVAL; - break; + goto out; } idx++; offset = 0; } - TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", - conn->read_msg.msg_iov, conn->read_msg.msg_iovlen); + i++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + iov_iter_kvec(&conn->read_msg.msg_iter, READ | ITER_KVEC, + conn->read_iov, i, read_size); +#else + conn->read_msg.msg_iov = conn->read_iov; + conn->read_msg.msg_iovlen = i; + conn->read_size = read_size; +#endif + TRACE_DBG("msg_iov=%p, msg_iovlen=%u", conn->read_iov, i); + +out: TRACE_EXIT_RES(res); return res; } @@ -1784,7 +1795,6 @@ static int nop_out_start(struct iscsi_cmnd *cmnd) size = cmnd->pdu.datasize; if (size && !conn->session->sess_params.rdma_extensions) { - conn->read_msg.msg_iov = conn->read_iov; if (cmnd->pdu.bhs.itt != ISCSI_RESERVED_TAG) { struct scatterlist *sg; @@ -1805,10 +1815,9 @@ static int nop_out_start(struct iscsi_cmnd *cmnd) for (i = 0; i < cmnd->sg_cnt; i++) { conn->read_iov[i].iov_base = - (void __force __user *)(page_address(sg_page(&sg[i]))); + page_address(sg_page(&sg[i])); tmp = min_t(u32, size, PAGE_SIZE); conn->read_iov[i].iov_len = tmp; - conn->read_size += tmp; size -= tmp; } sBUG_ON(size != 0); @@ -1820,10 +1829,9 @@ static int nop_out_start(struct iscsi_cmnd *cmnd) */ for (i = 0; i < (signed)ISCSI_CONN_IOV_MAX; i++) { conn->read_iov[i].iov_base = - (void __force __user *)(page_address(dummy_page)); + page_address(dummy_page); tmp = min_t(u32, size, PAGE_SIZE); conn->read_iov[i].iov_len = tmp; - conn->read_size += tmp; size -= tmp; } @@ -1831,9 +1839,15 @@ static int nop_out_start(struct iscsi_cmnd *cmnd) sBUG_ON(size != 0); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + iov_iter_kvec(&conn->read_msg.msg_iter, READ | ITER_KVEC, + conn->read_iov, i, cmnd->pdu.datasize); +#else + conn->read_msg.msg_iov = conn->read_iov; conn->read_msg.msg_iovlen = i; - TRACE_DBG("msg_iov=%p, msg_iovlen=%zd", conn->read_msg.msg_iov, - conn->read_msg.msg_iovlen); + conn->read_size = cmnd->pdu.datasize; +#endif + TRACE_DBG("msg_iov=%p, msg_iovlen=%d", conn->read_iov, i); } out: diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index 3e3c8f18c..8c7db3c7a 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -289,9 +289,13 @@ struct iscsi_conn { */ struct iscsi_cmnd *read_cmnd; struct msghdr read_msg; - u32 read_size; int read_state; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + struct kvec *read_iov; +#else + u32 read_size; struct iovec *read_iov; +#endif struct task_struct *rx_task; uint32_t rpadding; diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index bb1dd9d53..8d2597b7d 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -618,11 +618,16 @@ EXPORT_SYMBOL(start_close_conn); static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, size_t len) { - conn->read_iov[0].iov_base = (void __force __user *)data; + conn->read_iov[0].iov_base = data; conn->read_iov[0].iov_len = len; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + iov_iter_kvec(&conn->read_msg.msg_iter, READ | ITER_KVEC, + conn->read_iov, 1, len); +#else conn->read_msg.msg_iov = conn->read_iov; conn->read_msg.msg_iovlen = 1; conn->read_size = len; +#endif return; } @@ -684,8 +689,12 @@ static int do_recv(struct iscsi_conn *conn) { int res; mm_segment_t oldfs; - struct msghdr msg; + struct msghdr *msg; + int read_size; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) + struct iovec *first_iov; int first_len; +#endif EXTRACHECKS_BUG_ON(conn->read_cmnd == NULL); @@ -701,45 +710,48 @@ static int do_recv(struct iscsi_conn *conn) */ restart: - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = conn->read_msg.msg_iov; - msg.msg_iovlen = conn->read_msg.msg_iovlen; - first_len = msg.msg_iov->iov_len; + msg = &conn->read_msg; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + read_size = msg->msg_iter.count; +#else + read_size = conn->read_size; + first_iov = msg->msg_iov; + first_len = first_iov->iov_len; +#endif oldfs = get_fs(); set_fs(get_ds()); - res = sock_recvmsg(conn->sock, &msg, conn->read_size, + res = sock_recvmsg(conn->sock, msg, read_size, MSG_DONTWAIT | MSG_NOSIGNAL); set_fs(oldfs); - TRACE_DBG("msg_iovlen %zd, first_len %d, read_size %d, res %d", - msg.msg_iovlen, first_len, conn->read_size, res); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + TRACE_DBG("nr_segs %zd, bytes_left %zd, res %d", + msg->msg_iter.nr_segs, msg->msg_iter.count, res); +#else + TRACE_DBG("msg_iovlen %zd, read_size %d, res %d", msg->msg_iovlen, + read_size, res); +#endif if (res > 0) { /* - * To save some considerable effort and CPU power we - * suppose that TCP functions adjust - * conn->read_msg.msg_iov and conn->read_msg.msg_iovlen - * on amount of copied data. This BUG_ON is intended - * to catch if it is changed in the future. + * To save CPU cycles we suppose that sock_recvmsg() adjusts + * msg->msg_iov and msg->msg_iovlen. The BUG_ON() statements + * below verifies this. */ - sBUG_ON((res >= first_len) && - (conn->read_msg.msg_iov->iov_len != 0)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + sBUG_ON(msg->msg_iter.count + res != read_size); + res = msg->msg_iter.count; +#else + sBUG_ON((res >= first_len) && (first_iov->iov_len != 0)); conn->read_size -= res; - if (conn->read_size != 0) { - if (res >= first_len) { - int done = 1 + ((res - first_len) >> PAGE_SHIFT); - TRACE_DBG("done %d", done); - conn->read_msg.msg_iov += done; - conn->read_msg.msg_iovlen -= done; - } - } res = conn->read_size; +#endif } else { switch (res) { case -EAGAIN: TRACE_DBG("EAGAIN received for conn %p", conn); - res = conn->read_size; + res = read_size; break; case -ERESTARTSYS: TRACE_DBG("ERESTARTSYS received for conn %p", conn); @@ -825,7 +837,7 @@ static int iscsi_rx_check_ddigest(struct iscsi_conn *conn) static int process_read_io(struct iscsi_conn *conn, int *closed) { struct iscsi_cmnd *cmnd = conn->read_cmnd; - int res; + int bytes_left, res; TRACE_ENTRY(); @@ -913,10 +925,15 @@ static int process_read_io(struct iscsi_conn *conn, int *closed) break; case RX_END: - if (unlikely(conn->read_size != 0)) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + bytes_left = conn->read_msg.msg_iter.count; +#else + bytes_left = conn->read_size; +#endif + if (unlikely(bytes_left != 0)) { PRINT_CRIT_ERROR("conn read_size !=0 on RX_END " "(conn %p, op %x, read_size %d)", conn, - cmnd_opcode(cmnd), conn->read_size); + cmnd_opcode(cmnd), bytes_left); sBUG(); } conn->read_cmnd = NULL; @@ -924,7 +941,11 @@ static int process_read_io(struct iscsi_conn *conn, int *closed) cmnd_rx_end(cmnd); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + EXTRACHECKS_BUG_ON(conn->read_msg.msg_iter.count != 0); +#else EXTRACHECKS_BUG_ON(conn->read_size != 0); +#endif /* * To maintain fairness. Res must be 0 here anyway, the