mbuf(9): New m_get_n, m_gethdr_n. m_get_n(how, type, alignbytes, nbytes) returns an mbuf with no packet header having space for nbytes, with an internal buffer pointer aligned by alignbytes (typically ETHER_ALIGN or similar, if not zero). m_gethdr_n(how, type, alignbytes, nbytes) does the same but for an mbuf with a packet header. These return NULL on failure, which can happen either: (a) because how is M_DONTWAIT and allocating memory would sleep, or (b) because alignbytes + nbytes > MCLBYTES. On exit, m_len is set to nbytes, as is m_pkthdr.len for m_gethdr_n. These should be used to systematically replace all calls to m_get, m_gethdr, MGET, MGETHDR, and m_getcl. Most calls to m_clget and MCLGET will probably evaporate as a consequence. Proposed on tech-net last year: https://mail-index.netbsd.org/tech-net/2022/07/16/msg008285.htmldiff -r1.250 -r1.251 src/sys/kern/uipc_mbuf.c
(riastradh)
--- src/sys/kern/uipc_mbuf.c 2023/04/01 06:30:19 1.250
+++ src/sys/kern/uipc_mbuf.c 2023/04/12 06:48:08 1.251
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: uipc_mbuf.c,v 1.250 2023/04/01 06:30:19 skrll Exp $ */ | 1 | /* $NetBSD: uipc_mbuf.c,v 1.251 2023/04/12 06:48:08 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1999, 2001, 2018 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2001, 2018 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center, and Maxime Villard. | 9 | * NASA Ames Research Center, and Maxime Villard. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -52,27 +52,27 @@ | @@ -52,27 +52,27 @@ | |||
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
59 | * SUCH DAMAGE. | 59 | * SUCH DAMAGE. | |
60 | * | 60 | * | |
61 | * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95 | 61 | * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95 | |
62 | */ | 62 | */ | |
63 | 63 | |||
64 | #include <sys/cdefs.h> | 64 | #include <sys/cdefs.h> | |
65 | __KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.250 2023/04/01 06:30:19 skrll Exp $"); | 65 | __KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.251 2023/04/12 06:48:08 riastradh Exp $"); | |
66 | 66 | |||
67 | #ifdef _KERNEL_OPT | 67 | #ifdef _KERNEL_OPT | |
68 | #include "opt_mbuftrace.h" | 68 | #include "opt_mbuftrace.h" | |
69 | #include "opt_nmbclusters.h" | 69 | #include "opt_nmbclusters.h" | |
70 | #include "opt_ddb.h" | 70 | #include "opt_ddb.h" | |
71 | #include "ether.h" | 71 | #include "ether.h" | |
72 | #endif | 72 | #endif | |
73 | 73 | |||
74 | #include <sys/param.h> | 74 | #include <sys/param.h> | |
75 | #include <sys/systm.h> | 75 | #include <sys/systm.h> | |
76 | #include <sys/atomic.h> | 76 | #include <sys/atomic.h> | |
77 | #include <sys/cpu.h> | 77 | #include <sys/cpu.h> | |
78 | #include <sys/proc.h> | 78 | #include <sys/proc.h> | |
@@ -577,26 +577,70 @@ m_gethdr(int how, int type) | @@ -577,26 +577,70 @@ m_gethdr(int how, int type) | |||
577 | m->m_pkthdr.csum_data = 0; | 577 | m->m_pkthdr.csum_data = 0; | |
578 | m->m_pkthdr.segsz = 0; | 578 | m->m_pkthdr.segsz = 0; | |
579 | m->m_pkthdr.ether_vtag = 0; | 579 | m->m_pkthdr.ether_vtag = 0; | |
580 | m->m_pkthdr.pkthdr_flags = 0; | 580 | m->m_pkthdr.pkthdr_flags = 0; | |
581 | SLIST_INIT(&m->m_pkthdr.tags); | 581 | SLIST_INIT(&m->m_pkthdr.tags); | |
582 | 582 | |||
583 | m->m_pkthdr.pattr_class = NULL; | 583 | m->m_pkthdr.pattr_class = NULL; | |
584 | m->m_pkthdr.pattr_af = AF_UNSPEC; | 584 | m->m_pkthdr.pattr_af = AF_UNSPEC; | |
585 | m->m_pkthdr.pattr_hdr = NULL; | 585 | m->m_pkthdr.pattr_hdr = NULL; | |
586 | 586 | |||
587 | return m; | 587 | return m; | |
588 | } | 588 | } | |
589 | 589 | |||
590 | struct mbuf * | |||
591 | m_get_n(int how, int type, size_t alignbytes, size_t nbytes) | |||
592 | { | |||
593 | struct mbuf *m; | |||
594 | ||||
595 | if (alignbytes > MCLBYTES || nbytes > MCLBYTES - alignbytes) | |||
596 | return NULL; | |||
597 | if ((m = m_get(how, type)) == NULL) | |||
598 | return NULL; | |||
599 | if (nbytes + alignbytes > MLEN) { | |||
600 | m_clget(m, how); | |||
601 | if ((m->m_flags & M_EXT) == 0) { | |||
602 | m_free(m); | |||
603 | return NULL; | |||
604 | } | |||
605 | } | |||
606 | m->m_len = alignbytes + nbytes; | |||
607 | m_adj(m, alignbytes); | |||
608 | ||||
609 | return m; | |||
610 | } | |||
611 | ||||
612 | struct mbuf * | |||
613 | m_gethdr_n(int how, int type, size_t alignbytes, size_t nbytes) | |||
614 | { | |||
615 | struct mbuf *m; | |||
616 | ||||
617 | if (nbytes > MCLBYTES || nbytes > MCLBYTES - alignbytes) | |||
618 | return NULL; | |||
619 | if ((m = m_gethdr(how, type)) == NULL) | |||
620 | return NULL; | |||
621 | if (alignbytes + nbytes > MHLEN) { | |||
622 | m_clget(m, how); | |||
623 | if ((m->m_flags & M_EXT) == 0) { | |||
624 | m_free(m); | |||
625 | return NULL; | |||
626 | } | |||
627 | } | |||
628 | m->m_len = m->m_pkthdr.len = alignbytes + nbytes; | |||
629 | m_adj(m, alignbytes); | |||
630 | ||||
631 | return m; | |||
632 | } | |||
633 | ||||
590 | void | 634 | void | |
591 | m_clget(struct mbuf *m, int how) | 635 | m_clget(struct mbuf *m, int how) | |
592 | { | 636 | { | |
593 | m->m_ext_storage.ext_buf = (char *)pool_cache_get_paddr(mcl_cache, | 637 | m->m_ext_storage.ext_buf = (char *)pool_cache_get_paddr(mcl_cache, | |
594 | how == M_WAIT ? (PR_WAITOK|PR_LIMITFAIL) : PR_NOWAIT, | 638 | how == M_WAIT ? (PR_WAITOK|PR_LIMITFAIL) : PR_NOWAIT, | |
595 | &m->m_ext_storage.ext_paddr); | 639 | &m->m_ext_storage.ext_paddr); | |
596 | 640 | |||
597 | if (m->m_ext_storage.ext_buf == NULL) | 641 | if (m->m_ext_storage.ext_buf == NULL) | |
598 | return; | 642 | return; | |
599 | 643 | |||
600 | KASSERTMSG((((vaddr_t)m->m_ext_storage.ext_buf & PAGE_MASK) + mclbytes | 644 | KASSERTMSG((((vaddr_t)m->m_ext_storage.ext_buf & PAGE_MASK) + mclbytes | |
601 | <= PAGE_SIZE), | 645 | <= PAGE_SIZE), | |
602 | "m=%p m->m_ext_storage.ext_buf=%p" | 646 | "m=%p m->m_ext_storage.ext_buf=%p" |
--- src/sys/sys/mbuf.h 2022/12/16 08:42:55 1.237
+++ src/sys/sys/mbuf.h 2023/04/12 06:48:08 1.238
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: mbuf.h,v 1.237 2022/12/16 08:42:55 msaitoh Exp $ */ | 1 | /* $NetBSD: mbuf.h,v 1.238 2023/04/12 06:48:08 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center and Matt Thomas of 3am Software Foundry. | 9 | * NASA Ames Research Center and Matt Thomas of 3am Software Foundry. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -730,26 +730,28 @@ extern struct mownerhead mowners; | @@ -730,26 +730,28 @@ extern struct mownerhead mowners; | |||
730 | extern struct mowner unknown_mowners[]; | 730 | extern struct mowner unknown_mowners[]; | |
731 | extern struct mowner revoked_mowner; | 731 | extern struct mowner revoked_mowner; | |
732 | #endif | 732 | #endif | |
733 | 733 | |||
734 | MALLOC_DECLARE(M_MBUF); | 734 | MALLOC_DECLARE(M_MBUF); | |
735 | MALLOC_DECLARE(M_SONAME); | 735 | MALLOC_DECLARE(M_SONAME); | |
736 | 736 | |||
737 | struct mbuf *m_copym(struct mbuf *, int, int, int); | 737 | struct mbuf *m_copym(struct mbuf *, int, int, int); | |
738 | struct mbuf *m_copypacket(struct mbuf *, int); | 738 | struct mbuf *m_copypacket(struct mbuf *, int); | |
739 | struct mbuf *m_devget(char *, int, int, struct ifnet *); | 739 | struct mbuf *m_devget(char *, int, int, struct ifnet *); | |
740 | struct mbuf *m_dup(struct mbuf *, int, int, int); | 740 | struct mbuf *m_dup(struct mbuf *, int, int, int); | |
741 | struct mbuf *m_get(int, int); | 741 | struct mbuf *m_get(int, int); | |
742 | struct mbuf *m_gethdr(int, int); | 742 | struct mbuf *m_gethdr(int, int); | |
743 | struct mbuf *m_get_n(int, int, size_t, size_t); | |||
744 | struct mbuf *m_gethdr_n(int, int, size_t, size_t); | |||
743 | struct mbuf *m_prepend(struct mbuf *,int, int); | 745 | struct mbuf *m_prepend(struct mbuf *,int, int); | |
744 | struct mbuf *m_pulldown(struct mbuf *, int, int, int *); | 746 | struct mbuf *m_pulldown(struct mbuf *, int, int, int *); | |
745 | struct mbuf *m_pullup(struct mbuf *, int); | 747 | struct mbuf *m_pullup(struct mbuf *, int); | |
746 | struct mbuf *m_copyup(struct mbuf *, int, int); | 748 | struct mbuf *m_copyup(struct mbuf *, int, int); | |
747 | struct mbuf *m_split(struct mbuf *,int, int); | 749 | struct mbuf *m_split(struct mbuf *,int, int); | |
748 | struct mbuf *m_getptr(struct mbuf *, int, int *); | 750 | struct mbuf *m_getptr(struct mbuf *, int, int *); | |
749 | void m_adj(struct mbuf *, int); | 751 | void m_adj(struct mbuf *, int); | |
750 | struct mbuf *m_defrag(struct mbuf *, int); | 752 | struct mbuf *m_defrag(struct mbuf *, int); | |
751 | int m_apply(struct mbuf *, int, int, | 753 | int m_apply(struct mbuf *, int, int, | |
752 | int (*)(void *, void *, unsigned int), void *); | 754 | int (*)(void *, void *, unsigned int), void *); | |
753 | void m_cat(struct mbuf *,struct mbuf *); | 755 | void m_cat(struct mbuf *,struct mbuf *); | |
754 | void m_clget(struct mbuf *, int); | 756 | void m_clget(struct mbuf *, int); | |
755 | void m_copyback(struct mbuf *, int, int, const void *); | 757 | void m_copyback(struct mbuf *, int, int, const void *); |