Motr  M0
recovery.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2014-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/recovery.h"
27 
28 #include "lib/arith.h" /* max_check */
29 #include "lib/errno.h" /* -ENOSYS */
30 #include "lib/memory.h"
31 #include "be/fmt.h"
32 #include "be/log.h"
33 #include "motr/magic.h" /* M0_BE_RECOVERY_MAGIC */
34 
145 M0_TL_DESCR_DEFINE(log_record_iter, "m0_be_log_record_iter list in recovery",
146  static, struct m0_be_log_record_iter, lri_linkage, lri_magic,
148 M0_TL_DEFINE(log_record_iter, static, struct m0_be_log_record_iter);
149 
150 M0_INTERNAL void m0_be_recovery_init(struct m0_be_recovery *rvr,
151  struct m0_be_recovery_cfg *cfg)
152 {
153  rvr->brec_cfg = *cfg;
154  m0_mutex_init(&rvr->brec_lock);
155  log_record_iter_tlist_init(&rvr->brec_iters);
156 }
157 
158 M0_INTERNAL void m0_be_recovery_fini(struct m0_be_recovery *rvr)
159 {
160  m0_mutex_fini(&rvr->brec_lock);
161  log_record_iter_tlist_fini(&rvr->brec_iters);
162 }
163 
165 {
166  int rc;
167 
168  M0_ALLOC_PTR(*iter);
169  rc = *iter == NULL ? -ENOMEM : 0;
170  rc = rc ?: m0_be_log_record_iter_init(*iter);
171 
172  return rc;
173 }
174 
175 static void
177 {
178  if (iter != NULL) {
180  m0_free(iter);
181  }
182 }
183 
184 M0_INTERNAL int m0_be_recovery_run(struct m0_be_recovery *rvr)
185 {
186  struct m0_be_fmt_log_header log_hdr = {};
187  struct m0_be_log_record_iter *prev = NULL;
188  struct m0_be_log_record_iter *iter;
189  struct m0_be_log *log = rvr->brec_cfg.brc_log;
190  m0_bindex_t last_discarded;
191  m0_bindex_t log_discarded;
192  m0_bindex_t next_pos = M0_BINDEX_MAX;
193  int rc;
194 
195  M0_ENTRY("rvr = %p, log = %p", rvr, log);
196 
197  /* TODO avoid reading of header from disk, log reads it during init */
198  rc = m0_be_fmt_log_header_init(&log_hdr, NULL);
199  M0_ASSERT(rc == 0);
200  rc = m0_be_log_header_read(log, &log_hdr);
201  M0_ASSERT(rc == 0);
202  log_discarded = log_hdr.flh_discarded;
203  M0_LOG(M0_DEBUG, "log_discarded=%"PRIu64, log_discarded);
204 
206  rc = rc ?: m0_be_log_record_initial(log, iter);
207  while (rc == 0) {
208  log_record_iter_tlink_init_at_tail(iter, &rvr->brec_iters);
209  prev = iter;
210  M0_LOG(M0_DEBUG, "Forward movement : prev header "
211  BFLRH_F, BFLRH_P(&prev->lri_header));
213  rc = rc ?: m0_be_log_record_next(log, prev, iter);
214  }
216  if (!M0_IN(rc, (0, -ENOENT))){
217  M0_LOG(M0_ERROR, "Error: rc=%d", rc);
218  goto err;
219  }
220  if (rc == -ENOENT && prev == NULL){
221  M0_LOG(M0_DEBUG, "Empty");
222  goto empty;
223  }
224 
225  last_discarded = max_check(prev->lri_header.lrh_discarded,
226  log_discarded);
227  prev = log_record_iter_tlist_head(&rvr->brec_iters);
228  while (prev != NULL && prev->lri_header.lrh_pos < last_discarded) {
229  next_pos = prev->lri_header.lrh_pos + prev->lri_header.lrh_size;
230  M0_LOG(M0_DEBUG, "next_pos=%"PRIu64, next_pos);
231  log_record_iter_tlink_del_fini(prev);
233  prev = log_record_iter_tlist_head(&rvr->brec_iters);
234  }
235  M0_ASSERT(ergo(prev == NULL,
236  last_discarded == log_discarded &&
237  last_discarded == next_pos));
238  if (prev == NULL){
239  M0_LOG(M0_DEBUG, "Empty");
240  goto empty;
241  }
242 
243  rc = 0;
244  while (rc == 0 && prev->lri_header.lrh_pos > last_discarded) {
246  rc = rc ?: m0_be_log_record_prev(log, prev, iter);
247  if (rc == 0) {
248  log_record_iter_tlink_init_at(iter, &rvr->brec_iters);
249  prev = iter;
250  M0_LOG(M0_DEBUG, "Backward movement : prev header "
251  BFLRH_F, BFLRH_P(&(prev->lri_header)));
252  } else
254  }
255  M0_ASSERT(ergo(rc == 0, prev->lri_header.lrh_pos == last_discarded));
256 
257  if (rc != 0){
258  M0_LOG(M0_ERROR, "Error: rc=%d", rc);
259  goto err;
260  }
261 
262  iter = log_record_iter_tlist_tail(&rvr->brec_iters);
263 
266  rvr->brec_current = rvr->brec_last_record_pos +
268  rvr->brec_discarded = prev->lri_header.lrh_pos;
269  M0_LOG(M0_DEBUG, "Recovery scan complete : last_record_pos=%"PRIu64
270  " last_record_size=%"PRIu64
271  " current position=%"PRIu64
272  " discarded position=%"PRIu64,
275  rvr->brec_current,
276  rvr->brec_discarded);
277 
278  goto out;
279 
280 err:
281  M0_LOG(M0_ERROR, "Error during recovery scan. rc = %d", rc);
282  m0_tl_for(log_record_iter, &rvr->brec_iters, iter) {
283  log_record_iter_tlink_del_fini(iter);
285  } m0_tl_endfor;
286  goto out;
287 
288 empty:
289  rc = 0;
290  rvr->brec_last_record_pos = log_hdr.flh_group_lsn;
291  rvr->brec_last_record_size = log_hdr.flh_group_size;
292  rvr->brec_current = log_discarded;
293  rvr->brec_discarded = log_discarded;
294  M0_LOG(M0_DEBUG, "Empty Logs : last_record_pos=%"PRIu64
295  " last_record_size=%"PRIu64
296  " current position=%"PRIu64
297  " discarded position=%"PRIu64,
300  rvr->brec_current,
301  rvr->brec_discarded);
302  M0_POST(log_record_iter_tlist_is_empty(&rvr->brec_iters));
303 out:
304  m0_be_fmt_log_header_fini(&log_hdr);
305  M0_LEAVE();
306  return rc;
307 }
308 
309 M0_INTERNAL bool
311 {
312  bool result;
313 
314  m0_mutex_lock(&rvr->brec_lock);
315  result = !log_record_iter_tlist_is_empty(&rvr->brec_iters);
316  m0_mutex_unlock(&rvr->brec_lock);
317 
318  return result;
319 }
320 
321 M0_INTERNAL void
323  struct m0_be_log_record_iter *iter)
324 {
325  struct m0_be_log_record_iter *next;
326 
327  m0_mutex_lock(&rvr->brec_lock);
328  next = log_record_iter_tlist_pop(&rvr->brec_iters);
329  m0_mutex_unlock(&rvr->brec_lock);
330  M0_ASSERT(next != NULL);
332  log_record_iter_tlink_fini(next);
334  M0_LOG(M0_DEBUG, "iter pos=%" PRId64 " size=%" PRId64 " discarded=%"PRId64,
335  iter->lri_header.lrh_pos,
336  iter->lri_header.lrh_size,
337  iter->lri_header.lrh_discarded);
338 }
339 
340 /*
341  * Local variables:
342  * c-indentation-style: "K&R"
343  * c-basic-offset: 8
344  * tab-width: 8
345  * fill-column: 80
346  * scroll-step: 1
347  * End:
348  */
349 /*
350  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
351  */
m0_bindex_t lrh_pos
Definition: fmt.h:259
struct m0_tl brec_iters
Definition: recovery.h:66
struct m0_be_fmt_log_record_header lri_header
Definition: log.h:509
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define NULL
Definition: misc.h:38
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
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL int m0_be_log_record_initial(struct m0_be_log *log, struct m0_be_log_record_iter *curr)
Definition: log.c:1167
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL bool m0_be_recovery_log_record_available(struct m0_be_recovery *rvr)
Definition: recovery.c:310
#define max_check(a, b)
Definition: arith.h:95
m0_bcount_t brec_last_record_size
Definition: recovery.h:68
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
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_TL_DEFINE(log_record_iter, static, struct m0_be_log_record_iter)
static int be_recovery_log_record_iter_new(struct m0_be_log_record_iter **iter)
Definition: recovery.c:164
#define m0_tl_endfor
Definition: tlist.h:700
#define M0_ENTRY(...)
Definition: trace.h:170
m0_bcount_t lrh_size
Definition: fmt.h:260
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
#define PRIu64
Definition: types.h:58
struct m0_mutex brec_lock
Definition: recovery.h:65
m0_bindex_t brec_discarded
Definition: recovery.h:70
#define M0_ASSERT(cond)
M0_TL_DESCR_DEFINE(log_record_iter, "m0_be_log_record_iter list in recovery", static, struct m0_be_log_record_iter, lri_linkage, lri_magic, M0_BE_RECOVERY_MAGIC, M0_BE_RECOVERY_HEAD_MAGIC)
m0_bindex_t brec_last_record_pos
Definition: recovery.h:67
struct m0_be_log * brc_log
Definition: recovery.h:60
struct m0_be_recovery_cfg brec_cfg
Definition: recovery.h:64
static int next[]
Definition: cp.c:248
m0_bindex_t lrh_discarded
Definition: fmt.h:261
m0_bindex_t brec_current
Definition: recovery.h:69
#define BFLRH_F
Definition: fmt.h:268
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
m0_bindex_t flh_group_lsn
Definition: fmt.h:205
#define PRId64
Definition: types.h:57
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
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
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 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 void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_be_log_record_iter_fini(struct m0_be_log_record_iter *iter)
Definition: log.c:1156
Definition: log.h:261
static void be_recovery_log_record_iter_destroy(struct m0_be_log_record_iter *iter)
Definition: recovery.c:176
#define out(...)
Definition: gen.c:41
M0_INTERNAL int m0_be_recovery_run(struct m0_be_recovery *rvr)
Definition: recovery.c:184
m0_bindex_t flh_discarded
Definition: fmt.h:204
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
int32_t rc
Definition: trigger_fop.h:47
static void empty(void)
Definition: consumer.c:101
m0_bcount_t flh_group_size
Definition: fmt.h:206