Motr  M0
rings.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-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 #include "lib/finject.h"
23 #include "lib/mutex.h"
24 #include "lib/list.h"
25 #include "lib/memory.h"
26 #include "lib/errno.h"
27 #include "lib/misc.h"
28 #include "lib/chan.h"
29 #include "lib/vec.h"
30 #include "fid/fid.h" /* M0_FID_TINIT */
31 #include "xcode/xcode.h"
32 #include "ut/ut.h"
33 
34 #include "rm/rm.h"
35 #include "rm/ut/rings.h"
36 
38  .rt_name = "Rings of Power",
39  .rt_id = RINGS_RESOURCE_TYPE_ID,
40 };
41 
42 static void rings_policy(struct m0_rm_resource *resource,
43  struct m0_rm_incoming *in)
44 {
45  struct m0_rm_credit *credit;
46  struct m0_rm_pin *pin;
47  uint64_t datum;
48  int zeroes;
49 
50  /* Grant "real" ring if ANY_RING was requested */
51  if (in->rin_want.cr_datum == ANY_RING) {
52  /* One credit is always enough to satisfy request for ANY_RING.
53  * RM should not pin more than one credit in tests.
54  */
55  M0_ASSERT(pi_tlist_length(&in->rin_pins) == 1);
56  m0_tl_for (pi, &in->rin_pins, pin) {
58  credit = pin->rp_credit;
59  datum = credit->cr_datum;
60  zeroes = 0;
61  M0_ASSERT(datum != 0);
62  while ((datum & 0x01) == 0) {
63  zeroes++;
64  datum >>= 1;
65  }
66  in->rin_want.cr_datum = 1 << zeroes;
67  } m0_tl_endfor;
68  }
69 
70 }
71 
72 static void rings_credit_init(struct m0_rm_resource *resource,
73  struct m0_rm_credit *credit)
74 {
75  credit->cr_datum = 0;
76  credit->cr_ops = &rings_credit_ops;
77 }
78 
79 void rings_resource_free(struct m0_rm_resource *resource)
80 {
81  struct m0_rings *rings;
82 
83  rings = container_of(resource, struct m0_rings, rs_resource);
84  m0_free(rings);
85 }
86 
87 const struct m0_rm_resource_ops rings_ops = {
89  .rop_policy = rings_policy,
90  .rop_credit_init = rings_credit_init,
91  .rop_resource_free = rings_resource_free,
92 };
93 
94 static bool rings_resources_are_equal(const struct m0_rm_resource *c0,
95  const struct m0_rm_resource *c1)
96 {
97  return c0 == c1;
98 }
99 
100 static bool rings_resource_is(const struct m0_rm_resource *res, uint64_t res_id)
101 {
102  struct m0_rings *ring;
103 
104  ring = container_of(res, struct m0_rings, rs_resource);
105  M0_ASSERT(ring != NULL);
106  return res_id == ring->rs_id;
107 }
108 
109 static m0_bcount_t rings_resource_len(const struct m0_rm_resource *resource)
110 {
111  /* Resource type id + resource id */
112  return (m0_bcount_t) sizeof(uint64_t) + sizeof(uint64_t);
113 }
114 
116  const struct m0_rm_resource *resource)
117 {
118  struct m0_rings *rings;
119 
120  rings = container_of(resource, struct m0_rings, rs_resource);
121  M0_ASSERT(rings != NULL);
122 
123  m0_bufvec_cursor_copyto(cur, (void *)&rings->rs_id,
124  sizeof rings->rs_id);
125  return 0;
126 }
127 
129  struct m0_rm_resource **resource)
130 {
131  static uint64_t res_id;
132  struct m0_rings *rings;
133 
134  m0_bufvec_cursor_copyfrom(cur, &res_id, sizeof res_id);
135 
136  M0_ALLOC_PTR(rings);
137  if (rings == NULL)
138  return -ENOMEM;
139 
140  rings->rs_id = res_id;
143  rings->rs_resource.r_ops = &rings_ops;
144 
145  *resource = &rings->rs_resource;
146  return 0;
147 }
148 
151  .rto_is = rings_resource_is,
152  .rto_len = rings_resource_len,
153  .rto_encode = rings_resource_encode,
154  .rto_decode = rings_resource_decode
155 };
156 
157 static bool rings_credit_intersects(const struct m0_rm_credit *c0,
158  const struct m0_rm_credit *c1)
159 {
160  if (c0->cr_datum == ANY_RING || c1->cr_datum == ANY_RING)
161  return true;
162  return (c0->cr_datum & c1->cr_datum) != 0;
163 }
164 
165 static int rings_credit_join(struct m0_rm_credit *c0,
166  const struct m0_rm_credit *c1)
167 {
168  M0_ASSERT(c0->cr_datum != ANY_RING && c1->cr_datum != ANY_RING);
169  c0->cr_datum |= c1->cr_datum;
170  return 0;
171 }
172 
173 static int rings_credit_diff(struct m0_rm_credit *c0,
174  const struct m0_rm_credit *c1)
175 {
176  M0_ASSERT(ergo(c1->cr_datum == ANY_RING, c0->cr_datum == ANY_RING));
177 
178  if (c0->cr_datum == ANY_RING)
179  c0->cr_datum = (c1->cr_datum != 0) ? 0 : c0->cr_datum;
180  else
181  c0->cr_datum &= ~c1->cr_datum;
182  return 0;
183 }
184 
185 static void rings_credit_free(struct m0_rm_credit *credit)
186 {
187  credit->cr_datum = 0;
188 }
189 
190 static int rings_credit_encdec(struct m0_rm_credit *credit,
191  struct m0_bufvec_cursor *cur,
192  enum m0_xcode_what what)
193 {
194  return m0_xcode_encdec(&M0_XCODE_OBJ(&M0_XT_U64, &credit->cr_datum),
195  cur, what);
196 }
197 
198 static int rings_credit_encode(struct m0_rm_credit *credit,
199  struct m0_bufvec_cursor *cur)
200 {
201  return rings_credit_encdec(credit, cur, M0_XCODE_ENCODE);
202 }
203 
204 static int rings_credit_decode(struct m0_rm_credit *credit,
205  struct m0_bufvec_cursor *cur)
206 {
207  return rings_credit_encdec(credit, cur, M0_XCODE_DECODE);
208 }
209 
211  const struct m0_rm_credit *src)
212 {
213  if (M0_FI_ENABLED("fail_copy"))
214  return -ENOMEM;
215 
216  dest->cr_datum = src->cr_datum;
217  dest->cr_owner = src->cr_owner;
218  dest->cr_ops = src->cr_ops;
219  return 0;
220 }
221 
222 static void rings_initial_capital(struct m0_rm_credit *self)
223 {
224  self->cr_datum = ALLRINGS;
225 }
226 
227 
228 static m0_bcount_t rings_credit_len(const struct m0_rm_credit *credit)
229 {
230  struct m0_xcode_obj datumobj;
231  struct m0_xcode_ctx ctx;
232 
233  datumobj.xo_type = &M0_XT_U64;
234  datumobj.xo_ptr = (void *)&credit->cr_datum;
235  m0_xcode_ctx_init(&ctx, &datumobj);
236  return m0_xcode_length(&ctx);
237 }
238 
239 static bool rings_is_subset(const struct m0_rm_credit *src,
240  const struct m0_rm_credit *dest)
241 {
242  M0_ASSERT(dest->cr_datum != ANY_RING);
243  if (src->cr_datum == ANY_RING)
244  return dest->cr_datum != 0;
245  return (dest->cr_datum & src->cr_datum) == src->cr_datum;
246 }
247 
248 static int rings_disjoin(struct m0_rm_credit *src,
249  const struct m0_rm_credit *dest,
250  struct m0_rm_credit *intersection)
251 {
252  M0_ASSERT(src->cr_datum != ANY_RING && dest->cr_datum != ANY_RING);
253 
254  intersection->cr_datum = src->cr_datum & dest->cr_datum;
255  src->cr_datum &= ~intersection->cr_datum;
256  return 0;
257 }
258 
259 static bool rings_conflicts(const struct m0_rm_credit *c0,
260  const struct m0_rm_credit *c1)
261 {
262  M0_ASSERT(c0->cr_datum != ANY_RING || c1->cr_datum != ANY_RING);
263 
264  if (c0->cr_datum == ANY_RING || c1->cr_datum == ANY_RING)
265  return false;
266  if (c0->cr_datum == SHARED_RING && c1->cr_datum == SHARED_RING)
267  return false;
268 
269  return c0->cr_datum & c1->cr_datum;
270 }
271 
274  .cro_join = rings_credit_join,
275  .cro_diff = rings_credit_diff,
276  .cro_copy = rings_credit_copy,
277  .cro_free = rings_credit_free,
278  .cro_encode = rings_credit_encode,
279  .cro_decode = rings_credit_decode,
280  .cro_len = rings_credit_len,
281  .cro_is_subset = rings_is_subset,
282  .cro_disjoin = rings_disjoin,
283  .cro_conflicts = rings_conflicts,
284  .cro_initial_capital = rings_initial_capital,
285 };
286 
287 static void rings_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
288 {
289  M0_PRE(in != NULL);
290 }
291 
293 {
294 }
295 
298  .rio_conflict = rings_incoming_conflict
299 };
300 
301 static void rings_rtype_set(struct rm_ut_data *self)
302 {
303  struct m0_rm_resource_type *rings_rtype;
304  int rc;
305 
306  M0_ALLOC_PTR(rings_rtype);
307  M0_ASSERT(rings_rtype != NULL);
308  rings_rtype->rt_id = 0;
309  rings_rtype->rt_ops = &rings_rtype_ops;
310  rc = m0_rm_type_register(&self->rd_dom, rings_rtype);
311  M0_ASSERT(rc == 0);
312  self->rd_rt = rings_rtype;
313 }
314 
315 static void rings_rtype_unset(struct rm_ut_data *self)
316 {
317  m0_rm_type_deregister(self->rd_rt);
318  m0_free0(&self->rd_rt);
319 }
320 
321 static void rings_res_set(struct rm_ut_data *self)
322 {
323  struct m0_rings *rings_res;
324 
325  M0_ALLOC_PTR(rings_res);
326  M0_ASSERT(rings_res != NULL);
327  rings_res->rs_resource.r_ops = &rings_ops;
328  m0_rm_resource_add(self->rd_rt, &rings_res->rs_resource);
329  self->rd_res = &rings_res->rs_resource;
330 }
331 
332 static void rings_res_unset(struct rm_ut_data *self)
333 {
334  struct m0_rings *rings_res;
335 
336  m0_rm_resource_del(self->rd_res);
337  rings_res = container_of(self->rd_res, struct m0_rings, rs_resource);
338  m0_free(rings_res);
339  self->rd_res = NULL;
340 }
341 
342 static void rings_owner_set(struct rm_ut_data *self)
343 {
344  struct m0_rm_owner *owner;
346  (uint64_t)self);
347 
348  M0_ALLOC_PTR(owner);
349  M0_ASSERT(owner != NULL);
350  m0_rm_owner_init(owner, &fid, &m0_rm_no_group, self->rd_res, NULL);
351  self->rd_owner = owner;
352 }
353 
354 static void rings_owner_unset(struct rm_ut_data *self)
355 {
356  m0_rm_owner_fini(self->rd_owner);
357  m0_free0(&self->rd_owner);
358 }
359 
360 static void rings_datum_set(struct rm_ut_data *self)
361 {
362  self->rd_credit.cr_datum = ALLRINGS;
363 }
364 
365 const static struct rm_ut_data_ops rings_ut_data_ops = {
367  .rtype_unset = rings_rtype_unset,
368  .resource_set = rings_res_set,
369  .resource_unset = rings_res_unset,
370  .owner_set = rings_owner_set,
371  .owner_unset = rings_owner_unset,
372  .credit_datum_set = rings_datum_set
373 };
374 
376 {
377  data->rd_ops = &rings_ut_data_ops;
378 }
379 
380 /*
381  * Local variables:
382  * c-indentation-style: "K&R"
383  * c-basic-offset: 8
384  * tab-width: 8
385  * fill-column: 80
386  * scroll-step: 1
387  * End:
388  */
const struct m0_rm_credit_ops * cr_ops
Definition: rm.h:502
static void rings_owner_set(struct rm_ut_data *self)
Definition: rings.c:342
M0_INTERNAL int m0_xcode_encdec(struct m0_xcode_obj *obj, struct m0_bufvec_cursor *cur, enum m0_xcode_what what)
Definition: xcode.c:416
struct m0_rm_resource_type * r_type
Definition: rm.h:304
#define M0_PRE(cond)
const struct m0_xcode_type * xo_type
Definition: xcode.h:351
const struct m0_rm_resource_ops rings_ops
Definition: rings.c:87
uint64_t cr_datum
Definition: rm.h:514
static bool rings_resources_are_equal(const struct m0_rm_resource *c0, const struct m0_rm_resource *c1)
Definition: rings.c:94
#define NULL
Definition: misc.h:38
bool(* cro_intersects)(const struct m0_rm_credit *self, const struct m0_rm_credit *c1)
Definition: rm.h:579
uint64_t rs_id
Definition: rings.h:111
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
#define ergo(a, b)
Definition: misc.h:293
static int rings_credit_decode(struct m0_rm_credit *credit, struct m0_bufvec_cursor *cur)
Definition: rings.c:204
void(* rio_complete)(struct m0_rm_incoming *in, int32_t rc)
Definition: rm.h:1493
static m0_bcount_t rings_resource_len(const struct m0_rm_resource *resource)
Definition: rings.c:109
const struct m0_rm_credit_ops rings_credit_ops
Definition: rings.c:272
bool(* rto_eq)(const struct m0_rm_resource *resource0, const struct m0_rm_resource *resource1)
Definition: rm.h:454
struct m0_bufvec data
Definition: di.c:40
const struct m0_rm_incoming_ops rings_incoming_ops
Definition: rings.c:296
uint64_t m0_bcount_t
Definition: types.h:77
static bool rings_resource_is(const struct m0_rm_resource *res, uint64_t res_id)
Definition: rings.c:100
static bool rings_conflicts(const struct m0_rm_credit *c0, const struct m0_rm_credit *c1)
Definition: rings.c:259
#define container_of(ptr, type, member)
Definition: misc.h:33
struct m0_rm_credit rin_want
Definition: rm.h:1450
m0_xcode_what
Definition: xcode.h:647
static int rings_credit_join(struct m0_rm_credit *c0, const struct m0_rm_credit *c1)
Definition: rings.c:165
static const struct rm_ut_data_ops rings_ut_data_ops
Definition: rings.c:365
const struct m0_rm_resource_type_ops rings_rtype_ops
Definition: rings.c:149
#define m0_tl_endfor
Definition: tlist.h:700
struct m0_fid fid
Definition: di.c:46
M0_INTERNAL int m0_xcode_length(struct m0_xcode_ctx *ctx)
Definition: xcode.c:390
static int rings_credit_diff(struct m0_rm_credit *c0, const struct m0_rm_credit *c1)
Definition: rings.c:173
const struct m0_rm_resource_ops * r_ops
Definition: rm.h:305
static void rings_initial_capital(struct m0_rm_credit *self)
Definition: rings.c:222
static bool rings_credit_intersects(const struct m0_rm_credit *c0, const struct m0_rm_credit *c1)
Definition: rings.c:157
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_copyfrom(struct m0_bufvec_cursor *scur, void *ddata, m0_bcount_t num_bytes)
Definition: vec.c:692
struct m0_rm_credit * rp_credit
Definition: rm.h:1677
static m0_bcount_t rings_credit_len(const struct m0_rm_credit *credit)
Definition: rings.c:228
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
#define m0_free0(pptr)
Definition: memory.h:77
const struct m0_uint128 m0_rm_no_group
Definition: rm.c:211
#define M0_ASSERT(cond)
static void rings_datum_set(struct rm_ut_data *self)
Definition: rings.c:360
Definition: rings.h:96
M0_INTERNAL void m0_rm_owner_fini(struct m0_rm_owner *owner)
Definition: rm.c:943
static int rings_credit_encode(struct m0_rm_credit *credit, struct m0_bufvec_cursor *cur)
Definition: rings.c:198
Definition: rings.h:94
void(* rtype_set)(struct rm_ut_data *self)
Definition: rmut.h:96
static int rings_resource_encode(struct m0_bufvec_cursor *cur, const struct m0_rm_resource *resource)
Definition: rings.c:115
struct m0_rm_resource_type rings_resource_type
Definition: rings.c:37
struct m0_pdclust_instance pi
Definition: fd.c:107
static void rings_policy(struct m0_rm_resource *resource, struct m0_rm_incoming *in)
Definition: rings.c:42
static void rings_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
Definition: rings.c:287
static void rings_credit_free(struct m0_rm_credit *credit)
Definition: rings.c:185
static int rings_resource_decode(struct m0_bufvec_cursor *cur, struct m0_rm_resource **resource)
Definition: rings.c:128
static int rings_disjoin(struct m0_rm_credit *src, const struct m0_rm_credit *dest, struct m0_rm_credit *intersection)
Definition: rings.c:248
const char * rt_name
Definition: rm.h:389
static void rings_incoming_conflict(struct m0_rm_incoming *in)
Definition: rings.c:292
static int rings_credit_encdec(struct m0_rm_credit *credit, struct m0_bufvec_cursor *cur, enum m0_xcode_what what)
Definition: rings.c:190
M0_INTERNAL void m0_rm_resource_add(struct m0_rm_resource_type *rtype, struct m0_rm_resource *res)
Definition: rm.c:337
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static void rings_owner_unset(struct rm_ut_data *self)
Definition: rings.c:354
uint32_t rp_flags
Definition: rm.h:1676
static bool rings_is_subset(const struct m0_rm_credit *src, const struct m0_rm_credit *dest)
Definition: rings.c:239
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_copyto(struct m0_bufvec_cursor *dcur, void *sdata, m0_bcount_t num_bytes)
Definition: vec.c:677
static void rings_res_unset(struct rm_ut_data *self)
Definition: rings.c:332
const struct m0_rm_resource_type_ops * rt_ops
Definition: rm.h:388
M0_INTERNAL int m0_rm_type_register(struct m0_rm_domain *dom, struct m0_rm_resource_type *rt)
Definition: rm.c:252
void * xo_ptr
Definition: xcode.h:353
struct m0_tl rin_pins
Definition: rm.h:1466
void rings_utdata_ops_set(struct rm_ut_data *data)
Definition: rings.c:375
#define M0_XCODE_OBJ(type, ptr)
Definition: xcode.h:962
struct m0_rm_resource rs_resource
Definition: rings.h:110
static void rings_rtype_set(struct rm_ut_data *self)
Definition: rings.c:301
Definition: nucleus.c:42
M0_INTERNAL void m0_xcode_ctx_init(struct m0_xcode_ctx *ctx, const struct m0_xcode_obj *obj)
Definition: xcode.c:373
static void rings_rtype_unset(struct rm_ut_data *self)
Definition: rings.c:315
M0_INTERNAL void m0_rm_type_deregister(struct m0_rm_resource_type *rt)
Definition: rm.c:288
static void rings_res_set(struct rm_ut_data *self)
Definition: rings.c:321
M0_INTERNAL void m0_rm_owner_init(struct m0_rm_owner *owner, struct m0_fid *fid, const struct m0_uint128 *group, struct m0_rm_resource *res, struct m0_rm_remote *creditor)
Definition: rm.c:609
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
const struct m0_xcode_type M0_XT_U64
Definition: xcode.c:940
static int rings_credit_copy(struct m0_rm_credit *dest, const struct m0_rm_credit *src)
Definition: rings.c:210
struct m0_pdclust_src_addr src
Definition: fd.c:108
int32_t rc
Definition: trigger_fop.h:47
Definition: rm.h:1675
uint64_t rt_id
Definition: rm.h:403
static void rings_credit_init(struct m0_rm_resource *resource, struct m0_rm_credit *credit)
Definition: rings.c:72
M0_INTERNAL void m0_rm_resource_del(struct m0_rm_resource *res)
Definition: rm.c:361
void rings_resource_free(struct m0_rm_resource *resource)
Definition: rings.c:79
int(* rop_credit_decode)(struct m0_rm_resource *resource, struct m0_rm_credit *credit, struct m0_bufvec_cursor *cur)
Definition: rm.h:340