Motr  M0
ufid.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
24 #include "lib/trace.h" /* M0_LOG */
25 
26 #include "ut/ut.h" /* M0_UT_ASSERT */
27 #include "lib/finject.h"
28 #include "lib/tlist.h"
29 #include "lib/hash.h"
30 #include "lib/memory.h"
31 
32 #include "motr/client.h"
33 #include "motr/client_internal.h"
34 
35 #include "helpers/ufid.h"
36 #include "helpers/ufid.c"
37 
38 
40 static struct m0_client dummy_m0c;
42 
43 enum {
49 };
50 
51 #define EXPECT_EQ(a, b) M0_UT_ASSERT(a == b)
52 #define EXPECT_NE(a, b) M0_UT_ASSERT(a != b)
53 
54 #define UFID_RESERVED_TEST (60818UL)
55 #define UFID_RESERVED_TEST_HI \
56  (UFID_RESERVED_TEST << (64 - M0_UFID_RESERVED_BITS))
57 
58 static void id128_to_ufid(struct m0_uint128 *id128,
59  struct m0_ufid *ufid)
60 {
61  uint64_t genid_hi;
62  uint64_t genid_lo;
63  uint64_t salt;
64  uint64_t proc_id;
65  uint64_t seq_id;
66  uint64_t id_lo;
67  uint64_t id_hi;
68  uint64_t reserved;
69 
70  id_hi = id128->u_hi;
71  id_lo = id128->u_lo;
72 
73  seq_id = id_lo & M0_UFID_SEQID_MASK;
74  id_lo >>= M0_UFID_SEQID_BITS;
75  proc_id = id_lo & M0_UFID_PROCID_MASK;
76  id_lo >>= M0_UFID_PROCID_BITS;
77  genid_lo = id_lo & M0_UFID_GENID_LO_MASK;
78 
79  genid_hi = id_hi & M0_UFID_GENID_HI_MASK;
80  id_hi >>= M0_UFID_GENID_HI_BITS;
81  salt = id_hi & M0_UFID_SALT_MASK;
82  id_hi >>= M0_UFID_SALT_BITS;
83  reserved = id_hi & M0_UFID_RESERVED_MASK;
84 
85  ufid->uf_seq_id = seq_id;
86  ufid->uf_proc_id = proc_id;
87  ufid->uf_gen_id = (genid_hi << M0_UFID_GENID_HI_BITS) | genid_lo;
88  ufid->uf_salt = salt;
89  ufid->uf_reserved = reserved;
90 }
91 
92 static int ufid_validate(struct m0_uint128 *id128)
93 {
94  struct m0_ufid ufid;
95  struct m0_ufid current_ufid;
96 
97  id128_to_ufid(id128, &ufid);
98  current_ufid = dummy_ufid_gr.ufg_ufid_cur;
99 
100  /* gen ID should always be increasing */
101  if (ufid.uf_gen_id == 0 || ufid.uf_gen_id < current_ufid.uf_gen_id)
102  return UFID_ERR_GEN_ID;
103 
104  /* seq ID should increase for same gen ID */
105  if (ufid.uf_gen_id == current_ufid.uf_gen_id &&
106  ufid.uf_seq_id <= current_ufid.uf_seq_id)
107  return UFID_ERR_SEQ_ID;
108 
109  /* Salt ID should remain same for the process */
110  if (current_ufid.uf_salt != 0 && ufid.uf_salt != current_ufid.uf_salt)
111  return UFID_ERR_SALT;
112 
113  /* Process Id should remain constant till the process dies */
114  if (current_ufid.uf_proc_id != 0 &&
115  ufid.uf_proc_id != current_ufid.uf_proc_id)
116  return UFID_ERR_PROC_ID;
117 
118  /* Motr bits should not be altered */
119  if (ufid.uf_reserved != 0 && ufid.uf_reserved != UFID_RESERVED_TEST)
120  return UFID_ERR_RESERVED;
121 
122  return 0;
123 }
124 #define UFID_VALIDATE(id) EXPECT_EQ(ufid_validate(id), 0)
125 
126 struct ut_ufid {
127  uint64_t u_magic;
128  struct m0_hlink u_link;
129 
131 };
132 
133 static uint64_t ufid_hash(const struct m0_htable *htable,
134  const struct m0_uint128 *id128)
135 {
136  const uint64_t seq_id = id128->u_lo & M0_UFID_SEQID_MASK;
137  return seq_id % htable->h_bucket_nr;
138 }
139 
140 static int ufid_hash_eq(const struct m0_uint128 *id1,
141  const struct m0_uint128 *id2)
142 {
143  return m0_uint128_eq(id1, id2);
144 }
145 
146 M0_HT_DESCR_DEFINE(ufid, "Hash of UFIDs",
147  static, struct ut_ufid,
148  u_link, u_magic, 0x43, 0x67, u_id128,
150 M0_HT_DEFINE(ufid, static, struct ut_ufid, struct m0_uint128);
151 static struct m0_htable ufid_tracker;
152 
153 static void ut_ufid_seq_id_refresh(void)
154 {
155  int i;
156  int nr_tests;
157  struct ut_ufid *new_ufid;
158  struct ut_ufid *found_ufid;
159  struct ut_ufid *ufid;
160  struct m0_ufid_generator *gr = &dummy_ufid_gr;
161 
162  ufid_htable_init(&ufid_tracker, 1024);
163 
164 #ifdef M0_ASSERT_EX_ON
165  /*
166  * Hash table invariant checks take too long if they are on. Reduce
167  * the number of tests for sequence id overflow test.
168  */
169  nr_tests = 10 * 1024;
171 #else
172  nr_tests = M0_UFID_SEQID_MAX + 1024;
173 #endif
174  for (i = 0; i < nr_tests; i++) {
175  ufid_seq_id_refresh(gr, 1);
176 
177  M0_ALLOC_PTR(new_ufid);
178  M0_UT_ASSERT(new_ufid != NULL);
179  ufid_to_id128(&gr->ufg_ufid_cur, &new_ufid->u_id128);
180 
181  found_ufid = m0_htable_lookup(&ufid_tracker,
182  &new_ufid->u_id128);
183  M0_UT_ASSERT(found_ufid == NULL);
184  m0_tlink_init(&ufid_tl, new_ufid);
185  ufid_htable_add(&ufid_tracker, new_ufid);
186  }
187 
188  m0_htable_for(ufid, ufid, &ufid_tracker) {
189  m0_htable_del(&ufid_tracker, ufid);
190  m0_free(ufid);
191  }
193 
194  ufid_htable_fini(&ufid_tracker);
195 }
196 
197 static void ut_ufid_salt_refresh(void)
198 {
199  int i;
200  int nr_tests = 100;
201  uint32_t prev_salt;
202  uint32_t curr_salt;
203  struct m0_ufid_generator *gr = &dummy_ufid_gr;
204 
205  ufid_salt_refresh(gr);
206  prev_salt = gr->ufg_ufid_cur.uf_salt;
207  for (i = 0; i < nr_tests; i++) {
208  ufid_salt_refresh(gr);
209  curr_salt = gr->ufg_ufid_cur.uf_salt;
210  EXPECT_NE(curr_salt, prev_salt);
211  prev_salt = curr_salt;
212  }
213 }
214 
215 static void ut_ufid_proc_id_refresh(void)
216 {
217  struct m0_ufid_generator *gr = &dummy_ufid_gr;
218 
219  /* Basic case. */
221 
222  /* Process ID warn bit set should return warning. */
223  m0_fi_enable_once("ufid_proc_id_refresh", "proc_id_warn");
225 
226  /* Process ID overflow detection. */
227  m0_fi_enable_once("ufid_proc_id_refresh", "proc_id_overflow");
228  EXPECT_EQ(ufid_proc_id_refresh(gr), -EOVERFLOW);
229 }
230 
232 {
233  struct m0_ufid_generator *gr = &dummy_ufid_gr;
234 
235  /* Basic case. */
237 
238  /* Refresh should fail after retry is exhausted. */
239  m0_fi_enable_once("ufid_generation_id_refresh",
240  "retries_exhausted");
242 
243  /* Refresh should fail if clock is set earlier than base time. */
244  m0_fi_enable_once("ufid_generation_id_refresh",
245  "clock_lt_base_ts");
247 
248  /* Refresh should fail for large clock skew */
249  m0_fi_enable_once("ufid_generation_id_refresh",
250  "clock_skew");
252 }
253 
254 static void ut_m0_ufid_next(void)
255 {
256  struct m0_uint128 id128;
257  struct m0_ufid_generator *gr = &dummy_ufid_gr;
258 
259  M0_SET0(&id128);
260 
261  /* Base cases*/
262  EXPECT_EQ(m0_ufid_next(gr, 1, &id128), 0);
263  UFID_VALIDATE(&id128);
264 
265  /* Call again */
266  EXPECT_EQ(m0_ufid_next(gr, 1, &id128), 0);
267  UFID_VALIDATE(&id128);
268 
269  /* Get range */
270  EXPECT_EQ(m0_ufid_next(gr, 100, &id128), 0);
271  UFID_VALIDATE(&id128);
272 
273  EXPECT_EQ(m0_ufid_next(gr, M0_UFID_SEQID_MAX, &id128), 0);
274  UFID_VALIDATE(&id128);
275 
276  /* num_seq is 0 */
277  EXPECT_EQ(m0_ufid_next(gr, 0, &id128), -EINVAL);
278 
279  /* Greater than 2^20 */
280  EXPECT_EQ(m0_ufid_next(gr, M0_UFID_SEQID_MAX + 1, &id128), -EINVAL);
281 
282  /* id is higer than 91 bits set */
283  id128 = M0_UINT128(UFID_RESERVED_TEST_HI, 0);
284  EXPECT_EQ(m0_ufid_next(gr, 1, &id128), 0);
285  UFID_VALIDATE(&id128);
286 }
287 
288 static void ut_m0_ufid_new(void)
289 {
290  struct m0_uint128 id128;
291  struct m0_ufid_generator *gr = &dummy_ufid_gr;
292  struct m0_ufid ufid;
293 
294  M0_SET0(&id128);
295 
296  /* Basic test */
297  EXPECT_EQ(m0_ufid_new(gr, 1, 0, &id128), 0);
298  UFID_VALIDATE(&id128);
299  EXPECT_EQ(m0_ufid_new(gr, 100, 100, &id128), 0);
300  UFID_VALIDATE(&id128);
301 
302  /* Greater than 2^20 */
303  EXPECT_EQ(m0_ufid_new(gr, 1, M0_UFID_SEQID_MAX, &id128), 0);
304  UFID_VALIDATE(&id128);
305 
306  /* Negative Cases. */
307  /* Requested no. of FIDs should be between 1 and UFID_SEQID_MAX */
308  EXPECT_EQ(m0_ufid_new(gr, 0, 100, &id128), -EINVAL);
309  EXPECT_EQ(m0_ufid_new(gr, M0_UFID_SEQID_MAX + 1, 100, &id128),
310  -EINVAL);
311 
312  /* Check rollover. After rollover sequence ID should be 0 */
313  EXPECT_EQ(m0_ufid_new(gr, 1, M0_UFID_SEQID_MAX, &id128), 0);
314  id128_to_ufid(&id128, &ufid);
315  EXPECT_EQ(ufid.uf_seq_id, 0);
316 }
317 
318 M0_INTERNAL int ut_ufid_init(void)
319 {
320  dummy_m0c.m0c_process_fid.f_container = 0x7200000000000000;
323 
324  return 0;
325 }
326 
327 M0_INTERNAL int ut_ufid_fini(void)
328 {
330  return 0;
331 }
332 
333 struct m0_ut_suite ut_suite_ufid = {
334  .ts_name = "helpers-ufid-ut",
335  .ts_init = ut_ufid_init,
336  .ts_fini = ut_ufid_fini,
337  .ts_tests = {
338  { "m0_ufid_new",
339  &ut_m0_ufid_new},
340  { "m0_ufid_next",
341  &ut_m0_ufid_next},
342  { "ufid_generation_id_refresh",
344  { "ufid_proc_id_refresh",
346  { "ufid_salt_refresh",
348  { "ufid_seq_id_refresh",
350  { NULL, NULL },
351  }
352 };
353 
354 #undef M0_TRACE_SUBSYSTEM
355 
356 /*
357  * Local variables:
358  * c-indentation-style: "K&R"
359  * c-basic-offset: 8
360  * tab-width: 8
361  * fill-column: 80
362  * scroll-step: 1
363  * End:
364  */
#define EXPECT_EQ(a, b)
Definition: ufid.c:51
M0_INTERNAL int ut_ufid_init(void)
Definition: ufid.c:318
#define m0_htable_for(name, var, htable)
Definition: hash.h:483
M0_INTERNAL void * m0_htable_lookup(const struct m0_htable *htable, const void *key)
Definition: hash.c:162
#define NULL
Definition: misc.h:38
static void ufid_salt_refresh(struct m0_ufid_generator *gr)
Definition: ufid.c:45
uint32_t uf_seq_id
Definition: ufid.h:189
static struct m0_ufid_generator dummy_ufid_gr
Definition: ufid.c:41
M0_INTERNAL bool m0_uint128_eq(const struct m0_uint128 *u0, const struct m0_uint128 *u1)
Definition: misc.c:39
int m0_ufid_init(struct m0_client *m0c, struct m0_ufid_generator *gr)
Definition: ufid.c:248
#define M0_UFID_RESERVED_MASK
Definition: ufid.h:177
M0_INTERNAL int ut_ufid_fini(void)
Definition: ufid.c:327
#define M0_SET0(obj)
Definition: misc.h:64
Definition: ut.h:77
static void ut_ufid_seq_id_refresh(void)
Definition: ufid.c:153
void m0_ufid_fini(struct m0_ufid_generator *gr)
Definition: ufid.c:283
#define UFID_VALIDATE(id)
Definition: ufid.c:124
#define EXPECT_NE(a, b)
Definition: ufid.c:52
#define M0_UFID_GENID_HI_MASK
Definition: ufid.h:172
int i
Definition: dir.c:1033
static struct m0_client dummy_m0c
Definition: ufid.c:40
static int ufid_validate(struct m0_uint128 *id128)
Definition: ufid.c:92
struct m0_ufid ufg_ufid_cur
Definition: ufid.h:208
Definition: ufid.h:184
#define M0_UFID_GENID_LO_MASK
Definition: ufid.h:173
static void ut_ufid_salt_refresh(void)
Definition: ufid.c:197
struct m0_hlink u_link
Definition: ufid.c:128
static void id128_to_ufid(struct m0_uint128 *id128, struct m0_ufid *ufid)
Definition: ufid.c:58
M0_HT_DESCR_DEFINE(ufid, "Hash of UFIDs", static, struct ut_ufid, u_link, u_magic, 0x43, 0x67, u_id128, ufid_hash, ufid_hash_eq)
uint64_t u_hi
Definition: types.h:36
static void ut_ufid_generation_id_refresh(void)
Definition: ufid.c:231
static void ut_ufid_proc_id_refresh(void)
Definition: ufid.c:215
uint64_t f_container
Definition: fid.h:39
int m0_ufid_next(struct m0_ufid_generator *gr, uint32_t nr_ids, struct m0_uint128 *id128)
Definition: ufid.c:338
static struct m0_htable ufid_tracker
Definition: ufid.c:151
uint32_t uf_salt
Definition: ufid.h:186
#define UFID_RESERVED_TEST_HI
Definition: ufid.c:55
#define UFID_RESERVED_TEST
Definition: ufid.c:54
#define M0_UFID_SEQID_MASK
Definition: ufid.h:175
M0_INTERNAL void m0_tlink_init(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:63
#define M0_UFID_SALT_MASK
Definition: ufid.h:174
uint64_t uf_reserved
Definition: ufid.h:185
static void ut_m0_ufid_new(void)
Definition: ufid.c:288
struct m0_fid m0c_process_fid
static int ufid_hash_eq(const struct m0_uint128 *id1, const struct m0_uint128 *id2)
Definition: ufid.c:140
const char * ts_name
Definition: ut.h:99
static void ufid_to_id128(struct m0_ufid *ufid, struct m0_uint128 *id128)
Definition: ufid.c:209
uint64_t f_key
Definition: fid.h:40
Definition: ufid.c:126
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_HT_DEFINE(ufid, static, struct ut_ufid, struct m0_uint128)
uint32_t uf_proc_id
Definition: ufid.h:188
#define M0_UFID_SEQID_MAX
Definition: ufid.h:181
M0_INTERNAL void m0_htable_del(struct m0_htable *htable, void *amb)
Definition: hash.c:150
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
#define M0_UFID_PROCID_MASK
Definition: ufid.h:176
#define M0_UINT128(hi, lo)
Definition: types.h:40
static void ut_m0_ufid_next(void)
Definition: ufid.c:254
int m0_ufid_new(struct m0_ufid_generator *gr, uint32_t nr_ids, uint32_t nr_skip_ids, struct m0_uint128 *id128)
Definition: ufid.c:298
static int ufid_generation_id_refresh(struct m0_ufid_generator *gr)
Definition: ufid.c:60
static uint64_t ufid_hash(const struct m0_htable *htable, const struct m0_uint128 *id128)
Definition: ufid.c:133
uint64_t u_magic
Definition: ufid.c:127
uint64_t u_lo
Definition: types.h:37
static int ufid_proc_id_refresh(struct m0_ufid_generator *gr)
Definition: ufid.c:124
void m0_free(void *data)
Definition: memory.c:146
#define m0_htable_endfor
Definition: hash.h:491
struct m0_uint128 u_id128
Definition: ufid.c:130
uint64_t h_bucket_nr
Definition: hash.h:178
#define M0_UT_ASSERT(a)
Definition: ut.h:46
uint32_t uf_gen_id
Definition: ufid.h:187
struct m0_ut_suite ut_suite_ufid
Definition: ufid.c:39
static int ufid_seq_id_refresh(struct m0_ufid_generator *gr, uint32_t nr_seqs)
Definition: ufid.c:178