Motr  M0
rm_rwlock.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 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_UT
24 #include "lib/trace.h"
25 
26 #include "lib/types.h"
27 #include "lib/chan.h"
28 #include "lib/misc.h"
29 #include "lib/memory.h"
30 #include "lib/time.h"
31 #include "lib/vec.h"
32 #include "fop/fom_generic.h"
33 #include "fid/fid.h"
34 #include "ut/ut.h"
35 
36 #include "rm/rm.h"
37 #include "rm/rm_internal.h"
38 #include "rm/rm_rwlock.h" /* m0_rw_lockable */
39 #include "rm/ut/rmut.h"
40 
41 #define OWNER(srv_id) rm_ctxs[srv_id].rc_test_data.rd_owner
42 #define INREQ(srv_id) (&rm_ctxs[srv_id].rc_test_data.rd_in)
43 
45 
47 static struct m0_semaphore conflict_sem;
48 static struct m0_semaphore waiting_sem;
49 
50 static void rwlockable_rtype_set(struct rm_ut_data *self)
51 {
52  struct m0_rm_resource_type *rt;
53  int rc;
54 
56  M0_UT_ASSERT(rt != NULL);
57  rt->rt_id = M0_RM_RWLOCKABLE_RT;
58  rt->rt_ops = &rwlockable_type_ops;
59  rc = m0_rm_type_register(&self->rd_dom, rt);
60  M0_UT_ASSERT(rc == 0);
61  self->rd_rt = rt;
62 }
63 
64 static void rwlockable_rtype_unset(struct rm_ut_data *self)
65 {
66  m0_rm_type_deregister(self->rd_rt);
67  m0_free0(&self->rd_rt);
68 }
69 
70 static void rwlockable_res_set(struct rm_ut_data *self)
71 {
72  struct m0_rw_lockable *lockable;
73 
74  M0_ALLOC_PTR(lockable);
75  M0_UT_ASSERT(lockable != NULL);
76  m0_fid_set(&self->rd_fid, 1, 0);
77  m0_rw_lockable_init(lockable, &self->rd_fid, &self->rd_dom);
78  self->rd_res = &lockable->rwl_resource;
79 }
80 
81 static void rwlockable_res_unset(struct rm_ut_data *self)
82 {
83  struct m0_rw_lockable *lockable;
84 
85  lockable = container_of(self->rd_res, struct m0_rw_lockable,
86  rwl_resource);
87  m0_rw_lockable_fini(lockable);
88  m0_free(lockable);
89  self->rd_res = NULL;
90 }
91 
92 static void rwlock_owner_set(struct rm_ut_data *self)
93 {
94  struct m0_rm_owner *owner;
95  struct m0_rw_lockable *lockable;
97  (uint64_t)self);
98 
99  M0_ALLOC_PTR(owner);
100  M0_UT_ASSERT(owner != NULL);
101  lockable = container_of(self->rd_res, struct m0_rw_lockable,
102  rwl_resource);
103  m0_rm_rwlock_owner_init(owner, &fid, lockable, NULL);
104  self->rd_owner = owner;
105 }
106 
107 static void rwlock_owner_unset(struct rm_ut_data *self)
108 {
109  M0_UT_ASSERT(owner_state(self->rd_owner) == ROS_FINAL);
110  m0_rm_rwlock_owner_fini(self->rd_owner);
111  m0_free0(&self->rd_owner);
112 }
113 
114 const static struct rm_ut_data_ops rwlock_ut_data_ops = {
116  .rtype_unset = rwlockable_rtype_unset,
117  .resource_set = rwlockable_res_set,
118  .resource_unset = rwlockable_res_unset,
119  .owner_set = rwlock_owner_set,
120  .owner_unset = rwlock_owner_unset,
121  .credit_datum_set = NULL
122 };
123 
124 static void rwlock_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
125 {
126  /* Do nothing */
127  return;
128 }
129 
131 {
133 }
134 
137  .rio_conflict = rwlock_incoming_conflict
138 };
139 
140 static void rwlock_build_hierarchy(void)
141 {
147 
151 
155 
159 }
160 
161 static void rwlock_utinit(void)
162 {
163  uint32_t i;
164 
166 
167  for (i = 0; i < test_servers_nr; ++i)
168  rm_ctx_init(&rm_ctxs[i], i);
169 
172  for (i = 0; i < test_servers_nr; ++i) {
175  }
176 
180 }
181 
182 static void rwlock_servers_windup(void)
183 {
184  int i;
185 
186  for (i = 0; i < test_servers_nr; ++i)
188 }
189 
190 static void rwlock_servers_disc_fini(void)
191 {
192  int i;
193 
194  /* Disconnect the servers */
195  for (i = 0; i < test_servers_nr; ++i)
198  /* Finalise the servers */
199  for (i = 0; i < test_servers_nr; ++i)
200  rm_ctx_fini(&rm_ctxs[i]);
201 }
202 
203 static void rwlock_utfini(void)
204 {
207 }
208 
210  struct m0_rm_incoming *in,
212  enum m0_rm_rwlock_req_type req_type)
213 {
215  flags, req_type);
216  m0_rm_credit_get(in);
217 
218 }
219 
220 static void rwlock_req_wait(enum rm_server srv,
221  struct m0_rm_incoming *in)
222 {
223  int rc;
224 
226  rc = m0_sm_timedwait(&in->rin_sm,
228  M0_TIME_NEVER);
229  M0_UT_ASSERT(rc == 0);
231 }
232 
233 static void rwlock_acquire(enum rm_server srv,
234  struct m0_rm_incoming *in,
236  enum m0_rm_rwlock_req_type req_type)
237 {
238  rwlock_acquire_nowait(srv, in, flags, req_type);
239  rwlock_req_wait(srv, in);
240  M0_UT_ASSERT(in->rin_rc == 0);
242 }
243 
244 static void rwlock_release(struct m0_rm_incoming *in)
245 {
246  m0_rm_credit_put(in);
248 }
249 
250 static void rwlock_encdec_test()
251 {
252  struct m0_rm_resource *dec_res;
253  struct m0_bufvec bufvec;
254  struct m0_bufvec_cursor cur;
255  const struct m0_rm_resource_type_ops *rwlock_ops;
256  struct m0_rm_resource *resource;
257  int rc;
258 
259  rwlock_utinit();
260  m0_bufvec_alloc(&bufvec, 1, sizeof(struct m0_fid));
261  rwlock_ops = rm_ctxs[SERVER_1].rc_test_data.rd_rt->rt_ops;
262  resource = rm_ctxs[SERVER_1].rc_test_data.rd_res;
263 
264  /* Encode the resource from the data-set */
265  m0_bufvec_cursor_init(&cur, &bufvec);
266  rc = rwlock_ops->rto_encode(&cur, resource);
267  M0_UT_ASSERT(rc == 0);
268 
269  m0_bufvec_cursor_init(&cur, &bufvec);
270  rc = rwlock_ops->rto_decode(&cur, &dec_res);
271  M0_UT_ASSERT(rc == 0);
272  M0_UT_ASSERT(dec_res != NULL);
273  M0_UT_ASSERT(rwlock_ops->rto_eq(resource, dec_res));
274  m0_rm_resource_free(dec_res);
275 
276  m0_bufvec_free(&bufvec);
277  rwlock_utfini();
278 }
279 
281 {
282  rwlock_utinit();
283 
286 
288 
291 
293 
294  rwlock_utfini();
295 }
296 
298 {
299  rwlock_utinit();
302 
304 
307 
309 
310  rwlock_utfini();
311 }
312 
314 {
315  rwlock_utinit();
320 
324 
329 
332 
333  rwlock_utfini();
334 }
335 
337 {
338  rwlock_utinit();
340 
343 
347 
350 
352  M0_UT_ASSERT(INREQ(SERVER_2)->rin_rc == 0);
353 
358 
360 
362  rwlock_utfini();
363 }
364 
366 {
367  rwlock_utinit();
369 
372 
376 
379 
381  M0_UT_ASSERT(INREQ(SERVER_2)->rin_rc == 0);
382 
387 
389 
391  rwlock_utfini();
392 }
393 
395 {
396  rwlock_utinit();
398 
402 
407 
410 
412  M0_UT_ASSERT(INREQ(SERVER_3)->rin_rc == 0);
413 
418 
420 
422  rwlock_utfini();
423 }
424 
426 {
427  rwlock_utinit();
429 
433 
437 
440 
442  M0_UT_ASSERT(INREQ(SERVER_3)->rin_rc == 0);
443 
448 
450 
452  rwlock_utfini();
453 }
454 
456 {
457  rwlock_utinit();
458 
462 
466 
468 
469  /*
470  * Check that read credits are returned to the creditor successfully.
471  */
477  /*
478  * All the servers should be finalized while manually finalizing
479  * the servers.
480  */
483 
485 }
486 
488 {
491 
492  rwlock_utinit();
494 
498 
504 
511 
517 
521 
523 
525  rwlock_utfini();
526 }
527 
529 {
532 
533  rwlock_utinit();
535 
539 
547 
556 
567 
570 }
571 
573  .ts_name = "rm-rwlock-ut",
574  .ts_tests = {
575  { "rwlock-encdec" , rwlock_encdec_test },
576  { "read-lock" , rwlock_read_test },
577  { "read-lock-when-read-hold" , rwlock_read_read_hold_test },
578  { "read-lock-when-write-hold" , rwlock_read_write_hold_test },
579  { "write-lock" , rwlock_write_test },
580  { "write-lock-when-read-hold1", rwlock_write_read_hold_test1 },
581  { "write-lock-when-read-hold2", rwlock_write_read_hold_test2 },
582  { "write-lock-when-write-hold", rwlock_write_write_hold_test },
583  { "two-read-locks" , rwlock_two_read_locks_test },
584  { "writer-starvation" , rwlock_writer_starvation_test },
585  { "read-read-sharing" , rwlock_read_read_sharing_test },
586  { NULL, NULL }
587  }
588 };
589 
590 #undef M0_TRACE_SUBSYSTEM
591 
592 /*
593  * Local variables:
594  * c-indentation-style: "K&R"
595  * c-basic-offset: 8
596  * tab-width: 8
597  * fill-column: 80
598  * scroll-step: 1
599  * End:
600  */
Definition: rmut.h:47
static void rwlock_acquire_nowait(enum rm_server srv, struct m0_rm_incoming *in, enum m0_rm_incoming_flags flags, enum m0_rm_rwlock_req_type req_type)
Definition: rm_rwlock.c:209
static void rwlockable_res_set(struct rm_ut_data *self)
Definition: rm_rwlock.c:70
int const char const void size_t int flags
Definition: dir.c:328
#define NULL
Definition: misc.h:38
#define INREQ(srv_id)
Definition: rm_rwlock.c:42
struct rm_ctx rm_ctxs[SERVER_NR]
Definition: rmut.c:54
void creditor_cookie_setup(enum rm_server dsrv_id, enum rm_server csrv_id)
Definition: rmut.c:420
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
void rwlock_write_read_hold_test1(void)
Definition: rm_rwlock.c:365
void rwlock_write_test(void)
Definition: rm_rwlock.c:297
void(* rio_complete)(struct m0_rm_incoming *in, int32_t rc)
Definition: rm.h:1493
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
M0_INTERNAL bool m0_semaphore_timeddown(struct m0_semaphore *semaphore, const m0_time_t abs_timeout)
Definition: semaphore.c:75
static void rwlock_build_hierarchy(void)
Definition: rm_rwlock.c:140
static void rm_ctx_init(struct m0_rm_lock_ctx *ctx, struct m0_client *m0c, struct m0_fid *fid)
Definition: obj_lock.c:114
static const struct rm_ut_data_ops rwlock_ut_data_ops
Definition: rm_rwlock.c:114
struct rm_ut_data rc_test_data
Definition: rmut.h:133
const struct m0_rm_resource_type_ops rwlockable_type_ops
Definition: rm_rwlock.c:224
Definition: rmut.h:49
struct m0_ut_suite rm_rwlock_ut
Definition: rm_rwlock.c:572
M0_INTERNAL void m0_rm_rwlock_req_init(struct m0_rm_incoming *req, struct m0_rm_owner *owner, const struct m0_rm_incoming_ops *ops, enum m0_rm_incoming_flags flags, enum m0_rm_rwlock_req_type type)
Definition: rm_rwlock.c:548
static void rwlock_servers_windup(void)
Definition: rm_rwlock.c:182
bool(* rto_eq)(const struct m0_rm_resource *resource0, const struct m0_rm_resource *resource1)
Definition: rm.h:454
struct m0_rm_resource_type * rd_rt
Definition: rmut.h:110
#define M0_BITS(...)
Definition: misc.h:236
void rwlock_read_read_sharing_test(void)
Definition: rm_rwlock.c:528
#define container_of(ptr, type, member)
Definition: misc.h:33
Definition: ut.h:77
void rwlock_two_read_locks_test(void)
Definition: rm_rwlock.c:455
M0_INTERNAL void m0_rw_lockable_fini(struct m0_rw_lockable *lockable)
Definition: rm_rwlock.c:523
static void rwlock_release(struct m0_rm_incoming *in)
Definition: rm_rwlock.c:244
static struct m0_semaphore conflict_sem
Definition: rm_rwlock.c:47
Definition: rmut.h:48
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
struct m0_fid fid
Definition: di.c:46
void rwlock_read_test(void)
Definition: rm_rwlock.c:280
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
struct m0_rm_resource rwl_resource
Definition: rm_rwlock.h:120
static void rwlock_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
Definition: rm_rwlock.c:124
m0_rm_incoming_flags
Definition: rm.h:1183
M0_INTERNAL void m0_rm_rwlock_owner_init(struct m0_rm_owner *owner, struct m0_fid *fid, struct m0_rw_lockable *lockable, struct m0_rm_remote *creditor)
Definition: rm_rwlock.c:532
static void rwlockable_rtype_set(struct rm_ut_data *self)
Definition: rm_rwlock.c:50
M0_INTERNAL void m0_bufvec_free(struct m0_bufvec *bufvec)
Definition: vec.c:395
m0_rm_rwlock_req_type
Definition: rm_rwlock.h:104
static void rm_ctx_fini(struct m0_ref *ref)
Definition: obj_lock.c:168
int i
Definition: dir.c:1033
struct m0_sm rin_sm
Definition: rm.h:1436
Definition: rmut.h:50
static void rwlock_incoming_conflict(struct m0_rm_incoming *in)
Definition: rm_rwlock.c:130
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
Definition: rmut.h:46
static enum m0_rm_owner_state owner_state(const struct m0_rm_owner *owner)
Definition: rm_internal.h:297
M0_INTERNAL void m0_rm_rwlock_owner_fini(struct m0_rm_owner *owner)
Definition: rm_rwlock.c:542
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
rm_server
Definition: rmut.h:45
#define m0_free0(pptr)
Definition: memory.h:77
static enum rm_server test_servers_nr
Definition: rm_rwlock.c:46
static enum m0_rm_incoming_state incoming_state(const struct m0_rm_incoming *in)
Definition: rm_internal.h:285
static void rwlock_servers_disc_fini(void)
Definition: rm_rwlock.c:190
void rm_ctxs_conf_fini(struct rm_ctx *rm_ctxs, int ctxs_nr)
Definition: rmut.c:382
M0_INTERNAL void m0_rw_lockable_init(struct m0_rw_lockable *lockable, const struct m0_fid *fid, struct m0_rm_domain *dom)
Definition: rm_rwlock.c:508
int32_t rin_rc
Definition: rm.h:1446
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
static void rwlock_acquire(enum rm_server srv, struct m0_rm_incoming *in, enum m0_rm_incoming_flags flags, enum m0_rm_rwlock_req_type req_type)
Definition: rm_rwlock.c:233
M0_INTERNAL void m0_rm_rwlock_req_fini(struct m0_rm_incoming *req)
Definition: rm_rwlock.c:567
static struct rectype rt[]
Definition: beck.c:428
static void rwlock_utinit(void)
Definition: rm_rwlock.c:161
void(* rtype_set)(struct rm_ut_data *self)
Definition: rmut.h:96
#define OWNER(srv_id)
Definition: rm_rwlock.c:41
enum rm_server debtor_id[SERVER_NR - 1]
Definition: rmut.h:137
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
const struct m0_rm_incoming_ops rwlock_incoming_ops
Definition: rm_rwlock.c:135
static void rwlock_utfini(void)
Definition: rm_rwlock.c:203
int(* rto_decode)(struct m0_bufvec_cursor *cur, struct m0_rm_resource **resource)
Definition: rm.h:468
void rwlock_write_read_hold_test2(void)
Definition: rm_rwlock.c:394
Definition: rm.h:1145
static void rwlockable_res_unset(struct rm_ut_data *self)
Definition: rm_rwlock.c:81
uint32_t rc_debtors_nr
Definition: rmut.h:134
M0_INTERNAL void m0_rm_resource_free(struct m0_rm_resource *res)
Definition: rm.c:386
static void rwlock_owner_unset(struct rm_ut_data *self)
Definition: rm_rwlock.c:107
void rm_ctxs_conf_init(struct rm_ctx *rm_ctxs, int ctxs_nr)
Definition: rmut.c:345
static void rwlock_encdec_test()
Definition: rm_rwlock.c:250
static void rwlock_owner_set(struct rm_ut_data *self)
Definition: rm_rwlock.c:92
const char * ts_name
Definition: ut.h:99
Definition: rmut.h:88
const struct rm_ut_data_ops * rd_ops
Definition: rmut.h:115
M0_INTERNAL void m0_rm_credit_put(struct m0_rm_incoming *in)
Definition: rm.c:1797
void rwlock_write_write_hold_test(void)
Definition: rm_rwlock.c:425
int(* rto_encode)(struct m0_bufvec_cursor *cur, const struct m0_rm_resource *resource)
Definition: rm.h:473
void rwlock_read_write_hold_test(void)
Definition: rm_rwlock.c:336
Definition: fid.h:38
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
static void rwlock_req_wait(enum rm_server srv, struct m0_rm_incoming *in)
Definition: rm_rwlock.c:220
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
static void rwlockable_rtype_unset(struct rm_ut_data *self)
Definition: rm_rwlock.c:64
Definition: rm.h:863
enum rm_server creditor_id
Definition: rmut.h:136
const struct m0_rm_resource_type_ops * rt_ops
Definition: rm.h:388
M0_INTERNAL void m0_rm_owner_unlock(struct m0_rm_owner *owner)
Definition: rm.c:603
M0_INTERNAL int m0_rm_type_register(struct m0_rm_domain *dom, struct m0_rm_resource_type *rt)
Definition: rm.c:252
static struct m0_semaphore waiting_sem
Definition: rm_rwlock.c:48
void rwlock_read_read_hold_test(void)
Definition: rm_rwlock.c:313
void credits_are_equal(enum rm_server srv_id, enum rm_ut_credits_list list_id, uint64_t value)
Definition: rmut.c:429
struct m0_rm_resource * rd_res
Definition: rmut.h:111
M0_INTERNAL void m0_rm_owner_lock(struct m0_rm_owner *owner)
Definition: rm.c:592
M0_INTERNAL void m0_semaphore_up(struct m0_semaphore *semaphore)
Definition: semaphore.c:65
M0_INTERNAL void m0_rm_type_deregister(struct m0_rm_resource_type *rt)
Definition: rm.c:288
void rm_ctx_server_stop(enum rm_server srv_id)
Definition: rmut.c:291
void rwlock_writer_starvation_test(void)
Definition: rm_rwlock.c:487
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
void rm_ctx_server_start(enum rm_server srv_id)
Definition: rmut.c:222
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL void m0_rm_credit_get(struct m0_rm_incoming *in)
Definition: rm.c:1758
void rm_ctx_server_owner_windup(enum rm_server srv_id)
Definition: rmut.c:264
Definition: vec.h:145
static struct net_srv srv
Definition: net_test.c:52