Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: Steve French <sfrench@samba.org>
Cc: David Howells <dhowells@redhat.com>,
	Paulo Alcantara <pc@manguebit.org>,
	Shyam Prasad N <sprasad@microsoft.com>,
	Tom Talpey <tom@talpey.com>, Stefan Metzmacher <metze@samba.org>,
	Mina Almasry <almasrymina@google.com>,
	linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org
Subject: [RFC PATCH 18/36] cifs: Use page frag allocator for Tx buffers
Date: Tue, 19 May 2026 11:21:36 +0100	[thread overview]
Message-ID: <20260519102158.592165-19-dhowells@redhat.com> (raw)
In-Reply-To: <20260519102158.592165-1-dhowells@redhat.com>

Use a per-TCP connection page fragment allocator for transmission buffers
rather than using whole pages for messages less than half a page in size.
Currently, the data is copied into there, but we should allocate these in
future up front instead of kmalloc'd bits and avoid that copy too.

Note that these page fragments can be used with MSG_SPLICE_PAGES and thus
avoid a copy inside the TCP stack.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Shyam Prasad N <sprasad@microsoft.com>
cc: Tom Talpey <tom@talpey.com>
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
---
 fs/smb/client/cifsglob.h  |  2 ++
 fs/smb/client/connect.c   |  3 +++
 fs/smb/client/transport.c | 38 ++++++++++++++++++++++++++++++++------
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index f7c12d24e2ea..cd9bf550a144 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -662,6 +662,8 @@ struct TCP_Server_Info {
 	/* updates to tcpStatus protected by cifs_tcp_ses_lock */
 	enum statusEnum tcpStatus; /* what we think the status is */
 	char *hostname; /* hostname portion of UNC string */
+	struct page_frag_cache tx_alloc; /* Transmission buffer allocator */
+	struct mutex tx_alloc_lock; /* Lock for ->tx_alloc */
 	struct socket *ssocket;
 	struct sockaddr_storage dstaddr;
 	struct sockaddr_storage srcaddr; /* locally bind to this IP */
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 4a3ebbd6d71b..1d6a18390a25 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -1054,6 +1054,8 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
 		 */
 	}
 
+	page_frag_cache_drain(&server->tx_alloc);
+
 	put_net(cifs_net_ns(server));
 	kfree(server->leaf_fullpath);
 	kfree(server->hostname);
@@ -1694,6 +1696,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
 	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
 	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
 	mutex_init(&tcp_ses->reconnect_mutex);
+	mutex_init(&tcp_ses->tx_alloc_lock);
 	memcpy(&tcp_ses->srcaddr, &ctx->srcaddr,
 	       sizeof(tcp_ses->srcaddr));
 	memcpy(&tcp_ses->dstaddr, &ctx->dstaddr,
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index e43fce1099a9..98dca2524376 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -445,7 +445,8 @@ static size_t smb3_copy_data_iter(void *iter_from, size_t progress, size_t len,
  */
 static int smb_copy_data_into_buffer(struct TCP_Server_Info *server,
 				     int num_rqst, struct smb_rqst *rqst,
-				     struct iov_iter *iter, struct bvecq **_bq)
+				     struct iov_iter *iter, struct bvecq **_bq,
+				     unsigned int flags)
 {
 	struct bvecq *bq;
 	size_t total_len = 0, offset = 0;
@@ -460,9 +461,31 @@ static int smb_copy_data_into_buffer(struct TCP_Server_Info *server,
 		total_len += size;
 	}
 
-	bq = bvecq_alloc_buffer(total_len, GFP_NOFS);
-	if (!bq)
-		return -ENOMEM;
+	if (total_len <= PAGE_SIZE / 2) {
+		/* TODO: Choose algo-based alignment. */
+		unsigned int align = (flags & CIFS_TRANSFORM_REQ) ? 32 : 1;
+		size_t alen = (flags & CIFS_TRANSFORM_REQ) ?
+			round_up(total_len, align) : total_len;
+
+		bq = bvecq_alloc_chain(2, GFP_NOFS);
+		if (!bq)
+			return -ENOMEM;
+		mutex_lock(&server->tx_alloc_lock);
+		void *p = page_frag_alloc_align(&server->tx_alloc, alen,
+						GFP_NOFS, align);
+		mutex_unlock(&server->tx_alloc_lock);
+		if (!p) {
+			bvecq_put(bq);
+			return -ENOMEM;
+		}
+		bvec_set_virt(&bq->bv[1], p, total_len);
+		bq->nr_slots = 2;
+		bq->mem_type = BVECQ_MEM_PAGECACHE;
+	} else {
+		bq = bvecq_alloc_buffer2(total_len, 1, GFP_NOFS);
+		if (!bq)
+			return -ENOMEM;
+	}
 
 	iov_iter_bvec_queue(iter, ITER_DEST, bq, 1, 0, total_len);
 
@@ -495,6 +518,7 @@ static int smb_copy_data_into_buffer(struct TCP_Server_Info *server,
 		      "offset=%zx total_len=%zx\n", offset, total_len)) {
 		goto error;
 	}
+
 	iov_iter_bvec_queue(iter, ITER_DEST, bq, 1, 0, total_len);
 	*_bq = bq;
 	return 0;
@@ -519,7 +543,7 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 		return smb_EIO(smb_eio_trace_tx_need_transform);
 	}
 
-	rc = smb_copy_data_into_buffer(server, num_rqst, rqst, &iter, &bq);
+	rc = smb_copy_data_into_buffer(server, num_rqst, rqst, &iter, &bq, flags);
 	if (rc)
 		return rc;
 	content_len = iov_iter_count(&iter);
@@ -537,7 +561,9 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
 
 		/* TODO: Allocate netmem here */
 		rc = -ENOMEM;
-		hdr_blob = (void *)__get_free_page(GFP_NOFS);
+		mutex_lock(&server->tx_alloc_lock);
+		hdr_blob = page_frag_alloc(&server->tx_alloc, hdr_len, GFP_NOFS);
+		mutex_unlock(&server->tx_alloc_lock);
 		if (!hdr_blob)
 			goto error;
 		bvec_set_virt(&bq->bv[0], hdr_blob, hdr_len);


  parent reply	other threads:[~2026-05-19 10:23 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-19 10:21 [RFC PATCH 00/36] cifs: [WIP] Overhaul message handling and improve nework transport David Howells
2026-05-19 10:21 ` [RFC PATCH 01/36] net: Perform special handling for a splice from a bvecq David Howells
2026-05-19 10:21 ` [RFC PATCH 02/36] netfs: Add a facility to splice TCP receive buffers into " David Howells
2026-05-19 10:21 ` [RFC PATCH 03/36] netfs: Add some TCP receive queue helpers David Howells
2026-05-19 10:21 ` [RFC PATCH 04/36] cifs, nls: Provide unicode size determination func David Howells
2026-05-19 10:21 ` [RFC PATCH 05/36] cifs: Introduce an ALIGN8() macro David Howells
2026-05-19 10:21 ` [RFC PATCH 06/36] cifs: Rename mid_q_entry to smb_message David Howells
2026-05-19 10:21 ` [RFC PATCH 07/36] cifs: Add "Has dynamic part" flag form SMB2/3 StructureSize LSB David Howells
2026-05-19 10:21 ` [RFC PATCH 08/36] cifs: Add an enum to hold a trace value for the command/subcommand David Howells
2026-05-19 10:21 ` [RFC PATCH 09/36] cifs: Institute message managing struct David Howells
2026-05-19 10:21 ` [RFC PATCH 10/36] cifs: Split crypt_message() into encrypt and decrypt variants David Howells
2026-05-19 10:21 ` [RFC PATCH 11/36] cifs: Add new AEAD alloc and setup routines that draw from an iterator David Howells
2026-05-19 10:21 ` [RFC PATCH 12/36] cifs: [WIP] Rewrite base Rx to put data off the socket into a bvecq David Howells
2026-05-19 10:21 ` [RFC PATCH 13/36] cifs: Remove validate_t2() David Howells
2026-05-19 10:21 ` [RFC PATCH 14/36] cifs: Remove cifs_io_subrequest::got_bytes David Howells
2026-05-19 10:21 ` [RFC PATCH 15/36] cifs: Pass smb_message to cifs_verify_signature() David Howells
2026-05-19 10:21 ` [RFC PATCH 16/36] cifs: Rewrite base TCP transmission David Howells
2026-05-19 10:36   ` Stefan Metzmacher
2026-05-19 10:21 ` [RFC PATCH 17/36] cifs: Don't use corking David Howells
2026-05-19 10:21 ` David Howells [this message]
2026-05-19 10:21 ` [RFC PATCH 19/36] cifs: Try to better handle the "Dynamic" flag in StructureSize2 in SMB2/3 David Howells
2026-05-19 10:21 ` [RFC PATCH 20/36] cifs: Pass smb_message structs down into the transport layer David Howells
2026-05-19 10:21 ` [RFC PATCH 21/36] cifs: Add a tracepoint to trace the smb_message refcount David Howells
2026-05-19 10:21 ` [RFC PATCH 22/36] cifs: Trace smb1/2_copy_to_prepped_buffers() David Howells
2026-05-19 10:21 ` [RFC PATCH 23/36] cifs: Clean up mid->callback_data and kill off mid->creator David Howells
2026-05-19 10:21 ` [RFC PATCH 24/36] cifs: Add netmem allocation functions David Howells
2026-05-19 10:21 ` [RFC PATCH 25/36] cifs: Add more pieces to smb_message David Howells
2026-05-19 10:21 ` [RFC PATCH 26/36] cifs: Convert SMB2 Negotiate Protocol request David Howells
2026-05-19 10:21 ` [RFC PATCH 27/36] cifs: Convert SMB2 Session Setup request David Howells
2026-05-19 10:21 ` [RFC PATCH 28/36] cifs: Convert SMB2 Logoff request David Howells
2026-05-19 10:21 ` [RFC PATCH 29/36] cifs: Convert SMB2 Tree Connect request David Howells
2026-05-19 10:21 ` [RFC PATCH 30/36] cifs: Convert SMB2 Tree Disconnect request David Howells
2026-05-19 10:21 ` [RFC PATCH 31/36] cifs: Convert SMB2 Read request David Howells
2026-05-19 10:21 ` [RFC PATCH 32/36] cifs: Convert SMB2 Write request David Howells
2026-05-19 10:21 ` [RFC PATCH 33/36] cifs: [WIP] Don't copy new-style smb_messages to a set of pages David Howells
2026-05-19 10:21 ` [RFC PATCH 34/36] cifs: [WIP] Rearrange Create request subfuncs David Howells
2026-05-19 10:21 ` [RFC PATCH 35/36] cifs: [WIP] Convert SMB2 Posix Mkdir request David Howells
2026-05-19 10:21 ` [RFC PATCH 36/36] cifs: [WIP] Convert SMB2 Open request David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260519102158.592165-19-dhowells@redhat.com \
    --to=dhowells@redhat.com \
    --cc=almasrymina@google.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=metze@samba.org \
    --cc=pc@manguebit.org \
    --cc=sfrench@samba.org \
    --cc=sprasad@microsoft.com \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox