Motr  M0
buffer_pool.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/misc.h" /* m0_forall */
24 #include "lib/memory.h"/* M0_ALLOC_PTR */
25 #include "lib/errno.h" /* ENOMEM */
26 #include "lib/arith.h" /* M0_CNT_INC, M0_CNT_DEC */
27 #include "motr/magic.h"
28 #include "net/buffer_pool.h"
29 #include "net/net_internal.h"
30 
31 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_NET
32 #include "lib/trace.h"
33 
40 M0_TL_DESCR_DEFINE(m0_net_pool, "net_buffer_pool", M0_INTERNAL,
41  struct m0_net_buffer, nb_lru, nb_magic,
43 M0_TL_DEFINE(m0_net_pool, M0_INTERNAL, struct m0_net_buffer);
44 
45 static bool pool_colour_check(const struct m0_net_buffer_pool *pool);
46 static bool pool_lru_buffer_check(const struct m0_net_buffer_pool *pool);
47 static bool colour_is_valid(const struct m0_net_buffer_pool *pool,
48  uint32_t colour);
49 
50 M0_INTERNAL bool m0_net_buffer_pool_invariant(const struct m0_net_buffer_pool
51  *pool)
52 {
53  return _0C(pool != NULL) &&
54  /* domain must be set and initialized */
55  _0C(pool->nbp_ndom != NULL) &&
56  _0C(pool->nbp_ndom->nd_xprt != NULL) &&
57  /* must have the appropriate callback */
58  _0C(pool->nbp_ops != NULL) &&
60  _0C(pool->nbp_free <= pool->nbp_buf_nr) &&
61  _0C(pool->nbp_free ==
62  m0_net_pool_tlist_length(&pool->nbp_lru)) &&
65  _0C((pool->nbp_colours_nr == 0) == (pool->nbp_colours == NULL));
66 }
67 
68 static bool pool_colour_check(const struct m0_net_buffer_pool *pool)
69 {
70  return m0_forall(i, pool->nbp_colours_nr,
71  m0_tl_forall(m0_net_tm, nb, &pool->nbp_colours[i],
72  m0_net_pool_tlink_is_in(nb)));
73 }
74 
75 static bool pool_lru_buffer_check(const struct m0_net_buffer_pool *pool)
76 {
77  return m0_tl_forall(m0_net_pool, nb, &pool->nbp_lru,
78  !(nb->nb_flags & M0_NET_BUF_QUEUED) &&
79  (nb->nb_flags & M0_NET_BUF_REGISTERED));
80 }
81 
83  struct m0_net_domain *ndom,
84  uint32_t threshold, uint32_t seg_nr,
85  m0_bcount_t seg_size, uint32_t colours,
86  unsigned shift, bool dont_dump)
87 {
88  int i;
89 
90  M0_PRE(pool != NULL);
91  M0_PRE(ndom != NULL);
93 
94  pool->nbp_threshold = threshold;
95  pool->nbp_ndom = ndom;
96  pool->nbp_free = 0;
97  pool->nbp_buf_nr = 0;
98  pool->nbp_seg_nr = seg_nr;
99  pool->nbp_seg_size = seg_size;
100  pool->nbp_colours_nr = colours;
101  pool->nbp_align = shift;
102  pool->nbp_dont_dump = dont_dump;
103 
104  if (colours == 0)
105  pool->nbp_colours = NULL;
106  else {
107  M0_ALLOC_ARR(pool->nbp_colours, colours);
108  if (pool->nbp_colours == NULL)
109  return M0_ERR(-ENOMEM);
110  }
111  m0_mutex_init(&pool->nbp_mutex);
112  m0_net_pool_tlist_init(&pool->nbp_lru);
113  for (i = 0; i < colours; ++i)
114  m0_net_tm_tlist_init(&pool->nbp_colours[i]);
115  return 0;
116 }
117 
122 static bool net_buffer_pool_grow(struct m0_net_buffer_pool *pool);
123 
124 
126  uint32_t buf_nr)
127 {
128  int buffers = 0;
130 
131  while (buf_nr--) {
133  return buffers;
134  buffers++;
135  }
137  return buffers;
138 }
139 
142  struct m0_net_buffer *nb)
143 {
144  m0_net_pool_tlink_del_fini(nb);
145  m0_net_tm_tlist_remove(nb);
146  m0_net_tm_tlink_fini(nb);
147  m0_net_buffer_deregister(nb, pool->nbp_ndom);
148  m0_bufvec_free_aligned_packed(&nb->nb_buffer, pool->nbp_align);
149  m0_free(nb);
150  M0_CNT_DEC(pool->nbp_buf_nr);
152 }
153 
155 {
156  int i;
157  struct m0_net_buffer *nb;
158 
160 
161  if (pool->nbp_colours == NULL && pool->nbp_colours_nr != 0)
162  return;
163  /*
164  * The lock here is only needed to keep m0_net_buffer_pool_invariant()
165  * happy. The caller must guarantee that there is no concurrency at this
166  * point.
167  */
170 
171  M0_ASSERT(pool->nbp_free == pool->nbp_buf_nr);
172 
173  m0_tl_for(m0_net_pool, &pool->nbp_lru, nb) {
174  M0_CNT_DEC(pool->nbp_free);
175  buffer_remove(pool, nb);
176  } m0_tl_endfor;
178  m0_net_pool_tlist_fini(&pool->nbp_lru);
179  for (i = 0; i < pool->nbp_colours_nr; i++)
180  m0_net_tm_tlist_fini(&pool->nbp_colours[i]);
181  if (pool->nbp_colours != NULL)
182  m0_free(pool->nbp_colours);
183  m0_mutex_fini(&pool->nbp_mutex);
184 }
185 
187 {
188  m0_mutex_lock(&pool->nbp_mutex);
189 }
190 
192  *pool)
193 {
194  return m0_mutex_is_locked(&pool->nbp_mutex);
195 }
196 
197 M0_INTERNAL bool m0_net_buffer_pool_is_not_locked(const struct
199 {
200  return m0_mutex_is_not_locked(&pool->nbp_mutex);
201 }
202 
204 {
205  m0_mutex_unlock(&pool->nbp_mutex);
206 }
207 
208 static bool colour_is_valid(const struct m0_net_buffer_pool *pool,
209  uint32_t colour)
210 {
211  return colour == M0_BUFFER_ANY_COLOUR || colour < pool->nbp_colours_nr;
212 }
213 
214 M0_INTERNAL struct m0_net_buffer *
216 {
217  struct m0_net_buffer *nb;
218 
219  M0_ENTRY();
221  M0_PRE(colour_is_valid(pool, colour));
222 
223  if (pool->nbp_free <= 0)
224  return NULL;
225  if (colour != M0_BUFFER_ANY_COLOUR &&
226  !m0_net_tm_tlist_is_empty(&pool->nbp_colours[colour]))
227  nb = m0_net_tm_tlist_head(&pool->nbp_colours[colour]);
228  else
229  nb = m0_net_pool_tlist_head(&pool->nbp_lru);
230  M0_ASSERT(nb != NULL);
231  m0_net_pool_tlist_del(nb);
232  m0_net_tm_tlist_remove(nb);
233  M0_CNT_DEC(pool->nbp_free);
234  if (pool->nbp_free < pool->nbp_threshold)
235  pool->nbp_ops->nbpo_below_threshold(pool);
236  nb->nb_pool = pool;
238  M0_POST(nb->nb_ep == NULL);
239  M0_LEAVE();
240  return nb;
241 }
242 
244  struct m0_net_buffer *buf,
245  uint32_t colour)
246 {
247  M0_PRE(buf != NULL);
249  M0_PRE(buf->nb_ep == NULL);
250  M0_PRE(colour_is_valid(pool, colour));
251  M0_PRE(!(buf->nb_flags & M0_NET_BUF_QUEUED));
252  M0_PRE(buf->nb_flags & M0_NET_BUF_REGISTERED);
253  M0_PRE(pool->nbp_ndom == buf->nb_dom);
254 
255  M0_ENTRY();
256  M0_ASSERT(buf->nb_magic == M0_NET_BUFFER_LINK_MAGIC);
257  M0_ASSERT(!m0_net_pool_tlink_is_in(buf));
258  if (colour != M0_BUFFER_ANY_COLOUR) {
259  M0_ASSERT(!m0_net_tm_tlink_is_in(buf));
260  m0_net_tm_tlist_add(&pool->nbp_colours[colour], buf);
261  }
262  m0_net_pool_tlist_add_tail(&pool->nbp_lru, buf);
263  M0_CNT_INC(pool->nbp_free);
264  if (pool->nbp_free == 1)
265  pool->nbp_ops->nbpo_not_empty(pool);
267  M0_LEAVE();
268 }
269 
271 {
272  int rc;
273  struct m0_net_buffer *nb;
274 
276 
277  M0_ALLOC_PTR(nb);
278  if (nb == NULL)
279  return false;
280  rc = m0_bufvec_alloc_aligned_packed(&nb->nb_buffer, pool->nbp_seg_nr,
281  pool->nbp_seg_size, pool->nbp_align);
282  if (rc != 0)
283  goto clean;
284  if(pool->nbp_align != 0 && pool->nbp_dont_dump) {
286  if (rc != 0) {
287  M0_LOG(M0_ERROR, "failed to mark bufvec %p dont_dump",
288  &nb->nb_buffer);
289  goto clean;
290  }
291  }
292 
293  rc = m0_net_buffer_register(nb, pool->nbp_ndom);
294  if (rc != 0)
295  goto clean;
296  m0_net_pool_tlink_init(nb);
297  m0_net_tm_tlink_init(nb);
298 
299  M0_CNT_INC(pool->nbp_buf_nr);
302  return true;
303 clean:
304  M0_ASSERT(rc != 0);
305  m0_bufvec_free_aligned_packed(&nb->nb_buffer, pool->nbp_align);
306  m0_free(nb);
307  return false;
308 }
309 
311 {
312  struct m0_net_buffer *nb;
313 
315 
316  if (pool->nbp_free <= pool->nbp_threshold)
317  return false;
318  M0_CNT_DEC(pool->nbp_free);
319  nb = m0_net_pool_tlist_head(&pool->nbp_lru);
320  M0_ASSERT(nb != NULL);
321  buffer_remove(pool, nb);
322  return true;
323 }
324 
325 #undef M0_TRACE_SUBSYSTEM
326  /* end of net_buffer_pool */
328 
329 /*
330  * Local variables:
331  * c-indentation-style: "K&R"
332  * c-basic-offset: 8
333  * tab-width: 8
334  * fill-column: 80
335  * scroll-step: 1
336  * End:
337  */
static m0_bcount_t seg_size
Definition: net.c:118
M0_INTERNAL void m0_net_buffer_pool_fini(struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:154
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL int m0_bufvec_alloc_aligned_packed(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size, unsigned shift)
Definition: vec.c:366
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
struct m0_net_buffer_pool * nb_pool
Definition: net.h:1508
static uint32_t seg_nr
Definition: net.c:119
#define NULL
Definition: misc.h:38
struct m0_bufvec nb_buffer
Definition: net.h:1322
M0_INTERNAL int m0_net_buffer_register(struct m0_net_buffer *buf, struct m0_net_domain *dom)
Definition: buf.c:65
M0_TL_DEFINE(m0_net_pool, M0_INTERNAL, struct m0_net_buffer)
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL bool m0_mutex_is_not_locked(const struct m0_mutex *mutex)
Definition: mutex.c:101
M0_INTERNAL struct m0_net_buffer * m0_net_buffer_pool_get(struct m0_net_buffer_pool *pool, uint32_t colour)
Definition: buffer_pool.c:215
M0_INTERNAL void m0_net_buffer_pool_unlock(struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:203
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: sock.c:887
static bool net_buffer_pool_grow(struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:270
#define m0_tl_endfor
Definition: tlist.h:700
#define M0_ENTRY(...)
Definition: trace.h:170
int i
Definition: dir.c:1033
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL bool m0_net_buffer_pool_is_locked(const struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:191
M0_INTERNAL bool m0_net_buffer_pool_invariant(const struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:50
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_net_buffer_pool_prune(struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:310
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
M0_INTERNAL bool m0_net_buffer_pool_is_not_locked(const struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:197
static void buffer_remove(struct m0_net_buffer_pool *pool, struct m0_net_buffer *nb)
Definition: buffer_pool.c:141
M0_INTERNAL void m0_net_buffer_pool_lock(struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:186
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
M0_TL_DESCR_DEFINE(m0_net_pool, "net_buffer_pool", M0_INTERNAL, struct m0_net_buffer, nb_lru, nb_magic, M0_NET_BUFFER_LINK_MAGIC, M0_NET_BUFFER_HEAD_MAGIC)
static bool pool_lru_buffer_check(const struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:75
static struct m0_pool pool
Definition: iter_ut.c:58
#define m0_forall(var, nr,...)
Definition: misc.h:112
M0_INTERNAL void m0_net_buffer_deregister(struct m0_net_buffer *buf, struct m0_net_domain *dom)
Definition: buf.c:107
#define M0_CNT_INC(cnt)
Definition: arith.h:226
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL int m0__bufvec_dont_dump(struct m0_bufvec *bufvec)
Definition: vec.c:331
M0_INTERNAL int m0_net_buffer_pool_provision(struct m0_net_buffer_pool *pool, uint32_t buf_nr)
Definition: buffer_pool.c:125
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL int32_t m0_net_domain_get_max_buffer_segments(struct m0_net_domain *dom)
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
M0_INTERNAL void m0_net_buffer_pool_put(struct m0_net_buffer_pool *pool, struct m0_net_buffer *buf, uint32_t colour)
Definition: buffer_pool.c:243
M0_INTERNAL void m0_bufvec_free_aligned_packed(struct m0_bufvec *bufvec, unsigned shift)
Definition: vec.c:443
static bool pool_colour_check(const struct m0_net_buffer_pool *pool)
Definition: buffer_pool.c:68
#define M0_PRE_EX(cond)
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
static bool colour_is_valid(const struct m0_net_buffer_pool *pool, uint32_t colour)
Definition: buffer_pool.c:208
M0_INTERNAL int m0_net_buffer_pool_init(struct m0_net_buffer_pool *pool, struct m0_net_domain *ndom, uint32_t threshold, uint32_t seg_nr, m0_bcount_t seg_size, uint32_t colours, unsigned shift, bool dont_dump)
Definition: buffer_pool.c:82
int32_t rc
Definition: trigger_fop.h:47
#define M0_POST_EX(cond)
struct m0_net_end_point * nb_ep
Definition: net.h:1424
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735