Motr  M0
flock.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 #include <sys/stat.h>
24 #include "lib/misc.h"
25 #include "lib/memory.h"
26 #include "lib/finject.h"
27 #include "lib/locality.h"
28 
29 #include "reqh/reqh_service.h"
30 #include "reqh/reqh.h"
31 #include "motr/setup.h"
32 
33 #include "sns/cm/repair/ag.h"
34 #include "sns/cm/cm.h"
35 #include "sns/cm/file.h"
37 #include "fop/fom_simple.h"
38 #include "mdservice/md_fid.h"
39 #include "rm/rm_service.h" /* m0_rms_type */
40 
41 enum {
44  KEY_START = 1ULL << 16,
45  NR = 3,
47  NR_FIDS = 10,
48 };
49 
50 struct flock_ut_fom {
53 };
54 
55 static struct m0_reqh *reqh;
56 static struct m0_reqh_service *service;
57 static struct m0_cm *cm;
58 static struct m0_sns_cm *scm;
59 static struct flock_ut_fom fs[NR];
60 static struct m0_fid test_fids[NR_FIDS];
61 static struct m0_fid gfid;
62 static int fid_index;
63 
64 enum {
69 };
70 
72  [M0_FOM_PHASE_INIT] = {
73  .sd_name = "init",
74  .sd_allowed = M0_BITS(FILE_LOCK),
75  .sd_flags = M0_SDF_INITIAL
76  },
77  [FILE_LOCK] = {
78  .sd_name = "File lock acquire",
80  },
81  [FILE_LOCK_WAIT] = {
82  .sd_name = "Wait for file lock",
84  },
85  [FILE_LOCKED] = {
86  .sd_name = "file locked, now unlock",
88  },
89  [FILE_UNLOCK_WAIT] = {
90  .sd_name = "file unlocked, now fini",
91  .sd_allowed = M0_BITS(M0_FOM_PHASE_FINISH)
92  },
94  .sd_name = "fini",
95  .sd_flags = M0_SDF_TERMINAL
96  }
97 };
98 
99 static struct m0_sm_conf flock_ut_conf = {
100  .scf_name = "flock ut fom",
101  .scf_nr_states = ARRAY_SIZE(flock_ut_fom_phases),
102  .scf_state = flock_ut_fom_phases,
103 };
104 
105 static int file_lock_verify(struct m0_sns_cm *scm, struct m0_fid *fid,
106  int64_t ref)
107 {
108  struct m0_sns_cm_file_ctx *fctx;
109 
111  M0_UT_ASSERT(fctx != NULL);
114  M0_UT_ASSERT(m0_ref_read(&fctx->sf_ref) <= ref);
115  return 0;
116 }
117 
119 {
120  return container_of(fs, struct flock_ut_fom, uf_fom);
121 }
122 
123 static int flock_ut_fom_tick(struct m0_fom *fom, void *data, int *phase)
124 {
125  int rc;
126  struct m0_sns_cm_file_ctx *fctx;
127  struct m0_fid *fid;
128 
129  fid = &gfid;
130 
131  m0_cm_lock(cm);
133  switch (*phase) {
134  case M0_FOM_PHASE_INIT:
135  *phase = FILE_LOCK;
136  rc = M0_FSO_AGAIN;
137  break;
138  case FILE_LOCK:
140  M0_UT_ASSERT(rc == 0 || rc == -EAGAIN);
141  if (rc == -EAGAIN)
143  if (rc == -EAGAIN) {
144  *phase = FILE_LOCK_WAIT;
145  rc = M0_FSO_WAIT;
146  }
147  if (rc == 0) {
148  *phase = FILE_LOCKED;
149  rc = M0_FSO_AGAIN;
150  }
151  break;
152  case FILE_LOCK_WAIT:
153  fctx = m0_scmfctx_htable_lookup(&scm->sc_file_ctx, fid);
154  M0_UT_ASSERT(fctx != NULL);
156  M0_UT_ASSERT(rc == 0 || rc == -EAGAIN);
157  if (rc == -EAGAIN)
158  rc = M0_FSO_WAIT;
159  if (rc == 0) {
160  *phase = FILE_LOCKED;
161  rc = M0_FSO_AGAIN;
162  }
163  break;
164  case FILE_LOCKED:
165  fctx = m0_scmfctx_htable_lookup(&scm->sc_file_ctx, fid);
168  m0_fom_wait_on(fom, &fctx->sf_sm.sm_chan, &fom->fo_cb);
170  *phase = FILE_UNLOCK_WAIT;
171  rc = M0_FSO_WAIT;
172  break;
173  case FILE_UNLOCK_WAIT:
174  M0_UT_ASSERT(m0_scmfctx_htable_lookup(&scm->sc_file_ctx, fid) == NULL);
175  *phase = M0_FOM_PHASE_FINISH;
176  rc = M0_FSO_WAIT;
177  break;
178  default:
179  rc = -1;
180  break;
181  }
182 
183  m0_cm_unlock(cm);
185 
186  return rc;
187 }
188 
190 {
191  struct flock_ut_fom *ut_fom = fom_simple2flock_fom(sfom);
192 
193  m0_semaphore_up(&ut_fom->uf_sem);
194 }
195 
196 static void sns_flock_multi_fom(void)
197 {
198  uint32_t i;
199 
200  M0_SET0(&fs);
201  m0_fid_set(&gfid, 0, KEY_START);
202  for (i = 0; i < NR; i++) {
206  }
207  for (i = 0; i < NR; i++) {
210  }
211 }
212 
213 static void sns_flock_single_fom(void)
214 {
215  m0_fid_set(&gfid, 0, KEY_START);
216 
217  m0_semaphore_init(&fs[0].uf_sem, 0);
222 }
223 
224 static int fids_set(void)
225 {
226  uint64_t cont = 0;
227  uint64_t key = KEY_START;
228  int i;
229 
230  for (i = 0; i < NR_FIDS; ++i) {
231  m0_fid_set(&test_fids[i], cont, key);
232  key++;
233  if (key == KEY_MAX) {
234  cont++;
235  key = KEY_START;
236  }
237  }
238  return 0;
239 }
240 
241 static int test_setup(void)
242 {
243  int rc;
244 
245  rc = cs_init(&sctx);
246  M0_ASSERT(rc == 0);
248  M0_ASSERT(reqh != NULL);
250  m0_reqh_service_type_find("M0_CST_SNS_REP"), reqh);
251  M0_ASSERT(service != NULL);
252  cm = container_of(service, struct m0_cm, cm_service);
253  M0_ASSERT(cm != NULL);
254  scm = cm2sns(cm);
255  M0_ASSERT(scm != NULL);
257  M0_ASSERT(rc == 0);
259  M0_ASSERT(rc == 0);
261  M0_ASSERT(service != NULL);
262  fids_set();
263  return 0;
264 }
265 
266 static int test_fini(void)
267 {
270  cs_fini(&sctx);
271  return 0;
272 }
273 
275  struct m0_clink *clink)
276 {
277  struct m0_chan *chan;
278  enum m0_rm_incoming_state state;
279 
282  state = fctx->sf_rin.rin_sm.sm_state;
285  /* Check if the lock is already acquired before waiting. */
286  while (!M0_IN(state, (RI_SUCCESS, RI_FAILURE))) {
288  state = fctx->sf_rin.rin_sm.sm_state;
289  }
290 
291  M0_UT_ASSERT(state == RI_SUCCESS);
298 }
299 
301  struct m0_clink *clink)
302 {
303  clink->cl_is_oneshot = true;
308 }
309 
310 static void sns_file_lock_unlock(void)
311 {
313  struct m0_clink tc_clink[NR_FIDS];
314  struct m0_fid fid;
315  uint64_t cont = 0;
316  uint64_t key = KEY_START;
317  int i;
318  int rc;
319 
321  for (i = 0; i < NR_FIDS; i++) {
322  fid_index = i;
323  m0_clink_init(&tc_clink[i], NULL);
325  M0_SET0(&fid);
326  m0_fid_set(&fid, cont, key);
328  M0_UT_ASSERT(rc == -EAGAIN);
330  file_lock_wait(fctx[i], &tc_clink[i]);
331  file_lock_verify(scm, &fid, 1);
332  ++key;
333  if (key == KEY_MAX) {
334  cont++;
335  key = KEY_START;
336  }
337  file_unlock_and_wait(fctx[i], &tc_clink[i]);
338  m0_clink_fini(&tc_clink[i]);
339  }
341 }
342 
344  .ts_name = "sns-file-lock-ut",
345  .ts_init = test_setup,
346  .ts_fini = test_fini,
347  .ts_tests = {
348  { "sns-file-lock-unlock", sns_file_lock_unlock},
349  { "sns-flock-single-fom", sns_flock_single_fom},
350  { "sns-flock-multi-fom", sns_flock_multi_fom},
351  { NULL, NULL }
352  }
353 };
354 
355 /*
356  * Local variables:
357  * c-indentation-style: "K&R"
358  * c-basic-offset: 8
359  * tab-width: 8
360  * fill-column: 80
361  * scroll-step: 1
362  * End:
363  */
void cs_fini(struct m0_motr *sctx)
Definition: cp_common.c:221
Definition: cm.h:205
M0_INTERNAL int m0_cm_ast_run_thread_init(struct m0_cm *cm)
Definition: cm.c:1215
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
Definition: flock.c:46
M0_INTERNAL void m0_cm_lock(struct m0_cm *cm)
Definition: cm.c:545
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
struct m0_reqh * m0_cs_reqh_get(struct m0_motr *cctx)
Definition: setup.c:1762
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
M0_INTERNAL void m0_clink_del(struct m0_clink *link)
Definition: chan.c:267
struct m0_htable sc_file_ctx
Definition: cm.h:268
M0_INTERNAL struct m0_sns_cm * cm2sns(struct m0_cm *cm)
Definition: cm.c:389
Definition: sm.h:350
static struct m0_reqh * reqh
Definition: flock.c:55
static struct m0_sm_conf flock_ut_conf
Definition: flock.c:99
static struct m0_sns_cm * scm
Definition: flock.c:58
struct m0_bufvec data
Definition: di.c:40
static void file_unlock_and_wait(struct m0_sns_cm_file_ctx *fctx, struct m0_clink *clink)
Definition: flock.c:300
M0_INTERNAL void m0_cm_ast_run_thread_fini(struct m0_cm *cm)
Definition: cm.c:1223
M0_INTERNAL void m0_fom_wait_on(struct m0_fom *fom, struct m0_chan *chan, struct m0_fom_callback *cb)
Definition: fom.c:1490
#define M0_BITS(...)
Definition: misc.h:236
static void file_lock_wait(struct m0_sns_cm_file_ctx *fctx, struct m0_clink *clink)
Definition: flock.c:274
M0_INTERNAL int m0_sns_cm_file_lock(struct m0_sns_cm *scm, const struct m0_fid *fid, struct m0_sns_cm_file_ctx **out)
Definition: file.c:404
struct m0_fid sf_fid
Definition: file.h:63
Definition: flock.c:45
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
Definition: ut.h:77
M0_INTERNAL struct m0_reqh_service_type * m0_reqh_service_type_find(const char *sname)
Definition: reqh_service.c:168
struct m0_fid fid
Definition: di.c:46
static struct m0_fid gfid
Definition: flock.c:61
M0_INTERNAL void m0_cm_unlock(struct m0_cm *cm)
Definition: cm.c:550
static int fid_index
Definition: flock.c:62
static void sns_flock_single_fom(void)
Definition: flock.c:213
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
struct m0_ut_suite sns_flock_ut
Definition: flock.c:343
int i
Definition: dir.c:1033
struct m0_sm rin_sm
Definition: rm.h:1436
M0_INTERNAL void m0_fid_set(struct m0_fid *fid, uint64_t container, uint64_t key)
Definition: fid.c:116
static void sns_file_lock_unlock(void)
Definition: flock.c:310
struct m0_mutex sc_file_ctx_mutex
Definition: cm.h:271
static int file_lock_verify(struct m0_sns_cm *scm, struct m0_fid *fid, int64_t ref)
Definition: flock.c:105
static int key
Definition: locality.c:283
m0_rm_incoming_state
Definition: rm.h:1134
M0_INTERNAL int m0_sns_cm_file_lock_wait(struct m0_sns_cm_file_ctx *fctx, struct m0_fom *fom)
Definition: file.c:370
M0_INTERNAL void m0_sns_cm_file_unlock(struct m0_sns_cm *scm, struct m0_fid *fid)
Definition: file.c:504
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
static struct flock_ut_fom * fom_simple2flock_fom(struct m0_fom_simple *fs)
Definition: flock.c:118
struct m0_semaphore uf_sem
Definition: flock.c:52
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
static int test_setup(void)
Definition: flock.c:241
M0_INTERNAL int m0_semaphore_init(struct m0_semaphore *semaphore, unsigned value)
Definition: semaphore.c:38
M0_INTERNAL int m0_sns_cm_rm_init(struct m0_sns_cm *scm)
Definition: cm.c:451
struct m0_fom_simple uf_fom
Definition: flock.c:51
struct m0_sm_group * sm_grp
Definition: sm.h:321
static struct m0_rpc_server_ctx sctx
Definition: console.c:88
void flock_ut_fom_free(struct m0_fom_simple *sfom)
Definition: flock.c:189
Definition: reqh.h:94
Definition: dump.c:103
Definition: chan.h:229
static struct m0_clink clink[RDWR_REQUEST_MAX]
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
Definition: fom.h:481
struct m0_reqh_service_type m0_rms_type
Definition: rm_service.c:69
const char * ts_name
Definition: ut.h:99
M0_INTERNAL struct m0_reqh_service * m0_reqh_service_find(const struct m0_reqh_service_type *st, const struct m0_reqh *reqh)
Definition: reqh_service.c:538
M0_INTERNAL int64_t m0_ref_read(const struct m0_ref *ref)
Definition: refs.c:44
const char * sd_name
Definition: sm.h:383
static int flock_ut_fom_tick(struct m0_fom *fom, void *data, int *phase)
Definition: flock.c:123
static struct m0_chan chan[RDWR_REQUEST_MAX]
Definition: fid.h:38
struct m0_ref sf_ref
Definition: file.h:110
static struct m0_fid test_fids[NR_FIDS]
Definition: flock.c:60
struct m0_chan sm_chan
Definition: sm.h:331
M0_INTERNAL void m0_clink_add(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:228
M0_INTERNAL bool m0_chan_timedwait(struct m0_clink *link, const m0_time_t abs_timeout)
Definition: chan.c:349
M0_INTERNAL void m0_semaphore_fini(struct m0_semaphore *semaphore)
Definition: semaphore.c:45
static struct m0_sm_state_descr flock_ut_fom_phases[]
Definition: flock.c:71
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
int cs_init(struct m0_motr *sctx)
Definition: cp_common.c:206
struct m0_rm_incoming sf_rin
Definition: file.h:91
Definition: cm.h:166
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
M0_INTERNAL struct m0_sns_cm_file_ctx * m0_sns_cm_fctx_locate(struct m0_sns_cm *scm, struct m0_fid *fid)
Definition: file.c:441
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
struct m0_sm sf_sm
Definition: file.h:112
M0_INTERNAL int m0_sns_cm_fctx_state_get(struct m0_sns_cm_file_ctx *fctx)
Definition: file.c:137
M0_INTERNAL void m0_rm_owner_unlock(struct m0_rm_owner *owner)
Definition: rm.c:603
struct m0_cm sc_base
Definition: cm.h:206
static struct m0_sns_cm_file_ctx fctx
Definition: net.c:55
Definition: flock.c:47
M0_INTERNAL void m0_semaphore_down(struct m0_semaphore *semaphore)
Definition: semaphore.c:49
static void sns_flock_multi_fom(void)
Definition: flock.c:196
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
struct m0_rm_owner sf_owner
Definition: file.h:85
static struct m0_cm * cm
Definition: flock.c:57
#define M0_FOM_SIMPLE_POST(s, r, c, t, f, d, l)
Definition: fom_simple.h:165
uint32_t sm_state
Definition: sm.h:307
M0_INTERNAL void m0_sns_cm_rm_fini(struct m0_sns_cm *scm)
Definition: cm.c:670
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static struct flock_ut_fom fs[NR]
Definition: flock.c:59
static int fids_set(void)
Definition: flock.c:224
static int test_fini(void)
Definition: flock.c:266
Definition: idx_mock.c:47
static struct m0_reqh_service * service
Definition: flock.c:56