Motr  M0
m0layout.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 <stdio.h> /* printf */
24 #include <stdlib.h> /* atoi */
25 #include <math.h> /* sqrt */
26 
27 #include "lib/misc.h" /* M0_SET0 */
28 #include "lib/memory.h"
29 #include "lib/assert.h"
30 #include "lib/arith.h"
31 #include "lib/errno.h" /* ENOMEM */
32 #include "motr/init.h"
33 #include "module/instance.h"
34 
35 #include "pool/pool.h"
36 #include "ioservice/fid_convert.h" /* m0_fid_gob_make() */
37 #include "layout/layout.h"
38 #include "layout/pdclust.h"
39 #include "layout/linear_enum.h" /* m0_linear_enum_build() */
40 
46 /*
47  * Creates dummy domain, registers pdclust layout type and linear
48  * enum type and creates dummy enum object.
49  * These objects are called as dummy since they are not used by this layout
50  * demo test.
51  */
53  uint64_t lid,
54  struct m0_pdclust_attr *attr,
55  struct m0_pdclust_layout **pl)
56 {
57  int rc;
58  struct m0_layout_linear_attr lin_attr;
59  struct m0_layout_linear_enum *lin_enum;
60 
62  M0_ASSERT(rc == 0);
63 
65  M0_ASSERT(rc == 0);
66 
67  lin_attr.lla_nr = attr->pa_P;
68  lin_attr.lla_A = 100;
69  lin_attr.lla_B = 200;
70  rc = m0_linear_enum_build(domain, &lin_attr, &lin_enum);
71  M0_ASSERT(rc == 0);
72 
73  rc = m0_pdclust_build(domain, lid, attr, &lin_enum->lle_base, pl);
74  M0_ASSERT(rc == 0);
75  return rc;
76 }
77 
79  int unit)
80 {
81  if (unit < play->pl_attr.pa_N)
82  return M0_PUT_DATA;
83  else if (unit < play->pl_attr.pa_N + play->pl_attr.pa_K)
84  return M0_PUT_PARITY;
85  else
86  return M0_PUT_SPARE;
87 }
88 
94  struct m0_pdclust_layout *pl,
95  int R, int I, bool print)
96 {
97  uint64_t group;
98  uint32_t unit;
99  uint32_t N;
100  uint32_t K;
101  uint32_t S;
102  uint32_t P;
103  uint32_t W;
104  int i;
105  struct m0_pdclust_src_addr src;
106  struct m0_pdclust_tgt_addr tgt;
107  struct m0_pdclust_src_addr src1;
108  struct m0_pdclust_attr attr = pl->pl_attr;
109  struct m0_pdclust_src_addr map[R][attr.pa_P];
110  uint32_t incidence[attr.pa_P][attr.pa_P];
111  uint32_t usage[attr.pa_P][M0_PUT_NR + 1];
112  uint32_t where[attr.pa_N + attr.pa_K + attr.pa_S];
113 
114 #ifndef __KERNEL__
115  uint64_t frame;
116  uint32_t obj;
117  const char *brace[M0_PUT_NR] = { "[]", "<>", "{}" };
118  const char *head[M0_PUT_NR+1] = { "D", "P", "S",
119  "total" };
120  uint32_t min;
121  uint32_t max;
122  uint64_t sum;
123  uint32_t u;
124  double sq;
125  double avg;
126 #endif
127 
129  M0_SET_ARR0(incidence);
130 
131  N = attr.pa_N;
132  K = attr.pa_K;
133  P = attr.pa_P;
134  S = attr.pa_S;
135  W = N + K + S;
136 
137 #ifndef __KERNEL__
138  if (print) {
139  printf("layout: N: %"PRIu32" K: %"PRIu32" P: %"PRIu32" "
140  "C: %"PRIu32" L: %"PRIu32"\n",
141  N, K, P, pl->pl_C, pl->pl_L);
142  }
143 #endif
144 
145  for (group = 0; group < I ; ++group) {
146  src.sa_group = group;
147  for (unit = 0; unit < W; ++unit) {
148  src.sa_unit = unit;
150  m0_pdclust_instance_inv(pi, &tgt, &src1);
151  M0_ASSERT(memcmp(&src, &src1, sizeof src) == 0);
152  if (tgt.ta_frame < R)
154  where[unit] = tgt.ta_obj;
156  usage[tgt.ta_obj][classify(pl, unit)]++;
157  }
158  for (unit = 0; unit < W; ++unit) {
159  for (i = 0; i < W; ++i)
160  incidence[where[unit]][where[i]]++;
161  }
162  }
163  if (!print)
164  return;
165 
166 #ifndef __KERNEL__
167  printf("map: \n");
168  for (frame = 0; frame < R; ++frame) {
169  printf("%5" PRIu64 " : ", frame);
170  for (obj = 0; obj < P; ++obj) {
171  int d;
172 
173  d = classify(pl, map[frame][obj].sa_unit);
174  printf("%c%2" PRIu64 ", %2" PRIu64 "%c ",
175  brace[d][0],
176  map[frame][obj].sa_group,
177  map[frame][obj].sa_unit,
178  brace[d][1]);
179  }
180  printf("\n");
181  }
182  printf("usage : \n");
183  for (i = 0; i < M0_PUT_NR + 1; ++i) {
184  max = sum = sq = 0;
185  min = ~0;
186  printf("%5s : ", head[i]);
187  for (obj = 0; obj < P; ++obj) {
188  u = usage[obj][i];
189  printf("%7"PRIu32" ", u);
190  min = min32u(min, u);
191  max = max32u(max, u);
192  sum += u;
193  sq += u*u;
194  }
195  avg = ((double)sum)/P;
196  printf(" | %7"PRIu32" %7"PRIu32" %7lf %7.2f%%\n", min, max, avg,
197  sqrt(sq/P - avg*avg)*100.0/avg);
198  }
199  printf("\nincidence:\n");
200  for (obj = 0; obj < P; ++obj) {
201  max = sum = sq = 0;
202  min = ~0;
203  for (i = 0; i < P; ++i) {
204  if (obj != i) {
205  u = incidence[obj][i];
206  min = min32u(min, u);
207  max = max32u(max, u);
208  sum += u;
209  sq += u*u;
210  printf("%5"PRIu32" ", u);
211  } else
212  printf(" * ");
213  }
214  avg = ((double)sum)/(P - 1);
215  printf(" | %5"PRIu32" %5"PRIu32" %5lf %5.2f%%\n", min, max, avg,
216  sqrt(sq/(P - 1) - avg*avg)*100.0/avg);
217  }
218 #endif
219 }
220 
221 int main(int argc, char **argv)
222 {
223  uint32_t N;
224  uint32_t K;
225  uint32_t P;
226  uint32_t S;
227  int R;
228  int I;
229  int rc;
230  uint32_t cache_nr;
231  uint64_t *cache_len;
232  uint64_t unitsize = 4096;
233  struct m0_pool_version pool_ver;
234  struct m0_layout *l;
235  struct m0_pdclust_layout *play;
236  struct m0_pdclust_attr attr;
237  struct m0_pool pool;
238  uint64_t id;
239  struct m0_uint128 seed;
240  struct m0_layout_domain domain;
241  struct m0_pdclust_instance *pi;
242  struct m0_fid gfid;
243  struct m0_layout_instance *li;
244  static struct m0 instance;
245  if (argc != 7 && argc != 9) {
246  printf(
247 "\t\tm0layout N K S P R I\nwhere\n"
248 "\tN : number of data units in a parity group\n"
249 "\tK : number of parity units in a parity group\n"
250 "\tS : number of spare uints in a parity group\n"
251 "\tP : number of target objects to stripe over\n"
252 "\tR : number of frames to show in a layout map\n"
253 "\tI : number of groups to iterate over while\n"
254 "\t calculating incidence and frame distributions\n"
255 "\tf_c: container-id for gfid\n"
256 "\tf_k: key for gfid\n"
257 "\noutput:\n"
258 "\tmap: an R*P map showing initial fragment of layout\n"
259 "\t [G, U] - data unit U from a group G\n"
260 "\t <G, U> - parity unit U from a group G\n"
261 "\t {G, U} - spare unit U from a group G\n"
262 "\tusage: counts of data, parity, spare and total frames\n"
263 "\t occupied on each target object, followed by MIN,\n"
264 "\t MAX, AVG, STD/AVG\n"
265 "\tincidence: a matrix showing a number of parity groups having\n"
266 "\t units on a given pair of target objects, followed by\n"
267 "\t MIN, MAX, AVG, STD/AVG\n");
268  return 1;
269  }
270  N = atoi(argv[1]);
271  K = atoi(argv[2]);
272  S = atoi(argv[3]);
273  P = atoi(argv[4]);
274  R = atoi(argv[5]);
275  I = atoi(argv[6]);
276 
277  id = 0x4A494E4E49455349; /* "jinniesi" */
279 
280  rc = m0_init(&instance);
281  if (rc != 0)
282  return rc;
283 
284  rc = m0_pool_init(&pool, &M0_FID_INIT(0, id), 0);
285  if (rc == 0) {
286  attr.pa_N = N;
287  attr.pa_K = K;
288  attr.pa_S = S;
289  attr.pa_P = P;
290  attr.pa_unit_size = unitsize;
291  attr.pa_seed = seed;
292 
293  rc = dummy_create(&domain, id, &attr, &play);
294  if (rc == 0) {
295  if (argc != 8)
296  m0_fid_gob_make(&gfid, 0, 999);
297  else
299  strtol(argv[7], NULL, 0),
300  strtol(argv[8], NULL, 0));
301  /*TODO: Currently in this utility we assume that no
302  * tolerance is supported for levels higher than disks.
303  * Hence only single cache is sufficient. In future we
304  * need to read configuration string.
305  */
306  cache_nr = 1;
308  M0_ALLOC_ARR(cache_len, cache_nr);
309  if (cache_len == NULL) {
310  rc = -ENOMEM;
311  goto out;
312  }
314  cache_len[0] = P;
315  l = m0_pdl_to_layout(play);
316  l->l_pver = &pool_ver;
317  rc = m0_layout_instance_build(l, &gfid, &li);
319  if (rc == 0) {
320  layout_demo(pi, play, R, I, true);
322  }
323 out:
327  }
328  m0_pool_fini(&pool);
329  }
330 
331  m0_fini();
332  return rc;
333 }
334 
337 /*
338  * Local variables:
339  * c-indentation-style: "K&R"
340  * c-basic-offset: 8
341  * tab-width: 8
342  * fill-column: 80
343  * scroll-step: 1
344  * End:
345  */
uint64_t id
Definition: cob.h:2380
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
M0_INTERNAL void m0_pool_fini(struct m0_pool *pool)
Definition: pool.c:322
M0_INTERNAL void m0_fid_gob_make(struct m0_fid *gob_fid, uint32_t container, uint64_t key)
Definition: fid_convert.c:46
uint64_t sa_group
Definition: pdclust.h:241
#define NULL
Definition: misc.h:38
map
Definition: processor.c:112
void m0_fini(void)
Definition: init.c:318
Definition: storage.c:103
M0_INTERNAL int m0_layout_domain_init(struct m0_layout_domain *dom)
Definition: layout.c:610
union @126 u
#define M0_FID_INIT(container, key)
Definition: fid.h:84
struct m0_layout_instance pi_base
Definition: pdclust.h:173
M0_INTERNAL void m0_uint128_init(struct m0_uint128 *u128, const char *magic)
Definition: misc.c:150
uint32_t pa_K
Definition: pdclust.h:107
M0_INTERNAL void m0_layout_domain_fini(struct m0_layout_domain *dom)
Definition: layout.c:633
struct m0_pool_version pool_ver
Definition: fd.c:111
M0_INTERNAL int m0_linear_enum_build(struct m0_layout_domain *dom, const struct m0_layout_linear_attr *attr, struct m0_layout_linear_enum **out)
Definition: linear_enum.c:138
uint64_t ta_obj
Definition: pdclust.h:256
static int sum
Definition: rwlock.c:53
int m0_init(struct m0 *instance)
Definition: init.c:310
#define N(i)
struct m0_pdclust_attr pl_attr
Definition: pdclust.h:150
uint32_t pl_C
Definition: pdclust.h:155
static struct foo * obj
Definition: tlist.c:302
M0_INTERNAL int m0_layout_instance_build(struct m0_layout *l, const struct m0_fid *fid, struct m0_layout_instance **out)
Definition: layout.c:1113
M0_INTERNAL int m0_pool_init(struct m0_pool *pool, const struct m0_fid *id, enum m0_pver_policy_code pver_policy)
Definition: pool.c:307
static int head(struct m0_sm *mach)
Definition: sm.c:468
void layout_demo(struct m0_pdclust_instance *pi, struct m0_pdclust_layout *pl, int R, int I, bool print)
Definition: m0layout.c:93
int i
Definition: dir.c:1033
m0_pdclust_unit_type
Definition: pdclust.h:89
#define PRIu64
Definition: types.h:58
static M0_UNUSED void print(struct m0_be_list *list)
Definition: list.c:186
#define M0_SET_ARR0(arr)
Definition: misc.h:72
struct m0_layout_enum lle_base
Definition: linear_enum.h:69
static void attr(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:949
struct m0_fd_tree pv_fd_tree
Definition: pool.h:139
#define M0_ASSERT(cond)
#define M0_PDCLUST_SEED
Definition: pdclust.h:76
uint64_t ta_frame
Definition: pdclust.h:254
struct m0_fd_cache_info ft_cache_info
Definition: fd.h:209
int main(int argc, char **argv)
Definition: m0layout.c:221
static long long max(long long a, long long b)
Definition: crate.c:196
Definition: instance.h:80
struct m0_pdclust_instance pi
Definition: fd.c:107
uint64_t fci_nr
Definition: fd.h:188
static int dummy_create(struct m0_layout_domain *domain, uint64_t lid, struct m0_pdclust_attr *attr, struct m0_pdclust_layout **pl)
Definition: m0layout.c:52
static void group(void)
Definition: sm.c:386
M0_INTERNAL void m0_pdclust_instance_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_src_addr *src, struct m0_pdclust_tgt_addr *tgt)
Definition: pdclust.c:701
M0_INTERNAL int m0_layout_standard_types_register(struct m0_layout_domain *dom)
Definition: layout.c:671
M0_INTERNAL void m0_pdclust_instance_inv(struct m0_pdclust_instance *pi, const struct m0_pdclust_tgt_addr *tgt, struct m0_pdclust_src_addr *src)
Definition: pdclust.c:746
static struct m0_clink l[NR]
Definition: chan.c:37
uint32_t pl_L
Definition: pdclust.h:160
static struct m0_pool pool
Definition: iter_ut.c:58
M0_INTERNAL struct m0_layout * m0_pdl_to_layout(struct m0_pdclust_layout *pl)
Definition: pdclust.c:393
uint64_t sa_unit
Definition: pdclust.h:243
#define PRIu32
Definition: types.h:66
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
static long long min(long long a, long long b)
Definition: crate.c:191
static uint32_t min32u(uint32_t a, uint32_t b)
Definition: arith.h:56
const struct m0_layout_instance_ops * li_ops
Definition: layout.h:593
Definition: fid.h:38
Definition: module.c:67
static uint32_t max32u(uint32_t a, uint32_t b)
Definition: arith.h:61
void(* lio_fini)(struct m0_layout_instance *li)
Definition: layout.h:607
M0_INTERNAL int m0_pdclust_build(struct m0_layout_domain *dom, uint64_t lid, const struct m0_pdclust_attr *attr, struct m0_layout_enum *le, struct m0_pdclust_layout **out)
Definition: pdclust.c:305
M0_INTERNAL void m0_layout_standard_types_unregister(struct m0_layout_domain *dom)
Definition: layout.c:697
static struct m0 instance
Definition: main.c:78
uint64_t * fci_info
Definition: fd.h:196
Definition: rwlock.c:42
Definition: pool.h:80
Definition: finject.c:60
M0_INTERNAL struct m0_pdclust_instance * m0_layout_instance_to_pdi(const struct m0_layout_instance *li)
Definition: pdclust.c:400
M0_INTERNAL void m0_layout_put(struct m0_layout *l)
Definition: layout.c:893
#define out(...)
Definition: gen.c:41
struct m0_fid gfid
Definition: dir.c:626
static struct m0_layout_domain domain
Definition: layout.c:49
static void usage(void)
Definition: console.c:155
struct m0_pdclust_src_addr src
Definition: fd.c:108
int32_t rc
Definition: trigger_fop.h:47
enum m0_pdclust_unit_type classify(const struct m0_pdclust_layout *play, int unit)
Definition: m0layout.c:78