git: 314cb279959b - main - mbuf: Don't force all M_EXTPG mbufs to be read-only

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 31 Oct 2024 20:33:18 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=314cb279959b08811543612a715e47266f685c7b

commit 314cb279959b08811543612a715e47266f685c7b
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-10-31 20:32:31 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-10-31 20:32:31 +0000

    mbuf: Don't force all M_EXTPG mbufs to be read-only
    
    Some M_EXTPG mbufs are read-only (e.g. those backing sendfile
    requests), but others are not.  Add a flags argument to
    mb_alloc_ext_pgs that can be used to set M_RDONLY when needed rather
    than setting it unconditionally.  Update mb_unmapped_to_ext to
    preserve M_RDONLY from the unmapped mbuf.
    
    Reviewed by:    gallatin
    Differential Revision:  https://reviews.freebsd.org/D46783
---
 sys/dev/cxgbe/cxgbei/icl_cxgbei.c | 2 +-
 sys/dev/cxgbe/tom/t4_cpl_io.c     | 2 +-
 sys/dev/iscsi/icl_soft.c          | 2 +-
 sys/dev/nvmf/nvmf_tcp.c           | 2 +-
 sys/fs/nfsclient/nfs_clrpcops.c   | 2 +-
 sys/kern/kern_mbuf.c              | 9 +++++----
 sys/kern/kern_sendfile.c          | 2 +-
 sys/kern/uipc_mbuf.c              | 4 ++--
 sys/sys/mbuf.h                    | 2 +-
 9 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
index ab1428c06d87..c8592807f843 100644
--- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
+++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
@@ -651,7 +651,7 @@ icl_cxgbei_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *ip,
 		while (len > 0) {
 			if (m == NULL) {
 				m = mb_alloc_ext_pgs(flags & ~ICL_NOCOPY,
-				    cxgbei_free_mext_pg);
+				    cxgbei_free_mext_pg, 0);
 				if (__predict_false(m == NULL))
 					return (ENOMEM);
 				atomic_add_int(&icp->ref_cnt, 1);
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 0a40bbda3f3f..8cafac61fa8b 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -2126,7 +2126,7 @@ alloc_aiotx_mbuf(struct kaiocb *job, int len)
 		if (npages < 0)
 			break;
 
-		m = mb_alloc_ext_pgs(M_WAITOK, aiotx_free_pgs);
+		m = mb_alloc_ext_pgs(M_WAITOK, aiotx_free_pgs, M_RDONLY);
 		m->m_epg_1st_off = pgoff;
 		m->m_epg_npgs = npages;
 		if (npages == 1) {
diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c
index 832ff8135ec5..812793a9fba3 100644
--- a/sys/dev/iscsi/icl_soft.c
+++ b/sys/dev/iscsi/icl_soft.c
@@ -1139,7 +1139,7 @@ icl_soft_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *request,
 		while (len > 0) {
 			if (m == NULL) {
 				m = mb_alloc_ext_pgs(flags & ~ICL_NOCOPY,
-				    icl_soft_free_mext_pg);
+				    icl_soft_free_mext_pg, 0);
 				if (__predict_false(m == NULL))
 					return (ENOMEM);
 				atomic_add_int(&isp->ref_cnt, 1);
diff --git a/sys/dev/nvmf/nvmf_tcp.c b/sys/dev/nvmf/nvmf_tcp.c
index 22275aaa835b..2e33334b92ee 100644
--- a/sys/dev/nvmf/nvmf_tcp.c
+++ b/sys/dev/nvmf/nvmf_tcp.c
@@ -884,7 +884,7 @@ nvmf_tcp_mext_pg(void *arg, int how)
 	struct nvmf_tcp_command_buffer *cb = arg;
 	struct mbuf *m;
 
-	m = mb_alloc_ext_pgs(how, nvmf_tcp_free_mext_pg);
+	m = mb_alloc_ext_pgs(how, nvmf_tcp_free_mext_pg, M_RDONLY);
 	m->m_ext.ext_arg1 = cb;
 	tcp_hold_command_buffer(cb);
 	return (m);
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 7540893ce63c..e1c02a71939b 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -9402,7 +9402,7 @@ nfsm_split(struct mbuf *mp, uint64_t xfer)
 	if (pgno == m->m_epg_npgs)
 		panic("nfsm_split: eroneous ext_pgs mbuf");
 
-	m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs);
+	m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs, 0);
 	m2->m_epg_flags |= EPG_FLAG_ANON;
 
 	/*
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 5c1c5b095449..73c98209474a 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -1014,7 +1014,8 @@ _mb_unmapped_to_ext(struct mbuf *m)
 
 		ref_inc++;
 		m_extadd(m_new, (char *)sf_buf_kva(sf), PAGE_SIZE,
-		    mb_unmapped_free_mext, sf, mref, M_RDONLY, EXT_SFBUF);
+		    mb_unmapped_free_mext, sf, mref, m->m_flags & M_RDONLY,
+		    EXT_SFBUF);
 		m_new->m_data += segoff;
 		m_new->m_len = seglen;
 
@@ -1119,7 +1120,7 @@ mb_unmapped_to_ext(struct mbuf *top)
  * freed.
  */
 struct mbuf *
-mb_alloc_ext_pgs(int how, m_ext_free_t ext_free)
+mb_alloc_ext_pgs(int how, m_ext_free_t ext_free, int flags)
 {
 	struct mbuf *m;
 
@@ -1137,7 +1138,7 @@ mb_alloc_ext_pgs(int how, m_ext_free_t ext_free)
 	m->m_epg_tls = NULL;
 	m->m_epg_so = NULL;
 	m->m_data = NULL;
-	m->m_flags |= (M_EXT | M_RDONLY | M_EXTPG);
+	m->m_flags |= M_EXT | M_EXTPG | flags;
 	m->m_ext.ext_flags = EXT_FLAG_EMBREF;
 	m->m_ext.ext_count = 1;
 	m->m_ext.ext_size = 0;
@@ -1709,7 +1710,7 @@ mb_alloc_ext_plus_pages(int len, int how)
 	vm_page_t pg;
 	int i, npgs;
 
-	m = mb_alloc_ext_pgs(how, mb_free_mext_pgs);
+	m = mb_alloc_ext_pgs(how, mb_free_mext_pgs, 0);
 	if (m == NULL)
 		return (NULL);
 	m->m_epg_flags |= EPG_FLAG_ANON;
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index 323e7fcde07b..05a820fe5ac1 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -1003,7 +1003,7 @@ retry_space:
 				ext_pgs_idx++;
 				if (ext_pgs_idx == max_pgs) {
 					m0 = mb_alloc_ext_pgs(M_WAITOK,
-					    sendfile_free_mext_pg);
+					    sendfile_free_mext_pg, M_RDONLY);
 
 					if (flags & SF_NOCACHE) {
 						m0->m_ext.ext_flags |=
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index f6ce9b5cc74b..f3e2f13e89ec 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1887,7 +1887,7 @@ m_uiotombuf_nomap(struct uio *uio, int how, int len, int maxseg, int flags)
 	 * ciphersuites.
 	 */
 	if (__predict_false(total == 0)) {
-		mb = mb_alloc_ext_pgs(how, mb_free_mext_pgs);
+		mb = mb_alloc_ext_pgs(how, mb_free_mext_pgs, 0);
 		if (mb == NULL)
 			return (NULL);
 		mb->m_epg_flags = EPG_FLAG_ANON;
@@ -1899,7 +1899,7 @@ m_uiotombuf_nomap(struct uio *uio, int how, int len, int maxseg, int flags)
 	 */
 	m = NULL;
 	while (total > 0) {
-		mb = mb_alloc_ext_pgs(how, mb_free_mext_pgs);
+		mb = mb_alloc_ext_pgs(how, mb_free_mext_pgs, 0);
 		if (mb == NULL)
 			goto failed;
 		if (m == NULL)
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index ab494a76833e..434f29feddcf 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -808,7 +808,7 @@ void		 mb_dupcl(struct mbuf *, struct mbuf *);
 void		 mb_free_ext(struct mbuf *);
 void		 mb_free_extpg(struct mbuf *);
 void		 mb_free_mext_pgs(struct mbuf *);
-struct mbuf	*mb_alloc_ext_pgs(int, m_ext_free_t);
+struct mbuf	*mb_alloc_ext_pgs(int, m_ext_free_t, int);
 struct mbuf	*mb_alloc_ext_plus_pages(int, int);
 struct mbuf	*mb_mapped_to_unmapped(struct mbuf *, int, int, int,
 		    struct mbuf **);