Motr  M0
update.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 
30 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DTM
31 
32 #include "lib/trace.h"
33 #include "lib/assert.h"
34 #include "lib/errno.h" /* EPROTO */
35 #include "lib/misc.h" /* M0_IN */
36 #include "motr/magic.h"
37 
38 #include "fop/fop.h"
39 
40 #include "dtm/dtm_internal.h"
41 #include "dtm/nucleus.h"
42 #include "dtm/operation.h"
43 #include "dtm/history.h"
44 #include "dtm/remote.h"
45 #include "dtm/update.h"
46 
47 M0_INTERNAL void m0_dtm_update_init(struct m0_dtm_update *update,
48  struct m0_dtm_history *history,
49  struct m0_dtm_oper *oper,
50  const struct m0_dtm_update_data *data)
51 {
52  M0_PRE(ergo(data->da_label != 0,
53  m0_tl_forall(oper, upd, &oper->oprt_op.op_ups,
54  upd->upd_up.up_state == M0_DOS_LIMBO &&
55  upd->upd_label != data->da_label)));
56  M0_PRE(!(history->h_hi.hi_flags & M0_DHF_CLOSED));
58  m0_dtm_up_init(&update->upd_up, &history->h_hi, &oper->oprt_op,
59  data->da_rule, data->da_ver, data->da_orig_ver);
60  update->upd_label = data->da_label;
63 }
64 
65 M0_INTERNAL bool m0_dtm_update_invariant(const struct m0_dtm_update *update)
66 {
67  const struct m0_dtm_up *up = &update->upd_up;
68  enum m0_dtm_state state = up->up_state;
69  const struct m0_dtm_update_comm *comm = &update->upd_comm;
70  enum m0_dtm_update_comm_state cstate = comm->uc_state;
71  const struct m0_fop *body = comm->uc_body;
72  struct m0_dtm_remote *rem = UPDATE_REM(update);
73 
74  return
75  m0_dtm_up_invariant(up) &&
76  _0C(M0_IN(cstate, (M0_DUX_NEW,
78  _0C(ergo(rem == NULL, body == NULL)) &&
79  _0C(ergo(body == NULL, cstate == M0_DUX_NEW)) &&
80  _0C(ergo(state > M0_DOS_INPROGRESS,
81  body == NULL || cstate > M0_DUX_NEW)) &&
82  _0C(ergo(cstate == M0_DUX_REPLIED,
83  body->f_item.ri_reply != NULL)) &&
84  _0C(ergo(rem != NULL, comm->uc_instance <= rem->re_instance));
85 }
86 
87 M0_INTERNAL bool m0_dtm_update_is_user(const struct m0_dtm_update *update)
88 {
90  return update->upd_label >= M0_DTM_USER_UPDATE_BASE;
91 }
92 
93 M0_INTERNAL void m0_dtm_update_pack(const struct m0_dtm_update *update,
94  struct m0_dtm_update_descr *updd)
95 {
96  const struct m0_dtm_up *up = &update->upd_up;
97  struct m0_dtm_history *history = UPDATE_HISTORY(update);
98 
100  M0_PRE(update->upd_up.up_state >= M0_DOS_FUTURE);
101  *updd = (struct m0_dtm_update_descr) {
102  .udd_utype = update->upd_ops->updo_type->updtt_id,
103  .udd_data = {
104  .da_label = update->upd_label,
105  .da_rule = up->up_rule,
106  .da_ver = up->up_ver,
107  .da_orig_ver = up->up_orig_ver
108  }
109  };
110  m0_dtm_history_pack(history, &updd->udd_id);
111 }
112 
113 M0_INTERNAL void m0_dtm_update_unpack(struct m0_dtm_update *update,
114  const struct m0_dtm_update_descr *updd)
115 {
116  struct m0_dtm_up *up = &update->upd_up;
117 
118  M0_PRE(update->upd_label == updd->udd_data.da_label);
119  M0_PRE(M0_IN(update->upd_up.up_state, (M0_DOS_INPROGRESS,
120  M0_DOS_PREPARE)));
121  M0_PRE(UPDATE_HISTORY(update)->h_ops->hio_type->hit_id ==
122  updd->udd_id.hid_htype);
123  M0_PRE(m0_dtm_update_matches_descr(update, updd));
124 
125  up->up_rule = updd->udd_data.da_rule;
126  up->up_ver = updd->udd_data.da_ver;
127  up->up_orig_ver = updd->udd_data.da_orig_ver;
128 
130 }
131 
132 M0_INTERNAL int m0_dtm_update_build(struct m0_dtm_update *update,
133  struct m0_dtm_oper *oper,
134  const struct m0_dtm_update_descr *updd)
135 {
136  struct m0_dtm_history *history;
137  struct m0_dtm *dtm = nu_dtm(oper->oprt_op.op_nu);
138  int result;
139 
140  result = m0_dtm_history_unpack(dtm, &updd->udd_id, &history);
141  if (result == 0) {
142  if (m0_tl_exists(oper, scan, &oper->oprt_op.op_ups,
143  scan->upd_label == updd->udd_data.da_label))
144  return M0_ERR_INFO(-EPROTO, "%i", updd->udd_data.da_label);
145  m0_dtm_update_init(update, history, oper, &updd->udd_data);
146  result = history->h_ops->hio_update(history, updd->udd_utype,
147  update);
148  }
149  M0_POST(ergo(result == 0, m0_dtm_update_invariant(update)));
150  return result;
151 }
152 
153 M0_INTERNAL bool
155  const struct m0_dtm_update_descr *updd)
156 {
157  const struct m0_dtm_up *up = &update->upd_up;
158 
159  return
160  up->up_rule == updd->udd_data.da_rule &&
161  M0_IN(up->up_ver, (0, updd->udd_data.da_ver)) &&
162  M0_IN(up->up_orig_ver, (0, updd->udd_data.da_orig_ver));
163 }
164 
165 M0_INTERNAL bool
167  const struct m0_dtm_update_descr *updd)
168 {
169  const struct m0_dtm_up *up = &update->upd_up;
170 
171  return
172  up->up_rule == updd->udd_data.da_rule &&
173  M0_IN(updd->udd_data.da_ver, (0, up->up_ver)) &&
174  M0_IN(updd->udd_data.da_orig_ver, (0, up->up_orig_ver));
175 }
176 
177 M0_INTERNAL void m0_dtm_update_list_init(struct m0_tl *list)
178 {
179  oper_tlist_init(list);
180 }
181 
182 M0_INTERNAL void m0_dtm_update_list_fini(struct m0_tl *list)
183 {
184  struct m0_dtm_update *leftover;
185 
186  m0_tl_for(oper, list, leftover) {
187  oper_tlist_del(leftover);
188  } m0_tl_endfor;
189  oper_tlist_fini(list);
190 }
191 
192 M0_INTERNAL void m0_dtm_update_reint(struct m0_dtm_update *update)
193 {
195  M0_PRE(update->upd_comm.uc_body != NULL);
196  M0_PRE(update->upd_comm.uc_state == M0_DUX_NEW);
197 
198  history_lock(UPDATE_HISTORY(update));
199  update_reint(update);
201 }
202 
204 
205 M0_INTERNAL void m0_dtm_comm_set(struct m0_dtm_update *update,
206  struct m0_fop *fop)
207 {
208  struct m0_dtm_update_comm *comm = &update->upd_comm;
209 
211  M0_PRE(comm->uc_state == M0_DUX_NEW);
212  M0_PRE(comm->uc_body == NULL);
213  M0_PRE(fop->f_item.ri_ops == NULL);
214  M0_PRE(fop->f_opaque == NULL);
215 
216  comm->uc_body = fop;
218  fop->f_opaque = update;
219 }
220 
221 M0_INTERNAL void m0_dtm_update_link(struct m0_tl *list,
222  struct m0_dtm_update *update, uint32_t nr)
223 {
224  while (nr-- != 0)
225  oper_tlink_init_at(update++, list);
226 }
227 
228 M0_INTERNAL struct m0_dtm_update *up_update(struct m0_dtm_up *up)
229 {
230  return up != NULL ?
231  container_of(up, struct m0_dtm_update, upd_up) : NULL;
232 }
233 
234 M0_INTERNAL bool update_is_earlier(struct m0_dtm_update *update0,
235  struct m0_dtm_update *update1)
236 {
237  return up_is_earlier(UPDATE_UP(update0), UPDATE_UP(update1));
238 }
239 
240 M0_INTERNAL void update_reint(struct m0_dtm_update *update)
241 {
242  struct m0_dtm_update_comm *comm = &update->upd_comm;
243  struct m0_dtm_history *history = UPDATE_HISTORY(update);
244  struct m0_dtm_remote *rem = history->h_rem;
245 
247 
248  if (comm->uc_body == NULL)
249  return;
250  if (comm->uc_state == M0_DUX_NEW)
251  rem->re_ops->reo_send(rem, update);
252  else if (comm->uc_state == M0_DUX_INFLIGHT &&
253  comm->uc_instance == history->h_rem->re_instance)
254  ;
255  else
256  rem->re_ops->reo_resend(rem, update);
257 
258  comm->uc_state = M0_DUX_INFLIGHT;
259  comm->uc_instance = history->h_rem->re_instance;
260 }
261 
262 static void dtm_update_replied(struct m0_rpc_item *item)
263 {
264  struct m0_fop *fop = m0_rpc_item_to_fop(item);
265  struct m0_dtm_update *update = fop->f_opaque;
266  struct m0_dtm_update_comm *comm = &update->upd_comm;
267 
269  M0_PRE(fop == comm->uc_body);
270  M0_PRE(comm->uc_state == M0_DUX_INFLIGHT);
271 
272  /* XXX TODO Handle rpc errors. */
273 
274  if (!(comm->uc_flags & M0_DUCF_REPLIED_CALLED)) {
275  if (update->upd_ops->updto_replied != NULL)
276  update->upd_ops->updto_replied(update);
278  }
279 }
280 
281 static const struct m0_rpc_item_ops dtm_update_item_ops = {
283 };
284 
285 M0_TL_DESCR_DEFINE(history, "dtm history updates", M0_INTERNAL,
286  struct m0_dtm_update,
287  upd_up.up_hi_linkage, upd_up.up_magix,
289 M0_TL_DEFINE(history, M0_INTERNAL, struct m0_dtm_update);
290 
291 M0_TL_DESCR_DEFINE(oper, "dtm operation updates", M0_INTERNAL,
292  struct m0_dtm_update,
293  upd_up.up_op_linkage, upd_up.up_magix,
295 M0_TL_DEFINE(oper, M0_INTERNAL, struct m0_dtm_update);
296 
297 M0_INTERNAL void update_print_internal(const struct m0_dtm_update *update,
298  bool history)
299 {
300  static const char state_name[] = "LFpIVPS??????????????????";
301  static const char rule_name[] = "ISNA?????????????????????";
302  char buf[100];
303 
305  M0_LOG(M0_FATAL, "\tupdate: %s@%p/%p: %s",
306  update->upd_ops->updo_type->updtt_name,
307  update, update->upd_up.up_op, history ? &buf[0] : "");
308  M0_LOG(M0_FATAL, "\t\tstate: %c label: %lx "
309  "rule: %c ver: %lu orig: %lu",
310  state_name[update->upd_up.up_state],
311  (unsigned long)update->upd_label,
312  rule_name[update->upd_up.up_rule],
313  (unsigned long)update->upd_up.up_ver,
314  (unsigned long)update->upd_up.up_orig_ver);
315 }
316 
317 M0_INTERNAL void update_print(const struct m0_dtm_update *update)
318 {
319  update_print_internal(update, true);
320 }
321 
322 #undef M0_TRACE_SUBSYSTEM
323 
326 /*
327  * Local variables:
328  * c-indentation-style: "K&R"
329  * c-basic-offset: 8
330  * tab-width: 8
331  * fill-column: 80
332  * scroll-step: 1
333  * End:
334  */
335 /*
336  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
337  */
M0_INTERNAL void history_print_header(const struct m0_dtm_history *history, char *buf)
Definition: history.c:425
M0_INTERNAL int m0_dtm_update_build(struct m0_dtm_update *update, struct m0_dtm_oper *oper, const struct m0_dtm_update_descr *updd)
Definition: update.c:132
struct m0_dtm_up upd_up
Definition: update.h:72
struct m0_dtm_history_id udd_id
Definition: update.h:119
static size_t nr
Definition: dump.c:1505
#define M0_PRE(cond)
M0_INTERNAL void update_print_internal(const struct m0_dtm_update *update, bool history)
Definition: update.c:297
struct m0_dtm_update_comm upd_comm
Definition: update.h:75
enum m0_dtm_state up_state
Definition: nucleus.h:94
struct m0_dtm_update_data udd_data
Definition: update.h:118
struct m0_fop * uc_body
Definition: update.h:68
static struct m0_list list
Definition: list.c:144
m0_dtm_ver_t up_orig_ver
Definition: nucleus.h:97
M0_INTERNAL void m0_dtm_update_unpack(struct m0_dtm_update *update, const struct m0_dtm_update_descr *updd)
Definition: update.c:113
struct m0_dtm_nu * op_nu
Definition: nucleus.h:106
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
uint8_t hid_htype
Definition: update.h:114
const char * updtt_name
Definition: update.h:92
uint64_t hi_flags
Definition: nucleus.h:65
struct m0_dtm_remote * h_rem
Definition: history.h:59
#define M0_LOG(level,...)
Definition: trace.h:167
M0_INTERNAL bool m0_dtm_update_invariant(const struct m0_dtm_update *update)
Definition: update.c:65
#define UPDATE_UP(update)
Definition: dtm_internal.h:97
M0_INTERNAL bool m0_dtm_up_invariant(const struct m0_dtm_up *up)
Definition: nucleus.c:448
uint32_t da_label
Definition: update.h:98
void(* reo_send)(struct m0_dtm_remote *rem, struct m0_dtm_update *update)
Definition: remote.h:70
void(* reo_resend)(struct m0_dtm_remote *rem, struct m0_dtm_update *update)
Definition: remote.h:72
struct m0_bufvec data
Definition: di.c:40
struct m0_dtm_op oprt_op
Definition: operation.h:48
M0_INTERNAL bool m0_dtm_update_is_user(const struct m0_dtm_update *update)
Definition: update.c:87
M0_INTERNAL struct m0_dtm * nu_dtm(struct m0_dtm_nu *nu)
Definition: dtm.c:154
struct m0_dtm_hi h_hi
Definition: history.h:56
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL struct m0_dtm_update * up_update(struct m0_dtm_up *up)
Definition: update.c:228
static struct m0_rpc_item * item
Definition: item.c:56
m0_dtm_ver_t up_ver
Definition: nucleus.h:96
const struct m0_dtm_update_ops * upd_ops
Definition: update.h:74
uint32_t upd_label
Definition: update.h:73
Definition: sock.c:887
struct m0_dtm_op * up_op
Definition: nucleus.h:100
struct m0_fop_cob * body
Definition: dir.c:1436
#define m0_tl_endfor
Definition: tlist.h:700
int(* hio_update)(struct m0_dtm_history *history, uint8_t id, struct m0_dtm_update *update)
Definition: history.h:83
M0_INTERNAL void history_lock(const struct m0_dtm_history *history)
Definition: history.c:288
M0_INTERNAL void m0_dtm_update_link(struct m0_tl *list, struct m0_dtm_update *update, uint32_t nr)
Definition: update.c:221
M0_INTERNAL void update_print(const struct m0_dtm_update *update)
Definition: update.c:317
M0_INTERNAL bool update_is_earlier(struct m0_dtm_update *update0, struct m0_dtm_update *update1)
Definition: update.c:234
static void upd(void)
Definition: client_ut.c:2974
M0_TL_DEFINE(history, M0_INTERNAL, struct m0_dtm_update)
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
#define UPDATE_HISTORY(update)
Definition: dtm_internal.h:104
uint64_t uc_instance
Definition: update.h:67
M0_TL_DESCR_DEFINE(history, "dtm history updates", M0_INTERNAL, struct m0_dtm_update, upd_up.up_hi_linkage, upd_up.up_magix, M0_DTM_UP_MAGIX, M0_DTM_HI_MAGIX)
M0_INTERNAL int m0_dtm_history_unpack(struct m0_dtm *dtm, const struct m0_dtm_history_id *id, struct m0_dtm_history **out)
Definition: history.c:248
M0_INTERNAL bool m0_dtm_descr_matches_update(const struct m0_dtm_update *update, const struct m0_dtm_update_descr *updd)
Definition: update.c:166
Definition: tlist.h:251
M0_INTERNAL void m0_dtm_comm_set(struct m0_dtm_update *update, struct m0_fop *fop)
Definition: update.c:205
static void dtm_update_replied(struct m0_rpc_item *item)
Definition: update.c:262
M0_INTERNAL void update_reint(struct m0_dtm_update *update)
Definition: update.c:240
void * f_opaque
Definition: fop.h:84
#define M0_POST(cond)
struct m0_tl op_ups
Definition: nucleus.h:107
const struct m0_dtm_update_type * updo_type
Definition: update.h:87
static const struct m0_rpc_item_ops dtm_update_item_ops
Definition: update.c:203
uint64_t uc_flags
Definition: update.h:66
enum m0_dtm_up_rule up_rule
Definition: nucleus.h:95
M0_INTERNAL bool up_is_earlier(struct m0_dtm_up *up0, struct m0_dtm_up *up1)
Definition: nucleus.c:410
uint64_t da_ver
Definition: update.h:96
#define UPDATE_REM(update)
Definition: dtm_internal.h:105
M0_INTERNAL void m0_dtm_history_pack(const struct m0_dtm_history *history, struct m0_dtm_history_id *id)
Definition: history.c:239
void(* rio_replied)(struct m0_rpc_item *item)
Definition: item.h:300
M0_INTERNAL void history_unlock(const struct m0_dtm_history *history)
Definition: history.c:293
void(* updto_replied)(struct m0_dtm_update *updt)
Definition: update.h:86
enum m0_dtm_update_comm_state uc_state
Definition: update.h:65
M0_INTERNAL void m0_dtm_update_init(struct m0_dtm_update *update, struct m0_dtm_history *history, struct m0_dtm_oper *oper, const struct m0_dtm_update_data *data)
Definition: update.c:47
M0_INTERNAL void m0_dtm_update_reint(struct m0_dtm_update *update)
Definition: update.c:192
const struct m0_rpc_item_ops * ri_ops
Definition: item.h:149
M0_INTERNAL bool m0_dtm_update_matches_descr(const struct m0_dtm_update *update, const struct m0_dtm_update_descr *updd)
Definition: update.c:154
uint8_t da_rule
Definition: update.h:99
M0_INTERNAL void m0_dtm_update_list_fini(struct m0_tl *list)
Definition: update.c:182
#define _0C(exp)
Definition: assert.h:311
uint64_t re_instance
Definition: remote.h:56
M0_INTERNAL void m0_dtm_update_pack(const struct m0_dtm_update *update, struct m0_dtm_update_descr *updd)
Definition: update.c:93
const struct m0_dtm_remote_ops * re_ops
Definition: remote.h:57
static struct m0_fop * fop
Definition: item.c:57
struct m0_fop * m0_rpc_item_to_fop(const struct m0_rpc_item *item)
Definition: fop.c:346
Definition: dtm.h:529
M0_INTERNAL void m0_dtm_up_init(struct m0_dtm_up *up, struct m0_dtm_hi *hi, struct m0_dtm_op *op, enum m0_dtm_up_rule rule, m0_dtm_ver_t ver, m0_dtm_ver_t orig_ver)
Definition: nucleus.c:286
M0_INTERNAL void m0_dtm_update_list_init(struct m0_tl *list)
Definition: update.c:177
uint8_t updtt_id
Definition: update.h:91
m0_dtm_update_comm_state
Definition: update.h:54
uint8_t udd_utype
Definition: update.h:120
static int scan(struct scanner *s)
Definition: beck.c:963
uint64_t da_orig_ver
Definition: update.h:97
M0_INTERNAL bool m0_dtm_oper_invariant(const struct m0_dtm_oper *oper)
Definition: operation.c:69
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
struct m0_rpc_item f_item
Definition: fop.h:83
m0_dtm_state
Definition: nucleus.h:52
#define m0_tl_exists(name, var, head,...)
Definition: tlist.h:774
Definition: fop.h:79
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
const struct m0_dtm_history_ops * h_ops
Definition: history.h:65