* [Drbd-dev] [PATCH v3 53/55] drbd: Use sendmsg(MSG_SPLICE_PAGES) rather than sendmsg()
[not found] <20230331160914.1608208-1-dhowells@redhat.com>
@ 2023-03-31 16:09 ` David Howells
2023-03-31 16:09 ` [Drbd-dev] [PATCH v3 54/55] drdb: Send an entire bio in a single sendmsg David Howells
1 sibling, 0 replies; 2+ messages in thread
From: David Howells @ 2023-03-31 16:09 UTC (permalink / raw)
To: Matthew Wilcox, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Jens Axboe, Christoph Hellwig, Christian Brauner, netdev,
Jeff Layton, linux-kernel, Philipp Reisner, David Howells,
linux-mm, Chuck Lever III, linux-block, Al Viro, linux-fsdevel,
Lars Ellenberg, Linus Torvalds, drbd-dev
Use sendmsg() conditionally with MSG_SPLICE_PAGES in _drbd_send_page()
rather than calling sendpage() or _drbd_no_send_page().
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Philipp Reisner <philipp.reisner@linbit.com>
cc: Lars Ellenberg <lars.ellenberg@linbit.com>
cc: "Christoph Böhmwalder" <christoph.boehmwalder@linbit.com>
cc: Jens Axboe <axboe@kernel.dk>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: drbd-dev@lists.linbit.com
cc: linux-block@vger.kernel.org
cc: netdev@vger.kernel.org
---
drivers/block/drbd/drbd_main.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 2c764f7ee4a7..e5f90abd29b6 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1532,7 +1532,8 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
int offset, size_t size, unsigned msg_flags)
{
struct socket *socket = peer_device->connection->data.socket;
- int len = size;
+ struct bio_vec bvec;
+ struct msghdr msg = { .msg_flags = msg_flags, };
int err = -EIO;
/* e.g. XFS meta- & log-data is in slab pages, which have a
@@ -1541,33 +1542,33 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
* put_page(); and would cause either a VM_BUG directly, or
* __page_cache_release a page that would actually still be referenced
* by someone, leading to some obscure delayed Oops somewhere else. */
- if (drbd_disable_sendpage || !sendpage_ok(page))
- return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
+ if (!drbd_disable_sendpage && sendpage_ok(page))
+ msg.msg_flags |= MSG_NOSIGNAL | MSG_SPLICE_PAGES;
+
+ bvec_set_page(&bvec, page, offset, size);
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
- msg_flags |= MSG_NOSIGNAL;
drbd_update_congested(peer_device->connection);
do {
int sent;
- sent = socket->ops->sendpage(socket, page, offset, len, msg_flags);
+ sent = sock_sendmsg(socket, &msg);
if (sent <= 0) {
if (sent == -EAGAIN) {
if (we_should_drop_the_connection(peer_device->connection, socket))
break;
continue;
}
- drbd_warn(peer_device->device, "%s: size=%d len=%d sent=%d\n",
- __func__, (int)size, len, sent);
+ drbd_warn(peer_device->device, "%s: size=%d len=%zu sent=%d\n",
+ __func__, (int)size, msg_data_left(&msg), sent);
if (sent < 0)
err = sent;
break;
}
- len -= sent;
- offset += sent;
- } while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/);
+ } while (msg_data_left(&msg) /* THINK && device->cstate >= C_CONNECTED*/);
clear_bit(NET_CONGESTED, &peer_device->connection->flags);
- if (len == 0) {
+ if (!msg_data_left(&msg)) {
err = 0;
peer_device->device->send_cnt += size >> 9;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread* [Drbd-dev] [PATCH v3 54/55] drdb: Send an entire bio in a single sendmsg
[not found] <20230331160914.1608208-1-dhowells@redhat.com>
2023-03-31 16:09 ` [Drbd-dev] [PATCH v3 53/55] drbd: Use sendmsg(MSG_SPLICE_PAGES) rather than sendmsg() David Howells
@ 2023-03-31 16:09 ` David Howells
1 sibling, 0 replies; 2+ messages in thread
From: David Howells @ 2023-03-31 16:09 UTC (permalink / raw)
To: Matthew Wilcox, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Jens Axboe, Christoph Hellwig, Christian Brauner, netdev,
Jeff Layton, linux-kernel, Philipp Reisner, David Howells,
linux-mm, Chuck Lever III, linux-block, Al Viro, linux-fsdevel,
Lars Ellenberg, Linus Torvalds, drbd-dev
Since _drdb_sendpage() is now using sendmsg to send the pages rather
sendpage, pass the entire bio in one go using a bvec iterator instead of
doing it piecemeal.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Philipp Reisner <philipp.reisner@linbit.com>
cc: Lars Ellenberg <lars.ellenberg@linbit.com>
cc: "Christoph Böhmwalder" <christoph.boehmwalder@linbit.com>
cc: Jens Axboe <axboe@kernel.dk>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: drbd-dev@lists.linbit.com
cc: linux-block@vger.kernel.org
cc: netdev@vger.kernel.org
---
drivers/block/drbd/drbd_main.c | 77 +++++++++++-----------------------
1 file changed, 25 insertions(+), 52 deletions(-)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index e5f90abd29b6..ab63d6138407 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1512,28 +1512,15 @@ static void drbd_update_congested(struct drbd_connection *connection)
* As a workaround, we disable sendpage on pages
* with page_count == 0 or PageSlab.
*/
-static int _drbd_no_send_page(struct drbd_peer_device *peer_device, struct page *page,
- int offset, size_t size, unsigned msg_flags)
-{
- struct socket *socket;
- void *addr;
- int err;
-
- socket = peer_device->connection->data.socket;
- addr = kmap(page) + offset;
- err = drbd_send_all(peer_device->connection, socket, addr, size, msg_flags);
- kunmap(page);
- if (!err)
- peer_device->device->send_cnt += size >> 9;
- return err;
-}
-
-static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *page,
- int offset, size_t size, unsigned msg_flags)
+static int _drbd_send_pages(struct drbd_peer_device *peer_device,
+ struct iov_iter *iter, unsigned msg_flags)
{
struct socket *socket = peer_device->connection->data.socket;
- struct bio_vec bvec;
- struct msghdr msg = { .msg_flags = msg_flags, };
+ struct msghdr msg = {
+ .msg_flags = msg_flags | MSG_NOSIGNAL,
+ .msg_iter = *iter,
+ };
+ size_t size = iov_iter_count(iter);
int err = -EIO;
/* e.g. XFS meta- & log-data is in slab pages, which have a
@@ -1542,11 +1529,8 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
* put_page(); and would cause either a VM_BUG directly, or
* __page_cache_release a page that would actually still be referenced
* by someone, leading to some obscure delayed Oops somewhere else. */
- if (!drbd_disable_sendpage && sendpage_ok(page))
- msg.msg_flags |= MSG_NOSIGNAL | MSG_SPLICE_PAGES;
-
- bvec_set_page(&bvec, page, offset, size);
- iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size);
+ if (drbd_disable_sendpage)
+ msg.msg_flags &= ~(MSG_NOSIGNAL | MSG_SPLICE_PAGES);
drbd_update_congested(peer_device->connection);
do {
@@ -1577,39 +1561,22 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
static int _drbd_send_bio(struct drbd_peer_device *peer_device, struct bio *bio)
{
- struct bio_vec bvec;
- struct bvec_iter iter;
+ struct iov_iter iter;
- /* hint all but last page with MSG_MORE */
- bio_for_each_segment(bvec, bio, iter) {
- int err;
+ iov_iter_bvec(&iter, ITER_SOURCE, bio->bi_io_vec, bio->bi_vcnt,
+ bio->bi_iter.bi_size);
- err = _drbd_no_send_page(peer_device, bvec.bv_page,
- bvec.bv_offset, bvec.bv_len,
- bio_iter_last(bvec, iter)
- ? 0 : MSG_MORE);
- if (err)
- return err;
- }
- return 0;
+ return _drbd_send_pages(peer_device, &iter, 0);
}
static int _drbd_send_zc_bio(struct drbd_peer_device *peer_device, struct bio *bio)
{
- struct bio_vec bvec;
- struct bvec_iter iter;
+ struct iov_iter iter;
- /* hint all but last page with MSG_MORE */
- bio_for_each_segment(bvec, bio, iter) {
- int err;
+ iov_iter_bvec(&iter, ITER_SOURCE, bio->bi_io_vec, bio->bi_vcnt,
+ bio->bi_iter.bi_size);
- err = _drbd_send_page(peer_device, bvec.bv_page,
- bvec.bv_offset, bvec.bv_len,
- bio_iter_last(bvec, iter) ? 0 : MSG_MORE);
- if (err)
- return err;
- }
- return 0;
+ return _drbd_send_pages(peer_device, &iter, MSG_SPLICE_PAGES);
}
static int _drbd_send_zc_ee(struct drbd_peer_device *peer_device,
@@ -1621,10 +1588,16 @@ static int _drbd_send_zc_ee(struct drbd_peer_device *peer_device,
/* hint all but last page with MSG_MORE */
page_chain_for_each(page) {
+ struct iov_iter iter;
+ struct bio_vec bvec;
unsigned l = min_t(unsigned, len, PAGE_SIZE);
- err = _drbd_send_page(peer_device, page, 0, l,
- page_chain_next(page) ? MSG_MORE : 0);
+ bvec_set_page(&bvec, page, 0, l);
+ iov_iter_bvec(&iter, ITER_SOURCE, &bvec, 1, l);
+
+ err = _drbd_send_pages(peer_device, &iter,
+ MSG_SPLICE_PAGES |
+ (page_chain_next(page) ? MSG_MORE : 0));
if (err)
return err;
len -= l;
^ permalink raw reply related [flat|nested] 2+ messages in thread