Motr  M0
log.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_BE
24 #include "lib/trace.h"
25 
26 #include "be/log.h"
27 #include "be/fmt.h"
28 #include "be/op.h" /* m0_be_op */
29 #include "be/ha.h" /* m0_be_io_err_send */
30 
31 #include "lib/arith.h" /* m0_align */
32 #include "lib/errno.h" /* ENOENT */
33 #include "lib/memory.h"
34 #include "lib/tlist.h"
35 #include "lib/ext.h" /* M0_EXT */
36 #include "motr/magic.h"
37 #include "module/instance.h" /* m0_get */
38 
47 enum {
48  LGR_NEW = 1,
54 };
55 
56 static void be_log_header_update(struct m0_be_log *log);
57 static int be_log_header_write(struct m0_be_log *log,
58  struct m0_be_fmt_log_header *log_hdr);
59 
60 /* m0_be_log::lg_records */
61 M0_TL_DESCR_DEFINE(record, "be log records", static, struct m0_be_log_record,
62  lgr_linkage, lgr_magic, M0_BE_LOG_RECORD_MAGIC,
64 M0_TL_DEFINE(record, static, struct m0_be_log_record);
65 
66 static struct m0_be_log *be_log_module2log(struct m0_module *module)
67 {
68  /* XXX bob_of */
69  return container_of(module, struct m0_be_log, lg_module);
70 }
71 
72 static int be_log_level_enter(struct m0_module *module)
73 {
74  struct m0_be_recovery *rvr;
75  struct m0_be_log *log = be_log_module2log(module);
76  int level = module->m_cur + 1;
77  int rc;
78 
79  switch (level) {
81  log->lg_current = 0;
82  log->lg_discarded = 0;
83  log->lg_reserved = 0;
84  log->lg_free = 0;
85  log->lg_prev_record = 0;
86  log->lg_prev_record_size = 0;
87  log->lg_unplaced_exists = false;
89  record_tlist_init(&log->lg_records);
92  return 0;
94  return m0_be_log_sched_init(&log->lg_sched,
95  &log->lg_cfg.lc_sched_cfg);
97  if (log->lg_create_mode) {
99  m0_be_fmt_log_header_size_max(NULL);
101  &log->lg_cfg.lc_store_cfg);
102  } else {
104  &log->lg_cfg.lc_store_cfg);
105  }
106  return rc;
108  return m0_be_fmt_log_header_init(&log->lg_header, NULL);
110  if (log->lg_create_mode) {
111  m0_be_log_header__set(&log->lg_header, 0, 0, 0);
112  rc = be_log_header_write(log, &log->lg_header);
113  } else {
114  rc = m0_be_log_header_read(log, &log->lg_header);
115  }
116  return rc;
118  if (!log->lg_create_mode) {
119  log->lg_cfg.lc_recovery_cfg.brc_log = log;
121  &log->lg_cfg.lc_recovery_cfg);
122  if (log->lg_cfg.lc_skip_recovery) {
123  M0_LOG(M0_WARN, "recovery is skipped");
124  return 0;
125  } else {
126  return m0_be_recovery_run(&log->lg_recovery);
127  }
128  }
129  return 0;
131  if (!log->lg_create_mode) {
132  rvr = &log->lg_recovery;
133  log->lg_current = rvr->brec_current;
134  log->lg_discarded = rvr->brec_discarded;
137  }
139  (log->lg_current - log->lg_discarded);
140  M0_LOG(M0_DEBUG, "log="BL_F, BL_P(log));
141  log->lg_external_lock = log->lg_cfg.lc_lock;
143  return 0;
144  default:
145  return M0_ERR(-ENOSYS);
146  }
147 }
148 
149 static void be_log_level_leave(struct m0_module *module)
150 {
151  struct m0_be_log *log = be_log_module2log(module);
152  int level = module->m_cur;
153  int rc;
154 
155  switch (level) {
159  record_tlist_fini(&log->lg_records);
161  break;
164  break;
166  if (log->lg_destroy_mode)
168  else
170  break;
172  m0_be_fmt_log_header_fini(&log->lg_header);
173  break;
175  if (!log->lg_destroy_mode) {
177  rc = be_log_header_write(log, &log->lg_header);
178  M0_ASSERT_INFO(rc == 0, "rc=%d", rc); /* XXX */
179  }
180  break;
182  if (!log->lg_create_mode)
184  break;
186  break;
187  default:
188  M0_IMPOSSIBLE("Unexpected m0_module level");
189  }
190 }
191 
192 static const struct m0_modlev be_log_levels[] = {
194  .ml_name = "M0_BE_LOG_LEVEL_INIT",
195  .ml_enter = be_log_level_enter,
196  .ml_leave = be_log_level_leave,
197  },
199  .ml_name = "M0_BE_LOG_LEVEL_LOG_SCHED",
200  .ml_enter = be_log_level_enter,
201  .ml_leave = be_log_level_leave,
202  },
204  .ml_name = "M0_BE_LOG_LEVEL_LOG_STORE",
205  .ml_enter = be_log_level_enter,
206  .ml_leave = be_log_level_leave,
207  },
209  .ml_name = "M0_BE_LOG_LEVEL_HEADER_PREINIT",
210  .ml_enter = be_log_level_enter,
211  .ml_leave = be_log_level_leave,
212  },
214  .ml_name = "M0_BE_LOG_LEVEL_HEADER",
215  .ml_enter = be_log_level_enter,
216  .ml_leave = be_log_level_leave,
217  },
219  .ml_name = "M0_BE_LOG_LEVEL_RECOVERY",
220  .ml_enter = be_log_level_enter,
221  .ml_leave = be_log_level_leave,
222  },
224  .ml_name = "M0_BE_LOG_LEVEL_ASSIGNS",
225  .ml_enter = be_log_level_enter,
226  .ml_leave = be_log_level_leave,
227  },
229  .ml_name = "fully initialized",
230  },
231 };
232 
233 M0_INTERNAL void m0_be_log_module_setup(struct m0_be_log *log,
234  struct m0_be_log_cfg *lg_cfg,
235  bool create_mode)
236 {
237  log->lg_cfg = *lg_cfg;
238  log->lg_create_mode = create_mode;
239 
240  m0_module_setup(&log->lg_module, "m0_be_log",
242 }
243 
244 static void be_log_module_fini(struct m0_be_log *log,
245  bool destroy_mode)
246 {
247  M0_PRE(log->lg_reserved == 0);
249  log->lg_current == log->lg_discarded));
251  log->lg_discarded == log->lg_unplaced_pos));
252 
253  log->lg_destroy_mode = destroy_mode;
255 }
256 
257 static int be_log_module_init(struct m0_be_log *log,
258  struct m0_be_log_cfg *log_cfg,
259  bool create_mode)
260 {
261  int rc;
262 
263  m0_be_log_module_setup(log, log_cfg, create_mode);
265  if (rc != 0)
266  be_log_module_fini(log, create_mode);
267  return rc;
268 }
269 
270 M0_INTERNAL bool m0_be_log__invariant(struct m0_be_log *log)
271 {
272  return _0C(m0_mutex_is_locked(log->lg_external_lock)) &&
273  _0C(log->lg_discarded <= log->lg_current) &&
275  log->lg_discarded <= log->lg_unplaced_pos)) &&
276  _0C(log->lg_current - log->lg_discarded +
277  log->lg_reserved + log->lg_free ==
279 }
280 
281 M0_INTERNAL int m0_be_log_open(struct m0_be_log *log,
282  struct m0_be_log_cfg *log_cfg)
283 {
284  return be_log_module_init(log, log_cfg, false);
285 }
286 
287 M0_INTERNAL void m0_be_log_close(struct m0_be_log *log)
288 {
289  be_log_module_fini(log, false);
290 }
291 
292 M0_INTERNAL int m0_be_log_create(struct m0_be_log *log,
293  struct m0_be_log_cfg *log_cfg)
294 {
295  return be_log_module_init(log, log_cfg, true);
296 }
297 
298 M0_INTERNAL void m0_be_log_destroy(struct m0_be_log *log)
299 {
300  be_log_module_fini(log, true);
301 }
302 
303 static void be_log_header_io(struct m0_be_log *log,
304  enum m0_be_log_store_io_type io_type,
305  struct m0_be_op *op)
306 {
307  struct m0_be_log_io *lio;
308  struct m0_be_op *io_op;
309  unsigned iter;
310 
312 
313  lio = m0_be_log_store_rbuf_io_first(&log->lg_store, io_type,
314  &io_op, &iter);
315  /* log should have at least one header */
316  do {
317  /*
318  * It is safe to add io_op to op set here.
319  * log_sched can't finish I/O when it's locked.
320  */
321  m0_be_op_set_add(op, io_op);
322  m0_be_log_sched_add(&log->lg_sched, lio, io_op);
323  lio = m0_be_log_store_rbuf_io_next(&log->lg_store, io_type,
324  &io_op, &iter);
325  } while (lio != NULL);
326 }
327 
328 static void be_log_header_io_sync(struct m0_be_log *log,
329  enum m0_be_log_store_io_type io_type)
330 {
331  struct m0_be_op *op;
332 
333  M0_PRE(M0_IN(io_type, (M0_BE_LOG_STORE_IO_WRITE,
335  op = io_type == M0_BE_LOG_STORE_IO_WRITE ? &log->lg_header_write_op :
336  &log->lg_header_read_op;
339  be_log_header_io(log, io_type, op);
341  m0_be_op_wait(op);
342 }
343 
345 {
346  struct m0_be_fmt_log_record_header_cfg cfg = {
348  };
349 
351 }
352 
354 {
355  return m0_be_fmt_log_record_footer_size_max(NULL);
356 }
357 
359  m0_bcount_t *lio_size,
360  int lio_nr)
361 {
362  m0_bcount_t size = 0;
363  m0_bcount_t part;
364  uint64_t alignment = 1ULL << m0_be_log_bshift(log);
365  int i;
366 
367  M0_PRE(lio_nr > 0);
368 
369  for (i = 0; i < lio_nr; ++i) {
370  part = lio_size[i];
371  if (i == 0)
372  part += be_log_record_header_size();
373  if (i == lio_nr - 1)
374  part += be_log_record_footer_size();
375  size += m0_align(part, alignment);
376  }
377  return size;
378 }
379 
380 static void be_log_record_io_done_cb(struct m0_be_op *op, void *param)
381 {
382  struct m0_be_log_record *record = param;
383  struct m0_be_log *log = record->lgr_log;
384 
386  record->lgr_state = LGR_DONE;
388 }
389 
391  struct m0_be_log *log)
392 {
393  int i;
394 
395  record->lgr_log = log;
396  record->lgr_size = 0;
397  record->lgr_state = LGR_NEW;
398  record->lgr_need_discard = false;
399 
400  record->lgr_io_nr = 0;
401  for (i = 0; i < M0_BE_LOG_RECORD_IO_NR_MAX; ++i) {
402  record->lgr_io[i] = NULL;
403  record->lgr_op[i] = NULL;
404  }
405  m0_be_op_init(&record->lgr_record_op);
408 }
409 
411 {
412  int i;
413 
414  M0_PRE(M0_IN(record->lgr_state, (LGR_NEW, LGR_DONE)));
415 
416  if (record->lgr_need_discard && record->lgr_state == LGR_DONE)
417  record_tlink_del_fini(record);
418 
419  m0_be_op_fini(&record->lgr_record_op);
420  for (i = 0; i < record->lgr_io_nr; ++i) {
421  m0_be_op_fini(record->lgr_op[i]);
422  m0_free(record->lgr_op[i]);
423  m0_be_log_io_deallocate(record->lgr_io[i]);
424  m0_be_log_io_fini(record->lgr_io[i]);
425  m0_free(record->lgr_io[i]);
426  }
427  record->lgr_io_nr = 0;
428 
429  record->lgr_state = LGR_FINI;
430  record->lgr_log = NULL;
431 }
432 
434 {
435  int i;
436 
437  M0_PRE(M0_IN(record->lgr_state, (LGR_NEW, LGR_DONE)));
438 
439  /*
440  * With delayed discard records can't be removed from the list
441  * in m0_be_log_record_discard().
442  */
443  if (record->lgr_need_discard && record->lgr_state == LGR_DONE) {
444  /*
445  * XXX the lock shouldn't be taken here. Usually it's engine
446  * lock and it should be taken somewhere above in the call
447  * stack.
448  */
449  m0_mutex_lock(record->lgr_log->lg_external_lock);
450  record_tlink_del_fini(record);
451  m0_mutex_unlock(record->lgr_log->lg_external_lock);
452  }
454  m0_be_fmt_log_record_footer_reset(&record->lgr_footer);
455  m0_be_op_reset(&record->lgr_record_op);
456  for (i = 0; i < record->lgr_io_nr; ++i) {
457  m0_be_log_io_reset(record->lgr_io[i]);
458  m0_be_op_reset(record->lgr_op[i]);
459  }
460  record->lgr_state = LGR_NEW;
461  record->lgr_need_discard = false;
462  record->lgr_write_header = false;
463  record->lgr_log_header_discarded = M0_BINDEX_MAX;
464 }
465 
466 M0_INTERNAL void
468  struct m0_be_log_record_iter *iter,
469  bool need_discard)
470 {
472  struct m0_be_log *log = record->lgr_log;
473  int i;
474 
475  M0_ENTRY("iter->header="BFLRH_F, BFLRH_P(header));
476  M0_PRE(header->lrh_io_size.lrhs_nr == record->lgr_io_nr);
477 
478  record->lgr_log_header_discarded = iter->lri_log_header_discarded;
479  record->lgr_last_discarded = header->lrh_discarded;
480  record->lgr_position = header->lrh_pos;
481  record->lgr_prev_pos = header->lrh_prev_pos;
482  record->lgr_prev_size = header->lrh_prev_size;
483  record->lgr_size = header->lrh_size;
484  record->lgr_state = LGR_USED;
485  record->lgr_need_discard = need_discard;
486 
487  for (i = 0; i < header->lrh_io_size.lrhs_nr; ++i) {
489  header->lrh_io_size.lrhs_size[i]);
490  }
491  if (need_discard)
492  record_tlink_init_at_tail(record, &log->lg_records);
493  M0_LEAVE("record="BLR_F, BLR_P(record));
494 }
495 
497  struct m0_ext *ext)
498 {
499  M0_ASSERT(M0_IN(record->lgr_state,
501  *ext = M0_EXT(record->lgr_position,
502  record->lgr_position + record->lgr_size);
503 }
504 
506 {
507  struct m0_be_log *log = record->lgr_log;
508 
509  M0_ENTRY("record="BLR_F" log="BL_F, BLR_P(record), BL_P(log));
510  M0_PRE(record->lgr_need_discard);
513 
514  if (!log->lg_unplaced_exists ||
515  record->lgr_position < log->lg_unplaced_pos) {
516  log->lg_unplaced_exists = true;
517  log->lg_unplaced_pos = record->lgr_position;
518  log->lg_unplaced_size = record->lgr_size;
519  }
521 }
522 
523 M0_INTERNAL void m0_be_log_record_discard(struct m0_be_log *log,
525 {
526  M0_ENTRY("log="BL_F" size=%"PRIu64, BL_P(log), size);
529  M0_PRE(log->lg_discarded + size <= log->lg_current);
531  log->lg_discarded == log->lg_unplaced_pos ||
532  log->lg_discarded + size <= log->lg_unplaced_pos));
533 
534  /*
535  * User must guarantee discarding of records in the same order as
536  * they are prepared for I/O.
537  */
538 
539  if (log->lg_unplaced_exists &&
540  log->lg_discarded == log->lg_unplaced_pos) {
541  size = 0;
542  }
543  log->lg_free += size;
544  log->lg_discarded += size;
545  M0_LOG(M0_DEBUG, "log="BL_F" size=%"PRIu64, BL_P(log), size);
546 
548 
549  log->lg_got_space_cb(log);
550 }
551 
552 static void be_log_io_credit(struct m0_be_log *log,
553  struct m0_be_io_credit *accum)
554 {
555  m0_be_log_store_io_credit(&log->lg_store, accum);
556 }
557 
559  m0_bcount_t size_max)
560 {
561  struct m0_be_io_credit iocred;
562  struct m0_be_log_io *lio;
563  struct m0_be_log *log = record->lgr_log;
564  uint32_t bshift = m0_be_log_bshift(log);
565  int index = record->lgr_io_nr;
566  int rc = 0;
567 
568  M0_ENTRY("record=%p index=%d size_max=%"PRIu64,
569  record, index, size_max);
570 
572  return -ERANGE;
573 
574  /* We don't know which I/O is the last, therefore reserve footer size to
575  * all I/O.
576  */
577  size_max += index == 0 ? be_log_record_header_size() :
579  size_max = m0_align(size_max, 1ULL << bshift);
580  iocred = M0_BE_IO_CREDIT(1, size_max, 1);
581  be_log_io_credit(log, &iocred);
582 
583  M0_ALLOC_PTR(record->lgr_io[index]);
584  M0_ALLOC_PTR(record->lgr_op[index]);
585  if (record->lgr_io[index] == NULL || record->lgr_op[index] == NULL)
586  rc = -ENOMEM;
587 
588  lio = record->lgr_io[index];
589  rc = rc ?: m0_be_log_io_init(lio);
590  if (rc == 0) {
591  rc = m0_be_log_io_allocate(lio, &iocred, bshift);
592  if (rc != 0)
593  m0_be_log_io_fini(lio);
594  }
595 
596  if (rc == 0) {
597  m0_be_op_init(record->lgr_op[index]);
598  lio->lio_record = record;
599  ++record->lgr_io_nr;
600  } else {
601  m0_free(record->lgr_io[index]);
602  m0_free(record->lgr_op[index]);
603  }
604  return M0_RC(rc);
605 }
606 
608 {
609  struct m0_be_fmt_log_record_header_cfg cfg = {
611  };
612  return m0_be_fmt_log_record_header_init(hdr, &cfg);
613 }
614 
616 {
617  int rc;
618 
619  rc = be_log_record_header_init(&record->lgr_header);
620  if (rc != 0)
621  return rc;
622 
623  rc = m0_be_fmt_log_record_footer_init(&record->lgr_footer, NULL);
624  if (rc != 0)
626 
627  return rc;
628 }
629 
631 {
633  m0_be_fmt_log_record_footer_fini(&record->lgr_footer);
634 }
635 
637  int index,
639 {
640  struct m0_be_log_io *lio;
641 
642  M0_PRE(index < record->lgr_io_nr);
643 
644  lio = record->lgr_io[index];
645  lio->lio_buf_size = size;
646  lio->lio_buf_addr = lio->lio_buf.b_addr;
647  if (index == 0) {
648  /*
649  * This is first lio, so we need to reserve a window for
650  * log record header.
651  */
652  lio->lio_buf_addr = (char *)lio->lio_buf_addr +
654  }
656  &lio->lio_buf_size);
657 }
658 
659 M0_INTERNAL void
662  m0_bcount_t size_reserved)
663 {
664  struct m0_bufvec_cursor cur = {};
665  struct m0_bufvec bvec;
666  struct m0_be_log_io *lio;
667  struct m0_be_log *log = record->lgr_log;
668  struct m0_buf *buf;
669  m0_bcount_t size = 0;
670  m0_bcount_t size_lio;
671  m0_bcount_t size_lio_aligned;
672  m0_bcount_t size_fmt;
673  uint32_t bshift = m0_be_log_bshift(log);
674  uint64_t align = 1ULL << bshift;
675  void *addr_fmt;
676  void *addr_zero;
677  int rc;
678  int i;
679 
682 
683  M0_ENTRY("record=%p opcode=%d size_reserved=%"PRId64,
684  record, opcode, size_reserved);
685 
688  M0_PRE(ergo(opcode == SIO_READ, record->lgr_state == LGR_USED));
689  M0_PRE(ergo(opcode == SIO_WRITE, record->lgr_state == LGR_NEW));
690  M0_PRE(record->lgr_io_nr > 0);
691 
692  if (opcode == SIO_WRITE) {
693  record->lgr_state = LGR_USED;
694  record->lgr_need_discard = true;
695  record->lgr_position = log->lg_current;
696  record->lgr_prev_pos = log->lg_prev_record;
697  record->lgr_prev_size = log->lg_prev_record_size;
698  record->lgr_last_discarded = log->lg_discarded;
699  record->lgr_log_header_discarded = log->lg_header.flh_discarded;
700  record_tlink_init_at_tail(record, &log->lg_records);
701  }
702 
703  for (i = 0; i < record->lgr_io_nr; ++i) {
704  lio = record->lgr_io[i];
705  size_lio = lio->lio_buf_size;
706  size_lio += i == 0 ? be_log_record_header_size() : 0;
707  addr_zero = (char*)lio->lio_buf.b_addr + size_lio;
708  size_lio += i == record->lgr_io_nr - 1 ?
710 
711  /* fill padding with 0xCC */
712  size_lio_aligned = m0_align(size_lio, align);
713  memset(addr_zero, 0xCC, size_lio_aligned - size_lio);
714  size_lio = size_lio_aligned;
715 
717  0, size_lio);
719  record->lgr_position + size,
720  &lio->lio_be_io);
722  size += size_lio;
723  }
724 
725  if (opcode == SIO_WRITE) {
726  M0_ASSERT(size <= size_reserved);
727  log->lg_current += size;
728  log->lg_free += size_reserved - size;
729  log->lg_reserved -= size_reserved;
730  log->lg_prev_record = record->lgr_position;
731  log->lg_prev_record_size = size;
732  record->lgr_size = size;
734 
735  if (size_reserved != size)
736  log->lg_got_space_cb(log);
737 
738  /* log record header */
739  lio = record->lgr_io[0];
740  header = &record->lgr_header;
741  for (i = 0; i < record->lgr_io_nr; ++i) {
743  record->lgr_io[i]->lio_buf_size);
744  }
745  header->lrh_pos = record->lgr_position;
746  header->lrh_size = size;
747  header->lrh_discarded = record->lgr_last_discarded;
748  header->lrh_prev_pos = record->lgr_prev_pos;
749  header->lrh_prev_size = record->lgr_prev_size;
750  size_fmt = m0_be_fmt_log_record_header_size(header);
751  bvec = M0_BUFVEC_INIT_BUF(&lio->lio_buf.b_addr, &size_fmt);
753  m0_be_fmt_log_record_header_encode(header, &cur);
754 
755  /* log record footer */
756  lio = record->lgr_io[record->lgr_io_nr - 1];
757  footer = &record->lgr_footer;
758  footer->lrf_pos = record->lgr_position;
759  size_fmt = m0_be_fmt_log_record_footer_size(footer);
760  addr_fmt = (char *)lio->lio_buf.b_addr +
761  m0_align(lio->lio_buf_size + size_fmt, align) -
762  size_fmt;
763  bvec = M0_BUFVEC_INIT_BUF(&addr_fmt, &size_fmt);
765  m0_be_fmt_log_record_footer_encode(footer, &cur);
766  }
767 
768  if (opcode == SIO_WRITE &&
769  m0_be_log_store_overwrites(&log->lg_store, record->lgr_position,
770  size, log->lg_header.flh_group_lsn)) {
775  rc = m0_be_fmt_log_header_encode_buf(&log->lg_header, buf);
776  M0_ASSERT_INFO(rc == 0, "rc=%d", rc); /* XXX */
777  record->lgr_write_header = true;
778  }
779 
781 
782  /*
783  * Size is part of the log that is not held by records. Notify user
784  * if it less than threshold.
785  */
787  (log->lg_current - log->lg_discarded);
788  if (size <= log->lg_cfg.lc_full_threshold &&
789  log->lg_cfg.lc_full_cb != NULL)
790  log->lg_cfg.lc_full_cb(log);
791 
792  M0_LEAVE("record="BLR_F" log="BL_F, BLR_P(record), BL_P(log));
793 }
794 
796  struct m0_be_op *op)
797 {
798  struct m0_be_log *log = record->lgr_log;
799  struct m0_be_op op2 = {};
800  int i;
801 
802  record->lgr_state = LGR_SCHEDULED;
804  m0_be_op_set_add(op, &record->lgr_record_op);
805 
806  /* XXX Move op to ACTIVE state. Workaround for several tx_groups. */
807  m0_be_op_init(&op2);
808  m0_be_op_set_add(op, &op2);
809  m0_be_op_active(&op2);
810  m0_be_op_done(&op2);
811  m0_be_op_fini(&op2);
812 
813  if (record->lgr_write_header) {
815  m0_be_op_set_add(&record->lgr_record_op,
816  &log->lg_header_write_op);
818  &log->lg_header_write_op);
819  }
820  for (i = 0; i < record->lgr_io_nr; ++i) {
821  m0_be_op_set_add(&record->lgr_record_op,
822  record->lgr_op[i]);
824  record->lgr_io[i], record->lgr_op[i]);
825  }
827 }
828 
829 M0_INTERNAL struct m0_bufvec *
831  int index)
832 {
833  M0_PRE(index < record->lgr_io_nr);
834  return m0_be_log_io_bufvec(record->lgr_io[index]);
835 }
836 
837 M0_INTERNAL m0_bindex_t
839 {
840  return record->lgr_position;
841 }
842 
843 M0_INTERNAL m0_bindex_t
845 {
846  M0_PRE(record->lgr_log_header_discarded < M0_BINDEX_MAX);
847  return record->lgr_log_header_discarded;
848 }
849 
850 M0_INTERNAL int m0_be_log_reserve(struct m0_be_log *log, m0_bcount_t size)
851 {
852  int rc;
853 
854  M0_ENTRY("log="BL_F" size=%"PRIu64, BL_P(log), size);
855 
857 
858  if (log->lg_free < size) {
859  rc = -EAGAIN;
860  } else {
861  log->lg_free -= size;
862  log->lg_reserved += size;
863  rc = 0;
864  }
865  return M0_RC_INFO(rc, "log="BL_F, BL_P(log));
866 }
867 
868 M0_INTERNAL void m0_be_log_unreserve(struct m0_be_log *log, m0_bcount_t size)
869 {
870  M0_ENTRY("log="BL_F" size=%"PRIu64, BL_P(log), size);
871 
873  M0_PRE(log->lg_reserved >= size);
874 
875  log->lg_free += size;
876  log->lg_reserved -= size;
877 
878  log->lg_got_space_cb(log);
879 
880  M0_LEAVE("log="BL_F, BL_P(log));
881 }
882 
883 M0_INTERNAL uint32_t m0_be_log_bshift(struct m0_be_log *log)
884 {
885  return m0_be_log_store_bshift(&log->lg_store);
886 }
887 
888 M0_INTERNAL void m0_be_log_header__set(struct m0_be_fmt_log_header *hdr,
889  m0_bindex_t discarded,
890  m0_bindex_t lsn,
892 {
893  M0_ENTRY("discarded=%" PRId64 " lsn=%" PRId64 " size=%"PRId64,
894  discarded, lsn, size);
895 
896  m0_be_fmt_log_header_reset(hdr);
897  hdr->flh_discarded = discarded;
898  hdr->flh_group_lsn = lsn;
899  hdr->flh_group_size = size;
900 }
901 
902 M0_INTERNAL bool m0_be_log_header__is_eq(struct m0_be_fmt_log_header *hdr1,
903  struct m0_be_fmt_log_header *hdr2)
904 {
905  return hdr1->flh_discarded == hdr2->flh_discarded &&
906  hdr1->flh_group_lsn == hdr2->flh_group_lsn &&
907  hdr1->flh_group_size == hdr2->flh_group_size;
908 }
909 
910 static void be_log_header_update(struct m0_be_log *log)
911 {
912  struct m0_be_log_record *record;
915 
917  record = record_tlist_head(&log->lg_records);
918  /* this condition also handles the first record in log. */
919  if (record != NULL && record->lgr_state != LGR_DONE &&
920  record->lgr_position != 0) {
921  index = record->lgr_prev_pos;
922  size = record->lgr_prev_size;
923  }
924  while (record != NULL && record->lgr_state == LGR_DONE) {
925  index = record->lgr_position;
926  size = record->lgr_size;
927  record = record_tlist_next(&log->lg_records, record);
928  }
930 
931  if (log->lg_unplaced_exists && log->lg_unplaced_pos < index) {
932  index = log->lg_unplaced_pos;
933  size = log->lg_unplaced_size;
934  }
936 }
937 
938 static int be_log_header_write(struct m0_be_log *log,
939  struct m0_be_fmt_log_header *log_hdr)
940 {
941  struct m0_buf *buf;
942  int rc;
943 
944  M0_ENTRY("log_hdr="BFLH_F, BFLH_P(log_hdr));
947  rc = m0_be_fmt_log_header_encode_buf(log_hdr, buf);
948  if (rc == 0)
950  return M0_RC(rc);
951 }
952 
953 M0_INTERNAL bool m0_be_log_header__repair(struct m0_be_fmt_log_header **hdrs,
954  int nr,
955  struct m0_be_fmt_log_header *out)
956 {
957  bool need_repair = false;
958  int i = 0;
959 
960  M0_PRE(nr == 3);
961 
962  if (!m0_be_log_header__is_eq(hdrs[0], hdrs[1])) {
963  i = 2;
964  need_repair = true;
965  }
967  hdrs[i]->flh_group_lsn,
968  hdrs[i]->flh_group_size);
969 
970  return need_repair || !m0_be_log_header__is_eq(hdrs[0], hdrs[2]);
971 }
972 
973 M0_INTERNAL int m0_be_log_header_read(struct m0_be_log *log,
974  struct m0_be_fmt_log_header *log_hdr)
975 {
976  struct m0_be_fmt_log_header *hdrs[3] = {};
977  struct m0_buf *buf;
978  unsigned iter;
979  bool need_repair;
980  int rc = 0;
981  int i;
982 
983  /*
984  * This function always returns a valid log header and restores it
985  * if needed. To achieve this log stores redundant copies of log header.
986  * Recovery algorithm for log header:
987  * 1. Read 3 copies of log header
988  * 2. Compare the log headers
989  * 3. If 1st and 2nd are equal then 1st is valid
990  * 4. Else 3rd header is valid
991  * 5. If all 3 headers are not equal then write valid header
992  * 6. Return valid header to user
993  * Configuration must guarantee that we have at least 3 rbufs for log
994  * headers.
995  * The above algorithm doesn't work in case of stob corruption.
996  * This function recovers log header after multiple fails during
997  * previous recoveries.
998  */
999 
1003  for (i = 0; rc == 0 && buf != NULL && i < ARRAY_SIZE(hdrs); ++i) {
1004  rc = m0_be_fmt_log_header_decode_buf(&hdrs[i], buf,
1007  }
1008  if (rc == 0) {
1009  need_repair = m0_be_log_header__repair(hdrs, i, log_hdr);
1010  if (need_repair)
1011  be_log_header_write(log, log_hdr);
1012  }
1013 
1014  for (i = 0; i < ARRAY_SIZE(hdrs); ++i) {
1015  if (hdrs[i] != NULL)
1016  m0_be_fmt_log_header_decoded_free(hdrs[i]);
1017  }
1018  return M0_RC_INFO(rc, "log_hdr="BFLH_F, BFLH_P(log_hdr));
1019 }
1020 
1021 static int be_log_read_plain(struct m0_be_log *log,
1022  m0_bindex_t pos,
1023  m0_bcount_t size,
1024  void *out)
1025 {
1026  struct m0_be_io bio = {};
1027  struct m0_be_io_credit iocred = M0_BE_IO_CREDIT(1, size, 1);
1028  int rc;
1029 
1030  be_log_io_credit(log, &iocred);
1031  rc = m0_be_io_init(&bio);
1032  if (rc != 0)
1033  goto out;
1034  rc = m0_be_io_allocate(&bio, &iocred);
1035  if (rc == 0) {
1036  m0_be_io_add_nostob(&bio, out, 0, size);
1037  m0_be_log_store_io_translate(&log->lg_store, pos, &bio);
1040  bo_sm.sm_rc);
1041  m0_be_io_deallocate(&bio);
1042  }
1043  m0_be_io_fini(&bio);
1044 out:
1045  if (rc != 0)
1047  return rc;
1048 }
1049 
1052  struct m0_be_log *log)
1053 {
1054  m0_bindex_t pos = header->lrh_pos;
1055  m0_bcount_t size = header->lrh_size;
1056  m0_bindex_t prev = header->lrh_prev_pos;
1057  m0_bindex_t discarded = header->lrh_discarded;
1060  uint64_t alignment = 1ULL << m0_be_log_bshift(log);
1061 
1062  return ergo(pos == 0, prev == 0 && discarded == 0) &&
1063  ergo(pos != 0, prev < pos && discarded <= pos) &&
1064  size >= m0_align(hsize + fsize, alignment) &&
1065 // pos + size <= log->lg_current &&
1066  m0_is_aligned(pos, alignment) &&
1067  m0_is_aligned(prev, alignment) &&
1068  m0_is_aligned(discarded, alignment) &&
1069  m0_is_aligned(size, alignment);
1070 }
1071 
1074 {
1075  int i;
1076 
1077  M0_PRE(dest->lrh_io_nr_max >= src->lrh_io_size.lrhs_nr);
1078 
1079  dest->lrh_pos = src->lrh_pos;
1080  dest->lrh_size = src->lrh_size;
1081  dest->lrh_discarded = src->lrh_discarded;
1082  dest->lrh_prev_pos = src->lrh_prev_pos;
1083  dest->lrh_prev_size = src->lrh_prev_size;
1084  for (i = 0; i < src->lrh_io_size.lrhs_nr; ++i)
1085  dest->lrh_io_size.lrhs_size[i] = src->lrh_io_size.lrhs_size[i];
1086  dest->lrh_io_size.lrhs_nr = src->lrh_io_size.lrhs_nr;
1087 }
1088 
1089 static int be_log_record_iter_read(struct m0_be_log *log,
1090  struct m0_be_log_record_iter *iter,
1091  m0_bindex_t pos)
1092 {
1095  struct m0_bufvec_cursor cur;
1096  struct m0_bufvec bvec;
1097  m0_bcount_t size_fmt;
1098  m0_bcount_t size;
1099  uint32_t bshift = m0_be_log_bshift(log);
1100  uint64_t align = 1ULL << bshift;
1101  char *data;
1102  void *addr_fmt;
1103  int rc;
1104 
1105  M0_PRE(m0_is_aligned(pos, align));
1106 
1107  size_fmt = be_log_record_header_size();
1108  size = m0_align(size_fmt + (pos & (align - 1)), align);
1109  data = m0_alloc_aligned(size, bshift);
1110  if (data == NULL)
1111  return -ENOMEM;
1112  addr_fmt = data + (pos & (align - 1));
1113  bvec = M0_BUFVEC_INIT_BUF(&addr_fmt, &size_fmt);
1115  pos &= ~((m0_bindex_t)align - 1);
1116  rc = be_log_read_plain(log, pos, size, data);
1117  rc = rc ?: m0_be_fmt_log_record_header_decode(&header, &cur,
1119  if (rc == -EPROTO)
1120  rc = -ENOENT;
1121 
1122  m0_free_aligned(data, size, bshift);
1123  if (rc != 0)
1124  return rc;
1125 
1126  rc = m0_be_fmt_log_record_header__invariant(header, log) ? 0 : -ENOENT;
1127  if (rc == 0) {
1128  size_fmt = be_log_record_footer_size();
1129  size = m0_align(size_fmt, align);
1130  data = m0_alloc_aligned(size, bshift);
1131  addr_fmt = data + size - size_fmt;
1132  bvec = M0_BUFVEC_INIT_BUF(&addr_fmt, &size_fmt);
1134  rc = be_log_read_plain(log, pos + header->lrh_size - size,
1135  size, data);
1136  rc = rc ?: m0_be_fmt_log_record_footer_decode(&footer, &cur,
1138  if (rc == 0) {
1139  rc = header->lrh_pos == footer->lrf_pos ? 0 : -ENOENT;
1140  m0_be_fmt_log_record_footer_decoded_free(footer);
1141  }
1142  m0_free_aligned(data, size, bshift);
1143  if (rc == 0)
1145  }
1146  m0_be_fmt_log_record_header_decoded_free(header);
1147 
1148  return rc;
1149 }
1150 
1152 {
1153  return be_log_record_header_init(&iter->lri_header);
1154 }
1155 
1157 {
1159 }
1160 
1162  struct m0_be_log_record_iter *src)
1163 {
1164  be_log_record_header_copy(&dest->lri_header, &src->lri_header);
1165 }
1166 
1167 M0_INTERNAL int m0_be_log_record_initial(struct m0_be_log *log,
1168  struct m0_be_log_record_iter *curr)
1169 {
1170  m0_bindex_t pos = log->lg_header.flh_group_lsn;
1172  int rc;
1173 
1174  rc = (pos == 0 && size == 0) ? -ENOENT : 0;
1175  rc = rc ?: be_log_record_iter_read(log, curr, pos);
1176  if (rc == 0 && curr->lri_header.lrh_size != size)
1177  rc = -EBADF;
1178  /*
1179  * Assumption (also true for pos/size assignments): log is not being
1180  * written to during the time this function is executed.
1181  * Why this is needed: lg_header may be updated before this function
1182  * returns otherwise.
1183  */
1184  if (rc == 0) {
1185  curr->lri_log_header_discarded =
1186  log->lg_header.flh_discarded;
1187  }
1188  return rc;
1189 }
1190 
1191 M0_INTERNAL int m0_be_log_record_next(struct m0_be_log *log,
1192  const struct m0_be_log_record_iter *curr,
1193  struct m0_be_log_record_iter *next)
1194 {
1195  int rc = be_log_record_iter_read(log, next, curr->lri_header.lrh_pos +
1196  curr->lri_header.lrh_size);
1197  if (rc == 0 && curr->lri_header.lrh_pos >= next->lri_header.lrh_pos)
1198  rc = -ENOENT;
1199  return rc;
1200 }
1201 
1202 M0_INTERNAL int m0_be_log_record_prev(struct m0_be_log *log,
1203  const struct m0_be_log_record_iter *curr,
1204  struct m0_be_log_record_iter *prev)
1205 {
1206  int rc = be_log_record_iter_read(log, prev,
1207  curr->lri_header.lrh_prev_pos);
1208  if (rc == 0 && curr->lri_header.lrh_pos <= prev->lri_header.lrh_pos)
1209  rc = -ENOENT;
1210  return rc;
1211 }
1212 
1213 M0_INTERNAL bool
1215 {
1216  return log->lg_create_mode ? false :
1218 }
1219 
1220 M0_INTERNAL void
1222  struct m0_be_log_record_iter *iter)
1223 {
1225 }
1226 
1227 M0_INTERNAL m0_bindex_t
1229 {
1230  return log->lg_recovery.brec_discarded;
1231 }
1232 
1233 M0_INTERNAL bool m0_be_log_contains_stob(struct m0_be_log *log,
1234  const struct m0_stob_id *stob_id)
1235 {
1236  return m0_be_log_store_contains_stob(&log->lg_store, stob_id);
1237 }
1238 
1240 #undef M0_TRACE_SUBSYSTEM
1241 
1242 /*
1243  * Local variables:
1244  * c-indentation-style: "K&R"
1245  * c-basic-offset: 8
1246  * tab-width: 8
1247  * fill-column: 80
1248  * scroll-step: 1
1249  * End:
1250  */
1251 /*
1252  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1253  */
m0_bindex_t lrh_pos
Definition: fmt.h:259
M0_INTERNAL void m0_be_log_record_io_size_set(struct m0_be_log_record *record, int index, m0_bcount_t size)
Definition: log.c:636
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
M0_INTERNAL void m0_be_log_store_rbuf_io_reset(struct m0_be_log_store *ls, enum m0_be_log_store_io_type io_type)
Definition: log_store.c:718
m0_bcount_t lg_prev_record_size
Definition: log.h:293
M0_INTERNAL struct m0_bufvec * m0_be_log_record_io_bufvec(struct m0_be_log_record *record, int index)
Definition: log.c:830
static size_t nr
Definition: dump.c:1505
static int be_log_read_plain(struct m0_be_log *log, m0_bindex_t pos, m0_bcount_t size, void *out)
Definition: log.c:1021
#define M0_PRE(cond)
#define M0_BE_FMT_DECODE_CFG_DEFAULT
Definition: fmt.h:291
struct m0_be_fmt_log_record_header lri_header
Definition: log.h:509
M0_INTERNAL void m0_be_log_store_close(struct m0_be_log_store *ls)
Definition: log_store.c:586
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
Definition: log.c:49
static m0_bcount_t be_log_record_header_size(void)
Definition: log.c:344
static struct m0_be_log * be_log_module2log(struct m0_module *module)
Definition: log.c:66
#define NULL
Definition: misc.h:38
struct m0_be_op lg_header_read_op
Definition: log.h:312
Definition: io.h:230
M0_INTERNAL void m0_be_recovery_init(struct m0_be_recovery *rvr, struct m0_be_recovery_cfg *cfg)
Definition: recovery.c:150
M0_INTERNAL int m0_be_log_record_iter_init(struct m0_be_log_record_iter *iter)
Definition: log.c:1151
M0_INTERNAL int m0_be_log_store_open(struct m0_be_log_store *ls, struct m0_be_log_store_cfg *ls_cfg)
Definition: log_store.c:569
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
#define ergo(a, b)
Definition: misc.h:293
struct m0_be_log_record * lio_record
Definition: log_sched.h:67
M0_INTERNAL bool m0_be_log_recovery_record_available(struct m0_be_log *log)
Definition: log.c:1214
static unsigned align(FILE *file, uint64_t align, uint64_t pos)
Definition: utrace.c:301
struct m0_be_recovery_cfg lc_recovery_cfg
Definition: log.h:252
void * b_addr
Definition: buf.h:39
M0_INTERNAL int m0_be_log_record_allocate(struct m0_be_log_record *record)
Definition: log.c:615
Definition: log.c:51
M0_INTERNAL int m0_be_log_record_initial(struct m0_be_log *log, struct m0_be_log_record_iter *curr)
Definition: log.c:1167
M0_INTERNAL void m0_be_log_record_io_launch(struct m0_be_log_record *record, struct m0_be_op *op)
Definition: log.c:795
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
enum m0_trace_level level
Definition: trace.c:111
struct m0_bufvec lio_bufvec
Definition: log_sched.h:64
struct m0_be_log_store lg_store
Definition: log.h:274
M0_INTERNAL bool m0_be_recovery_log_record_available(struct m0_be_recovery *rvr)
Definition: recovery.c:310
struct m0_be_log_sched_cfg lc_sched_cfg
Definition: log.h:251
M0_INTERNAL int m0_be_log_open(struct m0_be_log *log, struct m0_be_log_cfg *log_cfg)
Definition: log.c:281
M0_INTERNAL struct m0_buf * m0_be_log_store_rbuf_read_buf_first(struct m0_be_log_store *ls, unsigned *iter)
Definition: log_store.c:660
m0_bcount_t brec_last_record_size
Definition: recovery.h:68
struct m0_bufvec data
Definition: di.c:40
static void be_log_record_io_done_cb(struct m0_be_op *op, void *param)
Definition: log.c:380
m0_bcount_t lg_free
Definition: log.h:288
M0_INTERNAL bool m0_be_fmt_log_record_header__invariant(struct m0_be_fmt_log_record_header *header, struct m0_be_log *log)
Definition: log.c:1050
M0_INTERNAL m0_bindex_t m0_be_log_recovery_discarded(struct m0_be_log *log)
Definition: log.c:1228
M0_INTERNAL struct m0_buf * m0_be_log_store_rbuf_read_buf_next(struct m0_be_log_store *ls, unsigned *iter)
Definition: log_store.c:668
M0_INTERNAL m0_bcount_t m0_be_log_reserved_size(struct m0_be_log *log, m0_bcount_t *lio_size, int lio_nr)
Definition: log.c:358
M0_INTERNAL void m0_be_fmt_log_record_header_fini(struct m0_be_fmt_log_record_header *obj)
Definition: fmt.c:578
const char * ml_name
Definition: module.h:114
m0_bcount_t lio_buf_size
Definition: log_sched.h:63
M0_INTERNAL void m0_be_log_record_io_prepare(struct m0_be_log_record *record, enum m0_stob_io_opcode opcode, m0_bcount_t size_reserved)
Definition: log.c:660
M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
uint64_t m0_bindex_t
Definition: types.h:80
M0_INTERNAL void m0_be_recovery_fini(struct m0_be_recovery *rvr)
Definition: recovery.c:158
M0_INTERNAL int m0_be_log_record_prev(struct m0_be_log *log, const struct m0_be_log_record_iter *curr, struct m0_be_log_record_iter *prev)
Definition: log.c:1202
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
m0_bindex_t lri_log_header_discarded
Definition: log.h:511
static void be_log_header_io(struct m0_be_log *log, enum m0_be_log_store_io_type io_type, struct m0_be_op *op)
Definition: log.c:303
static void be_log_header_update(struct m0_be_log *log)
Definition: log.c:910
M0_INTERNAL void m0_be_op_callback_set(struct m0_be_op *op, m0_be_op_cb_t cb, void *param, enum m0_be_op_state state)
Definition: op.c:239
static int void * buf
Definition: dir.c:1019
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL m0_bcount_t m0_be_log_store_buf_size(struct m0_be_log_store *ls)
Definition: log_store.c:596
#define M0_EXT(start, end)
Definition: ext.h:55
#define BFLH_P(log_hdr)
Definition: fmt.h:211
static int be_log_module_init(struct m0_be_log *log, struct m0_be_log_cfg *log_cfg, bool create_mode)
Definition: log.c:257
struct m0_module lg_module
Definition: log.h:265
static void be_log_module_fini(struct m0_be_log *log, bool destroy_mode)
Definition: log.c:244
Definition: sock.c:887
M0_INTERNAL struct m0_be_log_io * m0_be_log_store_rbuf_io_first(struct m0_be_log_store *ls, enum m0_be_log_store_io_type io_type, struct m0_be_op **op, unsigned *iter)
Definition: log_store.c:692
bool lg_unplaced_exists
Definition: log.h:298
M0_INTERNAL m0_bindex_t m0_be_log_record_discarded(const struct m0_be_log_record *record)
Definition: log.c:844
M0_INTERNAL void m0_be_fmt_log_record_header_reset(struct m0_be_fmt_log_record_header *obj)
Definition: fmt.c:584
M0_INTERNAL int m0_be_log_record_io_create(struct m0_be_log_record *record, m0_bcount_t size_max)
Definition: log.c:558
return M0_RC(rc)
op
Definition: libdemo.c:64
M0_INTERNAL void m0_be_log_module_setup(struct m0_be_log *log, struct m0_be_log_cfg *lg_cfg, bool create_mode)
Definition: log.c:233
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL bool m0_be_log_header__repair(struct m0_be_fmt_log_header **hdrs, int nr, struct m0_be_fmt_log_header *out)
Definition: log.c:953
Definition: buf.h:37
m0_bcount_t lrh_size
Definition: fmt.h:260
M0_INTERNAL void m0_be_io_configure(struct m0_be_io *bio, enum m0_stob_io_opcode opcode)
Definition: io.c:516
M0_INTERNAL void m0_be_io_err_send(uint32_t errcode, uint8_t location, uint8_t io_opcode)
Definition: ha.c:38
struct m0_be_recovery lg_recovery
Definition: log.h:277
M0_INTERNAL void m0_be_log_store_io_translate(struct m0_be_log_store *ls, m0_bindex_t position, struct m0_be_io *bio)
Definition: log_store.c:637
static m0_bcount_t be_log_record_footer_size(void)
Definition: log.c:353
int opcode
Definition: crate.c:301
M0_INTERNAL int m0_be_log_record_next(struct m0_be_log *log, const struct m0_be_log_record_iter *curr, struct m0_be_log_record_iter *next)
Definition: log.c:1191
int i
Definition: dir.c:1033
#define M0_RC_INFO(rc, fmt,...)
Definition: trace.h:209
struct m0_be_log_store_cfg lc_store_cfg
Definition: log.h:250
M0_INTERNAL void m0_be_io_add_nostob(struct m0_be_io *bio, void *ptr_user, m0_bindex_t offset_stob, m0_bcount_t size)
Definition: io.c:313
#define PRIu64
Definition: types.h:58
M0_INTERNAL void m0_be_io_fini(struct m0_be_io *bio)
Definition: io.c:224
M0_INTERNAL void m0_be_log_record_assign(struct m0_be_log_record *record, struct m0_be_log_record_iter *iter, bool need_discard)
Definition: log.c:467
struct m0_mutex * lc_lock
Definition: log.h:256
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL void m0_be_fmt_log_record_header_io_size_add(struct m0_be_fmt_log_record_header *obj, m0_bcount_t size)
Definition: fmt.c:602
m0_bindex_t lg_prev_record
Definition: log.h:292
M0_INTERNAL void m0_be_log_close(struct m0_be_log *log)
Definition: log.c:287
M0_INTERNAL bool m0_be_log_sched_is_locked(struct m0_be_log_sched *sched)
Definition: log_sched.c:62
#define M0_BE_OP_SYNC_RET(op_obj, action, member)
Definition: op.h:243
m0_bindex_t lg_discarded
Definition: log.h:286
#define BL_F
Definition: log.h:318
void * lio_buf_addr
Definition: log_sched.h:62
static int be_log_record_header_init(struct m0_be_fmt_log_record_header *hdr)
Definition: log.c:607
M0_INTERNAL bool m0_be_log__invariant(struct m0_be_log *log)
Definition: log.c:270
m0_bindex_t brec_discarded
Definition: recovery.h:70
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
m0_stob_io_opcode
Definition: io.h:227
bool lg_create_mode
Definition: log.h:263
static bool m0_is_aligned(uint64_t val, uint64_t alignment)
Definition: arith.h:179
m0_bindex_t brec_last_record_pos
Definition: recovery.h:67
M0_INTERNAL void m0_be_log_sched_add(struct m0_be_log_sched *sched, struct m0_be_log_io *lio, struct m0_be_op *op)
Definition: log_sched.c:67
m0_be_log_got_space_cb_t lg_got_space_cb
Definition: log.h:305
static int be_log_header_write(struct m0_be_log *log, struct m0_be_fmt_log_header *log_hdr)
Definition: log.c:938
m0_bindex_t flh_discarded
Definition: fmt.h:91
struct m0_be_log * brc_log
Definition: recovery.h:60
M0_INTERNAL void m0_be_log_io_deallocate(struct m0_be_log_io *lio)
Definition: log_sched.c:150
M0_INTERNAL bool m0_be_log_store_contains_stob(struct m0_be_log_store *ls, const struct m0_stob_id *stob_id)
Definition: log_store.c:768
Definition: log.c:53
static struct m0_bufvec bvec
Definition: xcode.c:169
M0_INTERNAL struct m0_be_log_io * m0_be_log_store_rbuf_io_next(struct m0_be_log_store *ls, enum m0_be_log_store_io_type io_type, struct m0_be_op **op, unsigned *iter)
Definition: log_store.c:702
M0_INTERNAL void m0_be_log_record_fini(struct m0_be_log_record *record)
Definition: log.c:410
static int next[]
Definition: cp.c:248
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
M0_INTERNAL void m0_module_setup(struct m0_module *module, const char *name, const struct m0_modlev *level, int level_nr, struct m0 *instance)
Definition: module.c:193
M0_INTERNAL int m0_be_io_init(struct m0_be_io *bio)
Definition: io.c:175
m0_be_log_got_space_cb_t lc_got_space_cb
Definition: log.h:253
struct m0_mutex lg_record_state_lock
Definition: log.h:282
m0_bindex_t brec_current
Definition: recovery.h:69
#define BFLRH_F
Definition: fmt.h:268
M0_INTERNAL int m0_be_log_create(struct m0_be_log *log, struct m0_be_log_cfg *log_cfg)
Definition: log.c:292
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
static void be_log_header_io_sync(struct m0_be_log *log, enum m0_be_log_store_io_type io_type)
Definition: log.c:328
M0_INTERNAL void m0_be_log_header__set(struct m0_be_fmt_log_header *hdr, m0_bindex_t discarded, m0_bindex_t lsn, m0_bcount_t size)
Definition: log.c:888
static int be_log_record_iter_read(struct m0_be_log *log, struct m0_be_log_record_iter *iter, m0_bindex_t pos)
Definition: log.c:1089
M0_INTERNAL void m0_be_log_record_discard(struct m0_be_log *log, m0_bcount_t size)
Definition: log.c:523
M0_INTERNAL void m0_be_op_done(struct m0_be_op *op)
Definition: stubs.c:104
m0_bindex_t flh_group_lsn
Definition: fmt.h:205
static void be_log_level_leave(struct m0_module *module)
Definition: log.c:149
M0_INTERNAL int m0_be_fmt_log_record_header_init(struct m0_be_fmt_log_record_header *obj, const struct m0_be_fmt_log_record_header_cfg *cfg)
Definition: fmt.c:567
M0_INTERNAL void m0_be_log_record_reset(struct m0_be_log_record *record)
Definition: log.c:433
struct m0_mutex * lg_external_lock
Definition: log.h:310
#define M0_BE_IO_CREDIT(reg_nr, reg_size, part_nr)
Definition: io.h:76
M0_INTERNAL struct m0_bufvec * m0_be_log_io_bufvec(struct m0_be_log_io *lio)
Definition: log_sched.c:159
#define PRId64
Definition: types.h:57
static void be_log_io_credit(struct m0_be_log *log, struct m0_be_io_credit *accum)
Definition: log.c:552
m0_bindex_t lg_current
Definition: log.h:284
M0_INTERNAL int m0_be_log_reserve(struct m0_be_log *log, m0_bcount_t size)
Definition: log.c:850
M0_INTERNAL void m0_be_recovery_log_record_get(struct m0_be_recovery *rvr, struct m0_be_log_record_iter *iter)
Definition: recovery.c:322
M0_INTERNAL bool m0_be_log_store_overwrites(struct m0_be_log_store *ls, m0_bindex_t index, m0_bcount_t size, m0_bindex_t position)
Definition: log_store.c:752
m0_bcount_t flh_group_size
Definition: fmt.h:93
M0_INTERNAL int m0_be_log_io_allocate(struct m0_be_log_io *lio, struct m0_be_io_credit *iocred, uint32_t log_bshift)
Definition: log_sched.c:114
M0_INTERNAL void m0_be_log_recovery_record_get(struct m0_be_log *log, struct m0_be_log_record_iter *iter)
Definition: log.c:1221
struct m0_be_op lg_header_write_op
Definition: log.h:314
struct m0_be_log_cfg lg_cfg
Definition: log.h:262
M0_INTERNAL void m0_be_op_reset(struct m0_be_op *op)
Definition: op.c:152
M0_INTERNAL int m0_be_log_io_init(struct m0_be_log_io *lio)
Definition: log_sched.c:97
m0_bindex_t flh_group_lsn
Definition: fmt.h:92
M0_INTERNAL void m0_be_op_active(struct m0_be_op *op)
Definition: stubs.c:100
m0_bindex_t lrh_prev_pos
Definition: fmt.h:262
#define BLR_F
Definition: log.h:378
M0_INTERNAL m0_bindex_t m0_be_log_record_position(const struct m0_be_log_record *record)
Definition: log.c:838
#define BFLH_F
Definition: fmt.h:209
M0_INTERNAL struct m0_buf * m0_be_log_store_rbuf_write_buf(struct m0_be_log_store *ls)
Definition: log_store.c:654
Definition: ext.h:37
bool lg_destroy_mode
Definition: log.h:264
M0_INTERNAL int m0_be_io_allocate(struct m0_be_io *bio, struct m0_be_io_credit *iocred)
Definition: io.c:180
#define BLR_P(record)
Definition: log.h:381
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_be_io_deallocate(struct m0_be_io *bio)
Definition: io.c:215
M0_INTERNAL bool m0_be_log_header__is_eq(struct m0_be_fmt_log_header *hdr1, struct m0_be_fmt_log_header *hdr2)
Definition: log.c:902
m0_bcount_t lsc_rbuf_size
Definition: log_store.h:182
M0_INTERNAL void m0_be_log_destroy(struct m0_be_log *log)
Definition: log.c:298
M0_INTERNAL void m0_be_log_record_iter_copy(struct m0_be_log_record_iter *dest, struct m0_be_log_record_iter *src)
Definition: log.c:1161
#define BFLRH_P(h)
Definition: fmt.h:271
M0_INTERNAL m0_bcount_t m0_be_fmt_log_record_header_size_max(const struct m0_be_fmt_log_record_header_cfg *cfg)
Definition: fmt.c:589
bool lc_skip_recovery
Definition: log.h:257
m0_bcount_t lg_unplaced_size
Definition: log.h:300
#define BL_P(log)
Definition: log.h:320
int m_cur
Definition: module.h:160
M0_INTERNAL int m0_be_log_header_read(struct m0_be_log *log, struct m0_be_fmt_log_header *log_hdr)
Definition: log.c:973
M0_INTERNAL int m0_be_log_store_create(struct m0_be_log_store *ls, struct m0_be_log_store_cfg *ls_cfg)
Definition: log_store.c:575
m0_bcount_t size
Definition: di.c:39
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_be_op_fini(struct m0_be_op *op)
Definition: stubs.c:92
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_be_op_set_add(struct m0_be_op *parent, struct m0_be_op *child)
Definition: op.c:297
struct m0_buf lio_buf
Definition: log_sched.h:61
m0_be_log_full_cb_t lc_full_cb
Definition: log.h:254
Definition: log.c:48
Definition: record.py:1
Definition: io.h:87
M0_INTERNAL void m0_be_log_record_iter_fini(struct m0_be_log_record_iter *iter)
Definition: log.c:1156
#define M0_ASSERT_INFO(cond, fmt,...)
M0_INTERNAL void m0_be_log_sched_fini(struct m0_be_log_sched *sched)
Definition: log_sched.c:47
Definition: log.h:261
struct m0_tl lg_records
Definition: log.h:280
#define out(...)
Definition: gen.c:41
static void be_log_record_header_copy(struct m0_be_fmt_log_record_header *dest, struct m0_be_fmt_log_record_header *src)
Definition: log.c:1072
M0_INTERNAL void m0_be_log_store_io_credit(struct m0_be_log_store *ls, struct m0_be_io_credit *accum)
Definition: log_store.c:601
struct m0_be_io lio_be_io
Definition: log_sched.h:65
M0_INTERNAL void m0_be_log_record_deallocate(struct m0_be_log_record *record)
Definition: log.c:630
M0_INTERNAL void * m0_alloc_aligned(size_t size, unsigned shift)
Definition: memory.c:168
Definition: io.h:229
M0_INTERNAL void m0_be_log_io_fini(struct m0_be_log_io *lio)
Definition: log_sched.c:102
Definition: op.h:59
M0_TL_DEFINE(record, static, struct m0_be_log_record)
M0_INTERNAL int m0_be_recovery_run(struct m0_be_recovery *rvr)
Definition: recovery.c:184
Definition: op.h:74
m0_be_log_store_io_type
Definition: log_store.h:125
struct m0_be_log_sched lg_sched
Definition: log.h:276
static int be_log_level_enter(struct m0_module *module)
Definition: log.c:72
M0_INTERNAL bool m0_be_log_contains_stob(struct m0_be_log *log, const struct m0_stob_id *stob_id)
Definition: log.c:1233
m0_bindex_t flh_discarded
Definition: fmt.h:204
M0_INTERNAL void m0_be_log_record_skip_discard(struct m0_be_log_record *record)
Definition: log.c:505
M0_INTERNAL void m0_be_log_sched_lock(struct m0_be_log_sched *sched)
Definition: log_sched.c:52
M0_INTERNAL void m0_be_op_init(struct m0_be_op *op)
Definition: stubs.c:87
void m0_free(void *data)
Definition: memory.c:146
m0_bindex_t lg_unplaced_pos
Definition: log.h:299
M0_INTERNAL void m0_be_io_launch(struct m0_be_io *bio, struct m0_be_op *op)
Definition: io.c:599
M0_INTERNAL void m0_be_log_record_init(struct m0_be_log_record *record, struct m0_be_log *log)
Definition: log.c:390
struct m0_pdclust_src_addr src
Definition: fd.c:108
M0_INTERNAL void m0_be_log_sched_unlock(struct m0_be_log_sched *sched)
Definition: log_sched.c:57
M0_TL_DESCR_DEFINE(record, "be log records", static, struct m0_be_log_record, lgr_linkage, lgr_magic, M0_BE_LOG_RECORD_MAGIC, M0_BE_LOG_RECORD_HEAD_MAGIC)
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL uint32_t m0_be_log_bshift(struct m0_be_log *log)
Definition: log.c:883
#define ARRAY_SIZE(a)
Definition: misc.h:45
static uint64_t m0_align(uint64_t val, uint64_t alignment)
Definition: arith.h:170
M0_INTERNAL void m0_be_log_store_destroy(struct m0_be_log_store *ls)
Definition: log_store.c:581
m0_bcount_t lg_reserved
Definition: log.h:290
static const struct m0_modlev be_log_levels[]
Definition: log.c:192
M0_INTERNAL void m0_module_fini(struct m0_module *module, int level)
Definition: module.c:142
M0_INTERNAL int m0_be_log_sched_init(struct m0_be_log_sched *sched, struct m0_be_log_sched_cfg *cfg)
Definition: log_sched.c:38
M0_INTERNAL void m0_be_log_io_reset(struct m0_be_log_io *lio)
Definition: log_sched.c:106
M0_INTERNAL void m0_be_log_record_ext(struct m0_be_log_record *record, struct m0_ext *ext)
Definition: log.c:496
M0_INTERNAL void m0_be_op_wait(struct m0_be_op *op)
Definition: stubs.c:96
m0_bcount_t flh_group_size
Definition: fmt.h:206
Definition: trace.h:478
struct m0_be_fmt_log_header lg_header
Definition: log.h:278
Definition: vec.h:145
M0_INTERNAL int m0_module_init(struct m0_module *module, int level)
Definition: module.c:131
M0_INTERNAL void m0_be_log_unreserve(struct m0_be_log *log, m0_bcount_t size)
Definition: log.c:868
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL uint32_t m0_be_log_store_bshift(struct m0_be_log_store *ls)
Definition: log_store.c:591