Motr  M0
obj_lock.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2019-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 
29 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CLIENT
30 
31 #include "lib/trace.h"
32 #include "motr/client.h"
33 #include "motr/client_internal.h"
34 #include "motr/io.h"
35 #include "ioservice/fid_convert.h"
36 
38 static void rm_ctx_init(struct m0_rm_lock_ctx *ctx,
39  struct m0_client *m0c,
40  struct m0_fid *fid);
41 
43 static void rm_ctx_fini(struct m0_ref *ref);
44 
46 static void rm_lock_req_init(struct m0_clink *clink,
47  struct m0_rm_owner *owner,
48  struct m0_rm_lock_req *req,
49  enum m0_rm_rwlock_req_type rw_type);
50 
52 static void rm_lock_req_fini(struct m0_rm_lock_req *req);
53 
55 static void obj_lock_incoming_complete(struct m0_rm_incoming *in, int32_t rc);
56 
58 static void obj_lock_incoming_conflict(struct m0_rm_incoming *in);
59 
62  .rio_conflict = obj_lock_incoming_conflict
63 };
64 
65 static bool rm_key_eq(const void *key1, const void *key2)
66 {
67  return m0_fid_eq(key1, key2);
68 }
69 
70 static uint64_t rm_hash_func(const struct m0_htable *htable, const void *k)
71 {
72  return m0_fid_hash(k) % htable->h_bucket_nr;
73 }
74 
75 M0_HT_DESCR_DEFINE(rm_ctx, "Hash-table for RM locks", M0_INTERNAL,
76  struct m0_rm_lock_ctx, rmc_hlink, rmc_magic,
78  rmc_key, rm_hash_func, rm_key_eq);
79 
80 M0_HT_DEFINE(rm_ctx, M0_INTERNAL, struct m0_rm_lock_ctx, struct m0_fid);
81 
83 {
84  struct m0_fid fid;
85  struct m0_rm_lock_ctx *ctx;
86  struct m0_entity *ent = &obj->ob_entity;
87  struct m0_client *m0c = ent->en_realm->re_instance;
88 
89  M0_ENTRY();
90  M0_PRE(obj != NULL);
91 
92  m0_fid_gob_make(&fid, ent->en_id.u_hi, ent->en_id.u_lo);
94  rm_ctx_hbucket_lock(&m0c->m0c_rm_ctxs, &fid);
95  ctx = rm_ctx_htable_lookup(&m0c->m0c_rm_ctxs, &fid);
96  if (ctx != NULL)
97  m0_ref_get(&ctx->rmc_ref);
98  else {
100  if (ctx == NULL) {
101  rm_ctx_hbucket_unlock(&m0c->m0c_rm_ctxs, &fid);
102  return M0_RC(-ENOMEM);
103  }
104  rm_ctx_init(ctx, m0c, &fid);
105  rm_ctx_htable_add(&m0c->m0c_rm_ctxs, ctx);
106  }
107  m0_cookie_init(&obj->ob_cookie, &ctx->rmc_gen);
108  rm_ctx_hbucket_unlock(&m0c->m0c_rm_ctxs, &fid);
109 
110  return M0_RC(0);
111 }
112 M0_EXPORTED(m0_obj_lock_init);
113 
114 static void rm_ctx_init(struct m0_rm_lock_ctx *ctx,
115  struct m0_client *m0c,
116  struct m0_fid *fid)
117 {
118  struct m0_rm_domain *rdom;
119  struct m0_pools_common *pc = &m0c->m0c_pools_common;
120 
121  M0_ENTRY();
122 
123  rdom = rm_domain_get(m0c);
124  M0_ASSERT(rdom != NULL);
125 
126  ctx->rmc_magic = M0_RM_MAGIC;
127  ctx->rmc_htable = &m0c->m0c_rm_ctxs;
128  ctx->rmc_key = *fid;
129  m0_cookie_new(&ctx->rmc_gen);
130  rm_ctx_tlink_init(ctx);
131  m0_ref_init(&ctx->rmc_ref, 1, rm_ctx_fini);
132  m0_rw_lockable_init(&ctx->rmc_rw_file, &ctx->rmc_key, rdom);
133  m0_rm_remote_init(&ctx->rmc_creditor, &ctx->rmc_rw_file.rwl_resource);
134  ctx->rmc_creditor.rem_session = m0_pools_common_active_rm_session(pc);
135  M0_ASSERT(ctx->rmc_creditor.rem_session != NULL);
136  ctx->rmc_creditor.rem_state = REM_SERVICE_LOCATED;
137  m0_fid_tgenerate(&ctx->rmc_own_fid, M0_RM_OWNER_FT);
138  m0_rm_rwlock_owner_init(&ctx->rmc_owner, &ctx->rmc_own_fid,
139  &ctx->rmc_rw_file, &ctx->rmc_creditor);
140 
141  M0_LEAVE();
142 }
143 
145 {
146  struct m0_rm_lock_ctx *ctx;
147 
148  M0_ENTRY();
149  M0_PRE(obj != NULL);
150 
151  ctx = m0_cookie_of(&obj->ob_cookie, struct m0_rm_lock_ctx,
152  rmc_gen);
153  M0_ASSERT(ctx != NULL);
154  rm_ctx_hbucket_lock(ctx->rmc_htable, &ctx->rmc_key);
155  if (m0_ref_read(&ctx->rmc_ref) == 1) {
156  rm_ctx_htable_del(ctx->rmc_htable, ctx);
157  rm_ctx_hbucket_unlock(ctx->rmc_htable, &ctx->rmc_key);
158  m0_ref_put(&ctx->rmc_ref);
159  } else {
160  m0_ref_put(&ctx->rmc_ref);
161  rm_ctx_hbucket_unlock(ctx->rmc_htable, &ctx->rmc_key);
162  }
163 
164  M0_LEAVE();
165 }
166 M0_EXPORTED(m0_obj_lock_fini);
167 
168 static void rm_ctx_fini(struct m0_ref *ref)
169 {
170  int rc;
171  struct m0_rm_lock_ctx *ctx;
172 
173  M0_ENTRY();
174 
175  ctx = M0_AMB(ctx, ref, rmc_ref);
176 
177  m0_rm_owner_windup(&ctx->rmc_owner);
178  rc = m0_rm_owner_timedwait(&ctx->rmc_owner,
180  M0_TIME_NEVER);
181  M0_ASSERT(rc == 0);
182  m0_rm_rwlock_owner_fini(&ctx->rmc_owner);
183  m0_rm_remote_fini(&ctx->rmc_creditor);
184  m0_rw_lockable_fini(&ctx->rmc_rw_file);
185  rm_ctx_tlink_fini(ctx);
186  m0_free(ctx);
187 
188  M0_LEAVE();
189 }
190 
191 M0_INTERNAL int m0_obj_lock_get(struct m0_obj *obj,
192  struct m0_rm_lock_req *req,
193  struct m0_clink *clink,
194  enum m0_rm_rwlock_req_type rw_type)
195 {
196  struct m0_rm_lock_ctx *ctx;
197 
198  M0_ENTRY();
199  M0_PRE(obj != NULL);
200  M0_PRE(req != NULL);
201  M0_PRE(clink != NULL);
203 
204  ctx = m0_cookie_of(&obj->ob_cookie, struct m0_rm_lock_ctx,
205  rmc_gen);
206  M0_ASSERT(ctx != NULL);
207  req->rlr_rc = 0;
208  rm_lock_req_init(clink, &ctx->rmc_owner, req, rw_type);
209  m0_rm_credit_get(&req->rlr_in);
210 
211  return M0_RC(0);
212 }
213 
214 M0_INTERNAL int m0_obj_lock_get_sync(struct m0_obj *obj,
215  struct m0_rm_lock_req *req,
216  enum m0_rm_rwlock_req_type rw_type)
217 {
218  struct m0_clink clink;
219 
220  M0_ENTRY();
221  M0_PRE(obj != NULL);
222  M0_PRE(req != NULL);
223 
225  clink.cl_is_oneshot = true;
226  m0_obj_lock_get(obj, req, &clink, rw_type);
229 
230  return M0_RC(req->rlr_rc);
231 }
232 
234  struct m0_rm_lock_req *req,
235  struct m0_clink *clink)
236 {
237  M0_ENTRY();
239 }
240 M0_EXPORTED(m0_obj_write_lock_get);
241 
243  struct m0_rm_lock_req *req)
244 {
245  M0_ENTRY();
247 }
248 M0_EXPORTED(m0_obj_write_lock_get_sync);
249 
251  struct m0_rm_lock_req *req,
252  struct m0_clink *clink)
253 {
254  M0_ENTRY();
256 }
257 M0_EXPORTED(m0_obj_read_lock_get);
258 
260  struct m0_rm_lock_req *req)
261 {
262  M0_ENTRY();
264 }
265 M0_EXPORTED(m0_obj_read_lock_get_sync);
266 
268 {
269  M0_ENTRY();
270 
271  M0_PRE(req != NULL);
272  m0_rm_credit_put(&req->rlr_in);
274 
275  M0_LEAVE();
276 }
277 M0_EXPORTED(m0_obj_lock_put);
278 
279 static void rm_lock_req_init(struct m0_clink *clink,
280  struct m0_rm_owner *owner,
281  struct m0_rm_lock_req *req,
282  enum m0_rm_rwlock_req_type rw_type)
283 {
284  M0_ENTRY();
285 
288  RIF_MAY_REVOKE | RIF_RESERVE, rw_type);
289  m0_mutex_init(&req->rlr_mutex);
290  m0_chan_init(&req->rlr_chan, &req->rlr_mutex);
291  m0_clink_add_lock(&req->rlr_chan, clink);
292 
293  M0_LEAVE();
294 }
295 
296 static void rm_lock_req_fini(struct m0_rm_lock_req *req)
297 {
298  M0_ENTRY();
299 
300  m0_chan_fini_lock(&req->rlr_chan);
301  m0_mutex_fini(&req->rlr_mutex);
302  m0_rm_incoming_fini(&req->rlr_in);
303 
304  M0_LEAVE();
305 }
306 
307 static void obj_lock_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
308 {
309  struct m0_rm_lock_req *req;
310 
311  M0_ENTRY();
312 
313  req = M0_AMB(req, in, rlr_in);
314  req->rlr_rc = rc;
315  /* Signals the thread waiting for the lock to be granted */
316  m0_chan_broadcast_lock(&req->rlr_chan);
317 
318  M0_LEAVE();
319 }
320 
322 {
323  /* Do nothing */
324 }
325 
326 #undef M0_TRACE_SUBSYSTEM
327 
330 /*
331  * Local variables:
332  * c-indentation-style: "K&R"
333  * c-basic-offset: 8
334  * tab-width: 8
335  * fill-column: 80
336  * scroll-step: 1
337  * End:
338  */
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
#define M0_PRE(cond)
M0_INTERNAL void m0_fid_gob_make(struct m0_fid *gob_fid, uint32_t container, uint64_t key)
Definition: fid_convert.c:46
M0_INTERNAL void m0_chan_broadcast_lock(struct m0_chan *chan)
Definition: chan.c:178
Definition: client.h:788
void m0_obj_lock_put(struct m0_rm_lock_req *req)
Definition: obj_lock.c:267
M0_INTERNAL uint64_t m0_fid_hash(const struct m0_fid *fid)
Definition: fid.c:295
#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
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
static struct io_request req
Definition: file.c:100
int m0_obj_read_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: obj_lock.c:250
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
static void rm_ctx_init(struct m0_rm_lock_ctx *ctx, struct m0_client *m0c, struct m0_fid *fid)
Definition: obj_lock.c:114
int m0_obj_write_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: obj_lock.c:242
static void obj_lock_incoming_complete(struct m0_rm_incoming *in, int32_t rc)
Definition: obj_lock.c:307
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
int m0_obj_lock_init(struct m0_obj *obj)
Definition: obj_lock.c:82
int m0_obj_write_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink)
Definition: obj_lock.c:233
static struct m0_clovis * m0c
Definition: main.c:25
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL void m0_rm_remote_init(struct m0_rm_remote *rem, struct m0_rm_resource *res)
Definition: rm.c:1411
void m0_obj_lock_fini(struct m0_obj *obj)
Definition: obj_lock.c:144
M0_INTERNAL void m0_rw_lockable_fini(struct m0_rw_lockable *lockable)
Definition: rm_rwlock.c:523
static struct foo * obj
Definition: tlist.c:302
M0_INTERNAL int m0_rm_owner_timedwait(struct m0_rm_owner *owner, uint64_t state, const m0_time_t abs_timeout)
Definition: rm.c:892
static struct m0_pools_common pc
Definition: iter_ut.c:59
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
#define M0_ENTRY(...)
Definition: trace.h:170
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
m0_rm_rwlock_req_type
Definition: rm_rwlock.h:104
static void rm_ctx_fini(struct m0_ref *ref)
Definition: obj_lock.c:168
struct m0_ref rmc_ref
static void rm_lock_req_fini(struct m0_rm_lock_req *req)
Definition: obj_lock.c:296
struct m0_rm_incoming rlr_in
M0_INTERNAL void m0_ref_put(struct m0_ref *ref)
Definition: refs.c:38
Definition: rmut.h:123
void m0_ref_init(struct m0_ref *ref, int init_num, void(*release)(struct m0_ref *ref))
Definition: refs.c:24
int m0_obj_read_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req)
Definition: obj_lock.c:259
M0_INTERNAL void m0_ref_get(struct m0_ref *ref)
Definition: refs.c:32
Definition: trace.h:482
M0_INTERNAL void m0_rm_rwlock_owner_fini(struct m0_rm_owner *owner)
Definition: rm_rwlock.c:542
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
Definition: refs.h:34
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
#define M0_ASSERT(cond)
M0_INTERNAL void m0_fid_tgenerate(struct m0_fid *fid, const uint8_t tid)
Definition: fid.c:155
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
static void obj_lock_incoming_conflict(struct m0_rm_incoming *in)
Definition: obj_lock.c:321
M0_HT_DESCR_DEFINE(rm_ctx, "Hash-table for RM locks", M0_INTERNAL, struct m0_rm_lock_ctx, rmc_hlink, rmc_magic, M0_RM_MAGIC, M0_RM_HEAD_MAGIC, rmc_key, rm_hash_func, rm_key_eq)
M0_INTERNAL struct m0_rm_domain * rm_domain_get(struct m0_client *cinst)
Definition: io.c:59
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
static bool rm_key_eq(const void *key1, const void *key2)
Definition: obj_lock.c:65
static struct m0_clink clink[RDWR_REQUEST_MAX]
const struct m0_rm_incoming_ops obj_lock_incoming_ops
Definition: obj_lock.c:60
static struct fdmi_ctx ctx
Definition: main.c:80
#define FID_P(f)
Definition: fid.h:77
M0_INTERNAL int m0_obj_lock_get_sync(struct m0_obj *obj, struct m0_rm_lock_req *req, enum m0_rm_rwlock_req_type rw_type)
Definition: obj_lock.c:214
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
M0_INTERNAL void m0_rm_credit_put(struct m0_rm_incoming *in)
Definition: rm.c:1797
M0_INTERNAL int64_t m0_ref_read(const struct m0_ref *ref)
Definition: refs.c:44
Definition: fid.h:38
M0_INTERNAL void m0_rm_remote_fini(struct m0_rm_remote *rem)
Definition: rm.c:1431
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_HT_DEFINE(rm_ctx, M0_INTERNAL, struct m0_rm_lock_ctx, struct m0_fid)
Definition: rm.h:863
M0_INTERNAL void m0_rm_owner_windup(struct m0_rm_owner *owner)
Definition: rm.c:930
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
static uint64_t rm_hash_func(const struct m0_htable *htable, const void *k)
Definition: obj_lock.c:70
M0_INTERNAL int m0_obj_lock_get(struct m0_obj *obj, struct m0_rm_lock_req *req, struct m0_clink *clink, enum m0_rm_rwlock_req_type rw_type)
Definition: obj_lock.c:191
M0_INTERNAL void m0_rm_incoming_fini(struct m0_rm_incoming *in)
Definition: rm.c:1099
M0_INTERNAL struct m0_rpc_session * m0_pools_common_active_rm_session(struct m0_pools_common *pc)
Definition: pool.c:1074
Definition: nucleus.c:42
struct m0_dirent * ent
Definition: dir.c:1029
M0_INTERNAL void m0_chan_fini_lock(struct m0_chan *chan)
Definition: chan.c:112
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
uint64_t h_bucket_nr
Definition: hash.h:178
static void rm_lock_req_init(struct m0_clink *clink, struct m0_rm_owner *owner, struct m0_rm_lock_req *req, enum m0_rm_rwlock_req_type rw_type)
Definition: obj_lock.c:279
M0_INTERNAL void m0_rm_credit_get(struct m0_rm_incoming *in)
Definition: rm.c:1758
#define FID_F
Definition: fid.h:75