Skip to content

Commit

Permalink
Merge branch 'work.sendmsg' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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()
  • Loading branch information
torvalds committed Mar 2, 2017
2 parents 821fd6f + 4038a2a commit 69fd110
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 242 deletions.
11 changes: 4 additions & 7 deletions drivers/block/drbd/drbd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
void *buf, size_t size, unsigned msg_flags)
{
struct kvec iov;
struct kvec iov = {.iov_base = buf, .iov_len = size};
struct msghdr msg;
int rv, sent = 0;

Expand All @@ -1855,23 +1855,22 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,

/* THINK if (signal_pending) return ... ? */

iov.iov_base = buf;
iov.iov_len = size;

msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;

iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1, size);

if (sock == connection->data.socket) {
rcu_read_lock();
connection->ko_count = rcu_dereference(connection->net_conf)->ko_count;
rcu_read_unlock();
drbd_update_congested(connection);
}
do {
rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
rv = sock_sendmsg(sock, &msg);
if (rv == -EAGAIN) {
if (we_should_drop_the_connection(connection, sock))
break;
Expand All @@ -1885,8 +1884,6 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
if (rv < 0)
break;
sent += rv;
iov.iov_base += rv;
iov.iov_len -= rv;
} while (sent < size);

if (sock == connection->data.socket)
Expand Down
76 changes: 31 additions & 45 deletions drivers/block/nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,12 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
/*
* Send or receive packet.
*/
static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
int size, int msg_flags)
static int sock_xmit(struct nbd_device *nbd, int index, int send,
struct iov_iter *iter, int msg_flags)
{
struct socket *sock = nbd->socks[index]->sock;
int result;
struct msghdr msg;
struct kvec iov;
unsigned long pflags = current->flags;

if (unlikely(!sock)) {
Expand All @@ -217,59 +216,49 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
return -EINVAL;
}

msg.msg_iter = *iter;

current->flags |= PF_MEMALLOC;
do {
sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
iov.iov_base = buf;
iov.iov_len = size;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;

if (send)
result = kernel_sendmsg(sock, &msg, &iov, 1, size);
result = sock_sendmsg(sock, &msg);
else
result = kernel_recvmsg(sock, &msg, &iov, 1, size,
msg.msg_flags);
result = sock_recvmsg(sock, &msg, msg.msg_flags);

if (result <= 0) {
if (result == 0)
result = -EPIPE; /* short read */
break;
}
size -= result;
buf += result;
} while (size > 0);
} while (msg_data_left(&msg));

tsk_restore_flags(current, pflags, PF_MEMALLOC);

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 */
static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
{
struct request *req = blk_mq_rq_from_pdu(cmd);
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);
struct bio *bio;
u32 type;
u32 tag = blk_mq_unique_tag(req);

iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));

switch (req_op(req)) {
case REQ_OP_DISCARD:
type = NBD_CMD_TRIM;
Expand All @@ -294,8 +283,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return -EIO;
}

memset(&request, 0, sizeof(request));
request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(type);
if (type != NBD_CMD_FLUSH) {
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
Expand All @@ -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",
cmd, nbdcmd_to_ascii(type),
(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);
if (result <= 0) {
dev_err_ratelimited(disk_to_dev(nbd->disk),
Expand All @@ -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",
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) {
dev_err(disk_to_dev(nbd->disk),
"Send data failed (result %d)\n",
Expand All @@ -350,17 +339,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
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 */
static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
{
Expand All @@ -370,9 +348,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
struct request *req = NULL;
u16 hwq;
u32 tag;
struct kvec iov = {.iov_base = &reply, .iov_len = sizeof(reply)};
struct iov_iter to;

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 (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
!test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
Expand Down Expand Up @@ -412,7 +393,9 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
struct bio_vec bvec;

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) {
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
result);
Expand Down Expand Up @@ -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)
{
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;

request.magic = htonl(NBD_REQUEST_MAGIC);
request.type = htonl(NBD_CMD_DISC);

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)
dev_err(disk_to_dev(nbd->disk),
"Send disconnect failed %d\n", ret);
Expand Down
64 changes: 24 additions & 40 deletions drivers/target/iscsi/iscsi_target_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1305,39 +1305,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,
Expand All @@ -1364,18 +1331,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;
}

void iscsit_collect_login_stats(
Expand Down
32 changes: 11 additions & 21 deletions drivers/usb/usbip/usbip_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,11 @@ EXPORT_SYMBOL_GPL(usbip_dump_header);
int usbip_recv(struct socket *sock, void *buf, int size)
{
int result;
struct msghdr msg;
struct kvec iov;
struct kvec iov = {.iov_base = buf, .iov_len = size};
struct msghdr msg = {.msg_flags = MSG_NOSIGNAL};
int total = 0;

/* for blocks of if (usbip_dbg_flag_xmit) */
char *bp = buf;
int osize = size;
iov_iter_kvec(&msg.msg_iter, READ|ITER_KVEC, &iov, 1, size);

usbip_dbg_xmit("enter\n");

Expand All @@ -344,26 +342,18 @@ int usbip_recv(struct socket *sock, void *buf, int size)
}

do {
int sz = msg_data_left(&msg);
sock->sk->sk_allocation = GFP_NOIO;
iov.iov_base = buf;
iov.iov_len = size;
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);

result = sock_recvmsg(sock, &msg, MSG_WAITALL);
if (result <= 0) {
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;
}

size -= result;
buf += result;
total += result;
} while (size > 0);
} while (msg_data_left(&msg));

if (usbip_dbg_flag_xmit) {
if (!in_interrupt())
Expand All @@ -372,9 +362,9 @@ int usbip_recv(struct socket *sock, void *buf, int size)
pr_debug("interrupt :");

pr_debug("receiving....\n");
usbip_dump_buffer(bp, osize);
pr_debug("received, osize %d ret %d size %d total %d\n",
osize, result, size, total);
usbip_dump_buffer(buf, size);
pr_debug("received, osize %d ret %d size %zd total %d\n",
size, result, msg_data_left(&msg), total);
}

return total;
Expand Down
Loading

0 comments on commit 69fd110

Please sign in to comment.