Commit 69fd110e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.sendmsg' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs sendmsg updates from Al Viro:
 "More sendmsg work.

  This is a fairly separate isolated stuff (there's a continuation
  around lustre, but that one was too late to soak in -next), thus the
  separate pull request"

* 'work.sendmsg' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  ncpfs: switch to sock_sendmsg()
  ncpfs: don't mess with manually advancing iovec on send
  ncpfs: sendmsg does *not* bugger iovec these days
  ceph_tcp_sendpage(): use ITER_BVEC sendmsg
  afs_send_pages(): use ITER_BVEC
  rds: remove dead code
  ceph: switch to sock_recvmsg()
  usbip_recv(): switch to sock_recvmsg()
  iscsi_target: deal with short writes on the tx side
  [nbd] pass iov_iter to nbd_xmit()
  [nbd] switch sock_xmit() to sock_{send,recv}msg()
  [drbd] use sock_sendmsg()
parents 821fd6f6 4038a2a3
...@@ -1846,7 +1846,7 @@ int drbd_send_out_of_sync(struct drbd_peer_device *peer_device, struct drbd_requ ...@@ -1846,7 +1846,7 @@ int drbd_send_out_of_sync(struct drbd_peer_device *peer_device, struct drbd_requ
int drbd_send(struct drbd_connection *connection, struct socket *sock, int drbd_send(struct drbd_connection *connection, struct socket *sock,
void *buf, size_t size, unsigned msg_flags) void *buf, size_t size, unsigned msg_flags)
{ {
struct kvec iov; struct kvec iov = {.iov_base = buf, .iov_len = size};
struct msghdr msg; struct msghdr msg;
int rv, sent = 0; int rv, sent = 0;
...@@ -1855,15 +1855,14 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, ...@@ -1855,15 +1855,14 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
/* THINK if (signal_pending) return ... ? */ /* THINK if (signal_pending) return ... ? */
iov.iov_base = buf;
iov.iov_len = size;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL; msg.msg_flags = msg_flags | MSG_NOSIGNAL;
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, size);
if (sock == connection->data.socket) { if (sock == connection->data.socket) {
rcu_read_lock(); rcu_read_lock();
connection->ko_count = rcu_dereference(connection->net_conf)->ko_count; connection->ko_count = rcu_dereference(connection->net_conf)->ko_count;
...@@ -1871,7 +1870,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, ...@@ -1871,7 +1870,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
drbd_update_congested(connection); drbd_update_congested(connection);
} }
do { do {
rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); rv = sock_sendmsg(sock, &msg);
if (rv == -EAGAIN) { if (rv == -EAGAIN) {
if (we_should_drop_the_connection(connection, sock)) if (we_should_drop_the_connection(connection, sock))
break; break;
...@@ -1885,8 +1884,6 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, ...@@ -1885,8 +1884,6 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
if (rv < 0) if (rv < 0)
break; break;
sent += rv; sent += rv;
iov.iov_base += rv;
iov.iov_len -= rv;
} while (sent < size); } while (sent < size);
if (sock == connection->data.socket) if (sock == connection->data.socket)
......
...@@ -201,13 +201,12 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, ...@@ -201,13 +201,12 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
/* /*
* Send or receive packet. * Send or receive packet.
*/ */
static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf, static int sock_xmit(struct nbd_device *nbd, int index, int send,
int size, int msg_flags) struct iov_iter *iter, int msg_flags)
{ {
struct socket *sock = nbd->socks[index]->sock; struct socket *sock = nbd->socks[index]->sock;
int result; int result;
struct msghdr msg; struct msghdr msg;
struct kvec iov;
unsigned long pflags = current->flags; unsigned long pflags = current->flags;
if (unlikely(!sock)) { if (unlikely(!sock)) {
...@@ -217,11 +216,11 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf, ...@@ -217,11 +216,11 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
return -EINVAL; return -EINVAL;
} }
msg.msg_iter = *iter;
current->flags |= PF_MEMALLOC; current->flags |= PF_MEMALLOC;
do { do {
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
iov.iov_base = buf;
iov.iov_len = size;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_control = NULL; msg.msg_control = NULL;
...@@ -229,47 +228,37 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf, ...@@ -229,47 +228,37 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
msg.msg_flags = msg_flags | MSG_NOSIGNAL; msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (send) if (send)
result = kernel_sendmsg(sock, &msg, &iov, 1, size); result = sock_sendmsg(sock, &msg);
else else
result = kernel_recvmsg(sock, &msg, &iov, 1, size, result = sock_recvmsg(sock, &msg, msg.msg_flags);
msg.msg_flags);
if (result <= 0) { if (result <= 0) {
if (result == 0) if (result == 0)
result = -EPIPE; /* short read */ result = -EPIPE; /* short read */
break; break;
} }
size -= result; } while (msg_data_left(&msg));
buf += result;
} while (size > 0);
tsk_restore_flags(current, pflags, PF_MEMALLOC); tsk_restore_flags(current, pflags, PF_MEMALLOC);
return result; return result;
} }
static inline int sock_send_bvec(struct nbd_device *nbd, int index,
struct bio_vec *bvec, int flags)
{
int result;
void *kaddr = kmap(bvec->bv_page);
result = sock_xmit(nbd, index, 1, kaddr + bvec->bv_offset,
bvec->bv_len, flags);
kunmap(bvec->bv_page);
return result;
}
/* always call with the tx_lock held */ /* always call with the tx_lock held */
static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
{ {
struct request *req = blk_mq_rq_from_pdu(cmd); struct request *req = blk_mq_rq_from_pdu(cmd);
int result; int result;
struct nbd_request request; struct nbd_request request = {.magic = htonl(NBD_REQUEST_MAGIC)};
struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)};
struct iov_iter from;
unsigned long size = blk_rq_bytes(req); unsigned long size = blk_rq_bytes(req);
struct bio *bio; struct bio *bio;
u32 type; u32 type;
u32 tag = blk_mq_unique_tag(req); u32 tag = blk_mq_unique_tag(req);
iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
switch (req_op(req)) { switch (req_op(req)) {
case REQ_OP_DISCARD: case REQ_OP_DISCARD:
type = NBD_CMD_TRIM; type = NBD_CMD_TRIM;
...@@ -294,8 +283,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) ...@@ -294,8 +283,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return -EIO; return -EIO;
} }
memset(&request, 0, sizeof(request));
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(type); request.type = htonl(type);
if (type != NBD_CMD_FLUSH) { if (type != NBD_CMD_FLUSH) {
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
...@@ -306,7 +293,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) ...@@ -306,7 +293,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n", dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n",
cmd, nbdcmd_to_ascii(type), cmd, nbdcmd_to_ascii(type),
(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req)); (unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req));
result = sock_xmit(nbd, index, 1, &request, sizeof(request), result = sock_xmit(nbd, index, 1, &from,
(type == NBD_CMD_WRITE) ? MSG_MORE : 0); (type == NBD_CMD_WRITE) ? MSG_MORE : 0);
if (result <= 0) { if (result <= 0) {
dev_err_ratelimited(disk_to_dev(nbd->disk), dev_err_ratelimited(disk_to_dev(nbd->disk),
...@@ -329,7 +316,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) ...@@ -329,7 +316,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n", dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
cmd, bvec.bv_len); cmd, bvec.bv_len);
result = sock_send_bvec(nbd, index, &bvec, flags); iov_iter_bvec(&from, ITER_BVEC | WRITE,
&bvec, 1, bvec.bv_len);
result = sock_xmit(nbd, index, 1, &from, flags);
if (result <= 0) { if (result <= 0) {
dev_err(disk_to_dev(nbd->disk), dev_err(disk_to_dev(nbd->disk),
"Send data failed (result %d)\n", "Send data failed (result %d)\n",
...@@ -350,17 +339,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) ...@@ -350,17 +339,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return 0; return 0;
} }
static inline int sock_recv_bvec(struct nbd_device *nbd, int index,
struct bio_vec *bvec)
{
int result;
void *kaddr = kmap(bvec->bv_page);
result = sock_xmit(nbd, index, 0, kaddr + bvec->bv_offset,
bvec->bv_len, MSG_WAITALL);
kunmap(bvec->bv_page);
return result;
}
/* NULL returned = something went wrong, inform userspace */ /* NULL returned = something went wrong, inform userspace */
static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
{ {
...@@ -370,9 +348,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) ...@@ -370,9 +348,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
struct request *req = NULL; struct request *req = NULL;
u16 hwq; u16 hwq;
u32 tag; u32 tag;
struct kvec iov = {.iov_base = &reply, .iov_len = sizeof(reply)};
struct iov_iter to;
reply.magic = 0; reply.magic = 0;
result = sock_xmit(nbd, index, 0, &reply, sizeof(reply), MSG_WAITALL); iov_iter_kvec(&to, READ | ITER_KVEC, &iov, 1, sizeof(reply));
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL);
if (result <= 0) { if (result <= 0) {
if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) && if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
!test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags)) !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
...@@ -412,7 +393,9 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index) ...@@ -412,7 +393,9 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
struct bio_vec bvec; struct bio_vec bvec;
rq_for_each_segment(bvec, req, iter) { rq_for_each_segment(bvec, req, iter) {
result = sock_recv_bvec(nbd, index, &bvec); iov_iter_bvec(&to, ITER_BVEC | READ,
&bvec, 1, bvec.bv_len);
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL);
if (result <= 0) { if (result <= 0) {
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n", dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
result); result);
...@@ -641,14 +624,17 @@ static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) ...@@ -641,14 +624,17 @@ static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev)
static void send_disconnects(struct nbd_device *nbd) static void send_disconnects(struct nbd_device *nbd)
{ {
struct nbd_request request = {}; struct nbd_request request = {
.magic = htonl(NBD_REQUEST_MAGIC),
.type = htonl(NBD_CMD_DISC),
};
struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)};
struct iov_iter from;
int i, ret; int i, ret;
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(NBD_CMD_DISC);
for (i = 0; i < nbd->num_connections; i++) { for (i = 0; i < nbd->num_connections; i++) {
ret = sock_xmit(nbd, i, 1, &request, sizeof(request), 0); iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
ret = sock_xmit(nbd, i, 1, &from, 0);
if (ret <= 0) if (ret <= 0)
dev_err(disk_to_dev(nbd->disk), dev_err(disk_to_dev(nbd->disk),
"Send disconnect failed %d\n", ret); "Send disconnect failed %d\n", ret);
......
...@@ -1305,39 +1305,6 @@ static int iscsit_do_rx_data( ...@@ -1305,39 +1305,6 @@ static int iscsit_do_rx_data(
return total_rx; 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( int rx_data(
struct iscsi_conn *conn, struct iscsi_conn *conn,
struct kvec *iov, struct kvec *iov,
...@@ -1364,18 +1331,35 @@ int tx_data( ...@@ -1364,18 +1331,35 @@ int tx_data(
int iov_count, int iov_count,
int data) int data)
{ {
struct iscsi_data_count c; struct msghdr msg;
int total_tx = 0;
if (!conn || !conn->sock || !conn->conn_ops) if (!conn || !conn->sock || !conn->conn_ops)
return -1; return -1;
memset(&c, 0, sizeof(struct iscsi_data_count)); if (data <= 0) {
c.iov = iov; pr_err("Data length is: %d\n", data);
c.iov_count = iov_count; return -1;
c.data_length = data; }
c.type = ISCSI_TX_DATA;
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;
} }
void iscsit_collect_login_stats( void iscsit_collect_login_stats(
......
...@@ -327,13 +327,11 @@ EXPORT_SYMBOL_GPL(usbip_dump_header); ...@@ -327,13 +327,11 @@ EXPORT_SYMBOL_GPL(usbip_dump_header);
int usbip_recv(struct socket *sock, void *buf, int size) int usbip_recv(struct socket *sock, void *buf, int size)
{ {
int result; int result;
struct msghdr msg; struct kvec iov = {.iov_base = buf, .iov_len = size};
struct kvec iov; struct msghdr msg = {.msg_flags = MSG_NOSIGNAL};
int total = 0; int total = 0;
/* for blocks of if (usbip_dbg_flag_xmit) */ iov_iter_kvec(&msg.msg_iter, READ|ITER_KVEC, &iov, 1, size);
char *bp = buf;
int osize = size;
usbip_dbg_xmit("enter\n"); usbip_dbg_xmit("enter\n");
...@@ -344,26 +342,18 @@ int usbip_recv(struct socket *sock, void *buf, int size) ...@@ -344,26 +342,18 @@ int usbip_recv(struct socket *sock, void *buf, int size)
} }
do { do {
int sz = msg_data_left(&msg);
sock->sk->sk_allocation = GFP_NOIO; sock->sk->sk_allocation = GFP_NOIO;
iov.iov_base = buf;
iov.iov_len = size; result = sock_recvmsg(sock, &msg, MSG_WAITALL);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = MSG_NOSIGNAL;
result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
if (result <= 0) { if (result <= 0) {
pr_debug("receive sock %p buf %p size %u ret %d total %d\n", pr_debug("receive sock %p buf %p size %u ret %d total %d\n",
sock, buf, size, result, total); sock, buf + total, sz, result, total);
goto err; goto err;
} }
size -= result;
buf += result;
total += result; total += result;
} while (size > 0); } while (msg_data_left(&msg));
if (usbip_dbg_flag_xmit) { if (usbip_dbg_flag_xmit) {
if (!in_interrupt()) if (!in_interrupt())
...@@ -372,9 +362,9 @@ int usbip_recv(struct socket *sock, void *buf, int size) ...@@ -372,9 +362,9 @@ int usbip_recv(struct socket *sock, void *buf, int size)
pr_debug("interrupt :"); pr_debug("interrupt :");
pr_debug("receiving....\n"); pr_debug("receiving....\n");
usbip_dump_buffer(bp, osize); usbip_dump_buffer(buf, size);
pr_debug("received, osize %d ret %d size %d total %d\n", pr_debug("received, osize %d ret %d size %zd total %d\n",
osize, result, size, total); size, result, msg_data_left(&msg), total);
} }
return total; return total;
......
...@@ -260,8 +260,7 @@ void afs_flat_call_destructor(struct afs_call *call) ...@@ -260,8 +260,7 @@ void afs_flat_call_destructor(struct afs_call *call)
/* /*
* attach the data from a bunch of pages on an inode to a call * attach the data from a bunch of pages on an inode to a call
*/ */
static int afs_send_pages(struct afs_call *call, struct msghdr *msg, static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
struct kvec *iov)
{ {
struct page *pages[8]; struct page *pages[8];
unsigned count, n, loop, offset, to; unsigned count, n, loop, offset, to;
...@@ -284,20 +283,21 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg, ...@@ -284,20 +283,21 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
loop = 0; loop = 0;
do { do {
struct bio_vec bvec = {.bv_page = pages[loop],
.bv_offset = offset};
msg->msg_flags = 0; msg->msg_flags = 0;
to = PAGE_SIZE; to = PAGE_SIZE;
if (first + loop >= last) if (first + loop >= last)
to = call->last_to; to = call->last_to;
else else
msg->msg_flags = MSG_MORE; msg->msg_flags = MSG_MORE;
iov->iov_base = kmap(pages[loop]) + offset; bvec.bv_len = to - offset;
iov->iov_len = to - offset;
offset = 0; offset = 0;
_debug("- range %u-%u%s", _debug("- range %u-%u%s",
offset, to, msg->msg_flags ? " [more]" : ""); offset, to, msg->msg_flags ? " [more]" : "");
iov_iter_kvec(&msg->msg_iter, WRITE | ITER_KVEC, iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC,
iov, 1, to - offset); &bvec, 1, to - offset);
/* have to change the state *before* sending the last /* have to change the state *before* sending the last
* packet as RxRPC might give us the reply before it * packet as RxRPC might give us the reply before it
...@@ -306,7 +306,6 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg, ...@@ -306,7 +306,6 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
call->state = AFS_CALL_AWAIT_REPLY; call->state = AFS_CALL_AWAIT_REPLY;
ret = rxrpc_kernel_send_data(afs_socket, call->rxcall, ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
msg, to - offset); msg, to - offset);
kunmap(pages[loop]);
if (ret < 0) if (ret < 0)
break; break;
} while (++loop < count); } while (++loop < count);
...@@ -391,7 +390,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp, ...@@ -391,7 +390,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
goto error_do_abort; goto error_do_abort;
if (call->send_pages) { if (call->send_pages) {
ret = afs_send_pages(call, &msg, iov); ret = afs_send_pages(call, &msg);
if (ret < 0) if (ret < 0)
goto error_do_abort; goto error_do_abort;
} }
......
...@@ -40,19 +40,12 @@ static int _recv(struct socket *sock, void *buf, int size, unsigned flags) ...@@ -40,19 +40,12 @@ static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); return kernel_recvmsg(sock, &msg, &iov, 1, size, flags);
} }
static inline int do_send(struct socket *sock, struct kvec *vec, int count,
int len, unsigned flags)
{
struct msghdr msg = { .msg_flags = flags };
return kernel_sendmsg(sock, &msg, vec, count, len);
}
static int _send(struct socket *sock, const void *buff, int len) static int _send(struct socket *sock, const void *buff, int len)
{ {
struct kvec vec; struct msghdr msg = { .msg_flags = 0 };
vec.iov_base = (void *) buff; struct kvec vec = {.iov_base = (void *)buff, .iov_len = len};
vec.iov_len = len; iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len);
return do_send(sock, &vec, 1, len, 0); return sock_sendmsg(sock, &msg);
} }
struct ncp_request_reply { struct ncp_request_reply {
...@@ -63,9 +56,7 @@ struct ncp_request_reply { ...@@ -63,9 +56,7 @@ struct ncp_request_reply {
size_t datalen; size_t datalen;
int result; int result;
enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
struct kvec* tx_ciov; struct iov_iter from;
size_t tx_totallen;
size_t tx_iovlen;
struct kvec tx_iov[3]; struct kvec tx_iov[3];
u_int16_t tx_type; u_int16_t tx_type;
u_int32_t sign[6]; u_int32_t sign[6];
...@@ -205,28 +196,22 @@ static inline void __ncptcp_abort(struct ncp_server *server) ...@@ -205,28 +196,22 @@ static inline void __ncptcp_abort(struct ncp_server *server)
static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
{ {
struct kvec vec[3]; struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT };
/* sock_sendmsg updates iov pointers for us :-( */ return sock_sendmsg(sock, &msg);
memcpy(vec, req->tx_ciov, req->tx_iovlen * sizeof(vec[0]));
return do_send(sock, vec, req->tx_iovlen,
req->tx_totallen, MSG_DONTWAIT);
} }
static void __ncptcp_try_send(struct ncp_server *server) static void __ncptcp_try_send(struct ncp_server *server)
{ {
struct ncp_request_reply *rq; struct ncp_request_reply *rq;
struct kvec *iov; struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT };
struct kvec iovc[3];
int result; int result;
rq = server->tx.creq; rq = server->tx.creq;
if (!rq) if (!rq)
return; return;
/* sock_sendmsg updates iov pointers for us :-( */ msg.msg_iter = rq->from;
memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0])); result = sock_sendmsg(server->ncp_sock, &msg);
result = do_send(server->ncp_sock, iovc, rq->tx_iovlen,
rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT);
if (result == -EAGAIN) if (result == -EAGAIN)
return; return;
...@@ -236,21 +221,12 @@ static void __ncptcp_try_send(struct ncp_server *server) ...@@ -236,21 +221,12 @@ static void __ncptcp_try_send(struct ncp_server *server)
__ncp_abort_request(server, rq, result); __ncp_abort_request(server, rq, result);
return; return;
} }
if (result >= rq->tx_totallen) { if (!msg_data_left(&msg)) {
server->rcv.creq = rq; server->rcv.creq = rq;
server->tx.creq = NULL; server->tx.creq = NULL;
return; return;
} }
rq->tx_totallen -= result; rq->from = msg.msg_iter;
iov = rq->tx_ciov;
while (iov->iov_len <= result) {
result -= iov->iov_len;
iov++;
rq->tx_iovlen--;
}
iov->iov_base += result;
iov->iov_len -= result;
rq->tx_ciov = iov;
} }
static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
...@@ -263,22 +239,21 @@ static inline void ncp_init_header(struct ncp_server *server, struct ncp_request ...@@ -263,22 +239,21 @@ static inline void ncp_init_header(struct ncp_server *server, struct ncp_request
static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
{ {
size_t signlen; size_t signlen, len = req->tx_iov[1].iov_len;
struct ncp_request_header* h; struct ncp_request_header *h = req->tx_iov[1].iov_base;
req->tx_ciov = req->tx_iov + 1;
h = req->tx_iov[1].iov_base;
ncp_init_header(server, req, h); ncp_init_header(server, req, h);
signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, signlen = sign_packet(server,
req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
cpu_to_le32(req->tx_totallen), req->sign); len - sizeof(struct ncp_request_header) + 1,
cpu_to_le32(len), req->sign);
if (signlen) { if (signlen) {
req->tx_ciov[1].iov_base = req->sign; /* NCP over UDP appends signature */
req->tx_ciov[1].iov_len = signlen; req->tx_iov[2].iov_base = req->sign;
req->tx_iovlen += 1; req->tx_iov[2].iov_len = signlen;
req->tx_totallen += signlen;
} }
iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
req->tx_iov + 1, signlen ? 2 : 1, len + signlen);
server->rcv.creq = req; server->rcv.creq = req;
server->timeout_last = server->m.time_out; server->timeout_last = server->m.time_out;
server->timeout_retries = server->m.retry_count; server->timeout_retries = server->m.retry_count;
...@@ -292,24 +267,23 @@ static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request ...@@ -292,24 +267,23 @@ static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request
static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
{ {
size_t signlen; size_t signlen, len = req->tx_iov[1].iov_len;
struct ncp_request_header* h; struct ncp_request_header *h = req->tx_iov[1].iov_base;
req->tx_ciov = req->tx_iov;
h = req->tx_iov[1].iov_base;
ncp_init_header(server, req, h); ncp_init_header(server, req, h);
signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1, len - sizeof(struct ncp_request_header) + 1,
cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16; cpu_to_be32(len + 24), req->sign + 4) + 16;
req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC); req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
req->sign[1] = htonl(req->tx_totallen + signlen); req->sign[1] = htonl(len + signlen);
req->sign[2] = htonl(NCP_TCP_XMIT_VERSION); req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
req->sign[3] = htonl(req->datalen + 8); req->sign[3] = htonl(req->datalen + 8);
/* NCP over TCP prepends signature */
req->tx_iov[0].iov_base = req->sign; req->tx_iov[0].iov_base = req->sign;
req->tx_iov[0].iov_len = signlen; req->tx_iov[0].iov_len = signlen;
req->tx_iovlen += 1; iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
req->tx_totallen += signlen; req->tx_iov, 2, len + signlen);
server->tx.creq = req; server->tx.creq = req;
__ncptcp_try_send(server); __ncptcp_try_send(server);
...@@ -364,18 +338,17 @@ static void __ncp_next_request(struct ncp_server *server) ...@@ -364,18 +338,17 @@ static void __ncp_next_request(struct ncp_server *server)
static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
{ {
if (server->info_sock) { if (server->info_sock) {
struct kvec iov[2]; struct msghdr msg = { .msg_flags = MSG_NOSIGNAL };
__be32 hdr[2]; __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)};
struct kvec iov[2] = {
hdr[0] = cpu_to_be32(len + 8); {.iov_base = hdr, .iov_len = 8},
hdr[1] = cpu_to_be32(id); {.iov_base = (void *)data, .iov_len = len},
};
iov[0].iov_base = hdr;
iov[0].iov_len = 8; iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE,
iov[1].iov_base = (void *) data; iov, 2, len + 8);
iov[1].iov_len = len;
do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL); sock_sendmsg(server->info_sock, &msg);
} }
} }
...@@ -711,8 +684,6 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size, ...@@ -711,8 +684,6 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size,
req->datalen = max_reply_size; req->datalen = max_reply_size;
req->tx_iov[1].iov_base = server->packet; req->tx_iov[1].iov_base = server->packet;
req->tx_iov[1].iov_len = size; req->tx_iov[1].iov_len = size;
req->tx_iovlen = 1;
req->tx_totallen = size;
req->tx_type = *(u_int16_t*)server->packet; req->tx_type = *(u_int16_t*)server->packet;
result = ncp_add_request(server, req); result = ncp_add_request(server, req);
......
...@@ -520,7 +520,8 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len) ...@@ -520,7 +520,8 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL }; struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
int r; int r;
r = kernel_recvmsg(sock, &msg, &iov, 1, len, msg.msg_flags); iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, len);
r = sock_recvmsg(sock, &msg, msg.msg_flags);
if (r == -EAGAIN) if (r == -EAGAIN)
r = 0; r = 0;
return r; return r;
...@@ -529,17 +530,20 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len) ...@@ -529,17 +530,20 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
static int ceph_tcp_recvpage(struct socket *sock, struct page *page, static int ceph_tcp_recvpage(struct socket *sock, struct page *page,
int page_offset, size_t length) int page_offset, size_t length)
{ {
void *kaddr; struct bio_vec bvec = {
int ret; .bv_page = page,
.bv_offset = page_offset,
.bv_len = length
};
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
int r;
BUG_ON(page_offset + length > PAGE_SIZE); BUG_ON(page_offset + length > PAGE_SIZE);
iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, &bvec, 1, length);
kaddr = kmap(page); r = sock_recvmsg(sock, &msg, msg.msg_flags);
BUG_ON(!kaddr); if (r == -EAGAIN)
ret = ceph_tcp_recvmsg(sock, kaddr + page_offset, length); r = 0;
kunmap(page); return r;
return ret;
} }
/* /*
...@@ -579,18 +583,28 @@ static int __ceph_tcp_sendpage(struct socket *sock, struct page *page, ...@@ -579,18 +583,28 @@ static int __ceph_tcp_sendpage(struct socket *sock, struct page *page,
static int ceph_tcp_sendpage(struct socket *sock, struct page *page, static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
int offset, size_t size, bool more) int offset, size_t size, bool more)
{ {
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
struct bio_vec bvec;
int ret; int ret;
struct kvec iov;
/* sendpage cannot properly handle pages with page_count == 0, /* sendpage cannot properly handle pages with page_count == 0,
* we need to fallback to sendmsg if that's the case */ * we need to fallback to sendmsg if that's the case */
if (page_count(page) >= 1) if (page_count(page) >= 1)
return __ceph_tcp_sendpage(sock, page, offset, size, more); return __ceph_tcp_sendpage(sock, page, offset, size, more);
iov.iov_base = kmap(page) + offset; bvec.bv_page = page;
iov.iov_len = size; bvec.bv_offset = offset;
ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more); bvec.bv_len = size;
kunmap(page);
if (more)
msg.msg_flags |= MSG_MORE;
else
msg.msg_flags |= MSG_EOR; /* superfluous, but what the hell */
iov_iter_bvec(&msg.msg_iter, WRITE | ITER_BVEC, &bvec, 1, size);
ret = sock_sendmsg(sock, &msg);
if (ret == -EAGAIN)
ret = 0;
return ret; return ret;
} }
......
...@@ -45,35 +45,6 @@ struct rds_page_remainder { ...@@ -45,35 +45,6 @@ struct rds_page_remainder {
static static
DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders); DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders);
/*
* returns 0 on success or -errno on failure.
*
* We don't have to worry about flush_dcache_page() as this only works
* with private pages. If, say, we were to do directed receive to pinned
* user pages we'd have to worry more about cache coherence. (Though
* the flush_dcache_page() in get_user_pages() would probably be enough).
*/
int rds_page_copy_user(struct page *page, unsigned long offset,
void __user *ptr, unsigned long bytes,
int to_user)
{
unsigned long ret;
void *addr;
addr = kmap(page);
if (to_user) {
rds_stats_add(s_copy_to_user, bytes);
ret = copy_to_user(ptr, addr + offset, bytes);
} else {
rds_stats_add(s_copy_from_user, bytes);
ret = copy_from_user(addr + offset, ptr, bytes);
}
kunmap(page);
return ret ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(rds_page_copy_user);
/** /**
* rds_page_remainder_alloc - build up regions of a message. * rds_page_remainder_alloc - build up regions of a message.
* *
......
...@@ -798,13 +798,6 @@ static inline int rds_message_verify_checksum(const struct rds_header *hdr) ...@@ -798,13 +798,6 @@ static inline int rds_message_verify_checksum(const struct rds_header *hdr)
/* page.c */ /* page.c */
int rds_page_remainder_alloc(struct scatterlist *scat, unsigned long bytes, int rds_page_remainder_alloc(struct scatterlist *scat, unsigned long bytes,
gfp_t gfp); gfp_t gfp);
int rds_page_copy_user(struct page *page, unsigned long offset,
void __user *ptr, unsigned long bytes,
int to_user);
#define rds_page_copy_to_user(page, offset, ptr, bytes) \
rds_page_copy_user(page, offset, ptr, bytes, 1)
#define rds_page_copy_from_user(page, offset, ptr, bytes) \
rds_page_copy_user(page, offset, ptr, bytes, 0)
void rds_page_exit(void); void rds_page_exit(void);
/* recv.c */ /* recv.c */
......
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