summaryrefslogtreecommitdiff
path: root/drivers/target
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-12-21 02:14:47 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-12-26 21:35:36 -0500
commit4113e47b3d0931879d75dc5ad7c4c294651b3c1d (patch)
tree27427469c37130ab26aa75ae40716413cbd161c8 /drivers/target
parentc9f2b6aeb92286f15ffc80d2ba16bc24e530f560 (diff)
iscsi_target: deal with short writes on the tx side
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c64
1 files changed, 24 insertions, 40 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index b5a1b4ccba12..a9ba2479374f 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1304,39 +1304,6 @@ static int iscsit_do_rx_data(
return total_rx;
}
-static int iscsit_do_tx_data(
- struct iscsi_conn *conn,
- struct iscsi_data_count *count)
-{
- int ret, iov_len;
- struct kvec *iov_p;
- struct msghdr msg;
-
- if (!conn || !conn->sock || !conn->conn_ops)
- return -1;
-
- if (count->data_length <= 0) {
- pr_err("Data length is: %d\n", count->data_length);
- return -1;
- }
-
- memset(&msg, 0, sizeof(struct msghdr));
-
- iov_p = count->iov;
- iov_len = count->iov_count;
-
- ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len,
- count->data_length);
- if (ret != count->data_length) {
- pr_err("Unexpected ret: %d send data %d\n",
- ret, count->data_length);
- return -EPIPE;
- }
- pr_debug("ret: %d, sent data: %d\n", ret, count->data_length);
-
- return ret;
-}
-
int rx_data(
struct iscsi_conn *conn,
struct kvec *iov,
@@ -1363,18 +1330,35 @@ int tx_data(
int iov_count,
int data)
{
- struct iscsi_data_count c;
+ struct msghdr msg;
+ int total_tx = 0;
if (!conn || !conn->sock || !conn->conn_ops)
return -1;
- memset(&c, 0, sizeof(struct iscsi_data_count));
- c.iov = iov;
- c.iov_count = iov_count;
- c.data_length = data;
- c.type = ISCSI_TX_DATA;
+ if (data <= 0) {
+ pr_err("Data length is: %d\n", data);
+ return -1;
+ }
+
+ memset(&msg, 0, sizeof(struct msghdr));
+
+ iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC,
+ iov, iov_count, data);
+
+ while (msg_data_left(&msg)) {
+ int tx_loop = sock_sendmsg(conn->sock, &msg);
+ if (tx_loop <= 0) {
+ pr_debug("tx_loop: %d total_tx %d\n",
+ tx_loop, total_tx);
+ return tx_loop;
+ }
+ total_tx += tx_loop;
+ pr_debug("tx_loop: %d, total_tx: %d, data: %d\n",
+ tx_loop, total_tx, data);
+ }
- return iscsit_do_tx_data(conn, &c);
+ return total_tx;
}
static bool sockaddr_equal(struct sockaddr_storage *x, struct sockaddr_storage *y)