1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
14  */
15 
16 /*
17  * Some minimal streams mblk_t management functions needed by
18  * ksocket_sendmblk:  esballoca(), freemsg(), ...
19  */
20 
21 #include <sys/types.h>
22 #include <sys/systm.h>
23 #include <sys/cred.h>
24 #include <sys/errno.h>
25 #include <sys/socket.h>
26 #include <sys/ksocket.h>
27 #include <sys/stream.h>
28 #include <sys/strsubr.h>
29 #include <sys/strsun.h>
30 #include <sys/debug.h>
31 #include <sys/kmem.h>
32 #include <limits.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <umem.h>
36 
37 static void
38 lastfree(mblk_t *mp, dblk_t *db)
39 {
40 	frtn_t *frp = db->db_frtnp;
41 
42 	ASSERT(db->db_mblk == mp);
43 	ASSERT(mp->b_datap == db);
44 
45 	ASSERT(frp != NULL);
46 	frp->free_func(frp->free_arg);
47 
48 	kmem_free(mp, sizeof (*mp));
49 	kmem_free(db, sizeof (*db));
50 }
51 
52 
53 mblk_t *
54 esballoca(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
55 {
56 	dblk_t *db;
57 	mblk_t *mp;
58 
59 	db = kmem_zalloc(sizeof (*db), KM_SLEEP);
60 	mp = kmem_zalloc(sizeof (*mp), KM_SLEEP);
61 
62 	mp->b_datap = db;
63 	db->db_mblk = mp;
64 
65 	db->db_base = base;
66 	db->db_lim = base + size;
67 	db->db_free = db->db_lastfree = lastfree;
68 	db->db_frtnp = frp;
69 
70 	/*
71 	 * streams.c uses these weird macro:
72 	 * DBLK_RTFU_WORD(dbp) = db_rtfu
73 	 * where db_rtfu = DBLK_RTFU(1, M_DATA, 0, 0)
74 	 * Probably only care about db_ref
75 	 */
76 	db->db_ref = 1;
77 
78 	mp->b_next = mp->b_prev = mp->b_cont = NULL;
79 	mp->b_rptr = mp->b_wptr = base;
80 	mp->b_queue = NULL;
81 
82 	return (mp);
83 }
84 
85 /*
86  * Same as esballoca() but sleeps waiting for memory.
87  * (in here, both sleep)
88  */
89 mblk_t *
90 esballoca_wait(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
91 {
92 	return (esballoca(base, size, pri, frp));
93 }
94 
95 void
96 freemsg(mblk_t *mp)
97 {
98 	mblk_t *mp_cont;
99 	dblk_t *db;
100 
101 	while (mp) {
102 		db = mp->b_datap;
103 		mp_cont = mp->b_cont;
104 
105 		ASSERT(db->db_ref > 0);
106 		ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
107 
108 		db->db_free(mp, db);
109 		mp = mp_cont;
110 	}
111 }
112