Whamcloud - gitweb
LU-14487 modules: remove references to Sun Trademark.
[fs/lustre-release.git] / lustre / obdclass / llog_cat.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  *
31  * lustre/obdclass/llog_cat.c
32  *
33  * OST<->MDS recovery logging infrastructure.
34  *
35  * Invariants in implementation:
36  * - we do not share logs among different OST<->MDS connections, so that
37  *   if an OST or MDS fails it need only look at log(s) relevant to itself
38  *
39  * Author: Andreas Dilger <adilger@clusterfs.com>
40  * Author: Alexey Zhuravlev <alexey.zhuravlev@intel.com>
41  * Author: Mikhail Pershin <mike.pershin@intel.com>
42  */
43
44 #define DEBUG_SUBSYSTEM S_LOG
45
46
47 #include <obd_class.h>
48
49 #include "llog_internal.h"
50
51
52 /**
53  * lockdep markers for nested struct llog_handle::lgh_lock locking.
54  */
55 enum {
56         LLOGH_CAT,
57         LLOGH_LOG,
58 };
59
60 /* Create a new log handle and add it to the open list.
61  * This log handle will be closed when all of the records in it are removed.
62  *
63  * Assumes caller has already pushed us into the kernel context and is locking.
64  */
65 static int llog_cat_new_log(const struct lu_env *env,
66                             struct llog_handle *cathandle,
67                             struct llog_handle *loghandle,
68                             struct thandle *th)
69 {
70         struct llog_thread_info *lgi = llog_info(env);
71         struct llog_logid_rec   *rec = &lgi->lgi_logid;
72         struct thandle *handle = NULL;
73         struct dt_device *dt = NULL;
74         struct llog_log_hdr     *llh = cathandle->lgh_hdr;
75         int                      rc, index;
76
77         ENTRY;
78
79         index = (cathandle->lgh_last_idx + 1) %
80                 (OBD_FAIL_PRECHECK(OBD_FAIL_CAT_RECORDS) ? (cfs_fail_val + 1) :
81                                                 LLOG_HDR_BITMAP_SIZE(llh));
82
83         /* check that new llog index will not overlap with the first one.
84          * - llh_cat_idx is the index just before the first/oldest still in-use
85          *      index in catalog
86          * - lgh_last_idx is the last/newest used index in catalog
87          *
88          * When catalog is not wrapped yet then lgh_last_idx is always larger
89          * than llh_cat_idx. After the wrap around lgh_last_idx re-starts
90          * from 0 and llh_cat_idx becomes the upper limit for it
91          *
92          * Check if catalog has already wrapped around or not by comparing
93          * last_idx and cat_idx */
94         if ((index == llh->llh_cat_idx + 1 && llh->llh_count > 1) ||
95             (index == 0 && llh->llh_cat_idx == 0)) {
96                 if (cathandle->lgh_name == NULL) {
97                         CWARN("%s: there are no more free slots in catalog "
98                               DFID":%x\n",
99                               loghandle2name(loghandle),
100                               PFID(&cathandle->lgh_id.lgl_oi.oi_fid),
101                               cathandle->lgh_id.lgl_ogen);
102                 } else {
103                         CWARN("%s: there are no more free slots in "
104                               "catalog %s\n", loghandle2name(loghandle),
105                               cathandle->lgh_name);
106                 }
107                 RETURN(-ENOSPC);
108         }
109
110         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_LLOG_CREATE_FAILED))
111                 RETURN(-ENOSPC);
112
113         if (loghandle->lgh_hdr != NULL) {
114                 /* If llog object is remote and creation is failed, lgh_hdr
115                  * might be left over here, free it first */
116                 LASSERT(!llog_exist(loghandle));
117                 OBD_FREE_LARGE(loghandle->lgh_hdr, loghandle->lgh_hdr_size);
118                 loghandle->lgh_hdr = NULL;
119         }
120
121         if (th == NULL) {
122                 dt = lu2dt_dev(cathandle->lgh_obj->do_lu.lo_dev);
123
124                 handle = dt_trans_create(env, dt);
125                 if (IS_ERR(handle))
126                         RETURN(PTR_ERR(handle));
127
128                 /* Create update llog object synchronously, which
129                  * happens during inialization process see
130                  * lod_sub_prep_llog(), to make sure the update
131                  * llog object is created before corss-MDT writing
132                  * updates into the llog object */
133                 if (cathandle->lgh_ctxt->loc_flags & LLOG_CTXT_FLAG_NORMAL_FID)
134                         handle->th_sync = 1;
135
136                 handle->th_wait_submit = 1;
137
138                 rc = llog_declare_create(env, loghandle, handle);
139                 if (rc != 0)
140                         GOTO(out, rc);
141
142                 rec->lid_hdr.lrh_len = sizeof(*rec);
143                 rec->lid_hdr.lrh_type = LLOG_LOGID_MAGIC;
144                 rec->lid_id = loghandle->lgh_id;
145                 rc = llog_declare_write_rec(env, cathandle, &rec->lid_hdr, -1,
146                                             handle);
147                 if (rc != 0)
148                         GOTO(out, rc);
149
150                 rc = dt_trans_start_local(env, dt, handle);
151                 if (rc != 0)
152                         GOTO(out, rc);
153
154                 th = handle;
155         }
156
157         rc = llog_create(env, loghandle, th);
158         /* if llog is already created, no need to initialize it */
159         if (rc == -EEXIST) {
160                 GOTO(out, rc = 0);
161         } else if (rc != 0) {
162                 CERROR("%s: can't create new plain llog in catalog: rc = %d\n",
163                        loghandle2name(loghandle), rc);
164                 GOTO(out, rc);
165         }
166
167         rc = llog_init_handle(env, loghandle,
168                               LLOG_F_IS_PLAIN | LLOG_F_ZAP_WHEN_EMPTY,
169                               &cathandle->lgh_hdr->llh_tgtuuid);
170         if (rc < 0)
171                 GOTO(out, rc);
172
173         /* build the record for this log in the catalog */
174         rec->lid_hdr.lrh_len = sizeof(*rec);
175         rec->lid_hdr.lrh_type = LLOG_LOGID_MAGIC;
176         rec->lid_id = loghandle->lgh_id;
177
178         /* append the new record into catalog. The new index will be
179          * assigned to the record and updated in rec header */
180         rc = llog_write_rec(env, cathandle, &rec->lid_hdr,
181                             &loghandle->u.phd.phd_cookie, LLOG_NEXT_IDX, th);
182         if (rc < 0)
183                 GOTO(out_destroy, rc);
184
185         CDEBUG(D_OTHER, "new plain log "DFID".%u of catalog "DFID"\n",
186                PFID(&loghandle->lgh_id.lgl_oi.oi_fid), rec->lid_hdr.lrh_index,
187                PFID(&cathandle->lgh_id.lgl_oi.oi_fid));
188
189         loghandle->lgh_hdr->llh_cat_idx = rec->lid_hdr.lrh_index;
190
191         /* limit max size of plain llog so that space can be
192          * released sooner, especially on small filesystems */
193         /* 2MB for the cases when free space hasn't been learned yet */
194         loghandle->lgh_max_size = 2 << 20;
195         dt = lu2dt_dev(cathandle->lgh_obj->do_lu.lo_dev);
196         rc = dt_statfs(env, dt, &lgi->lgi_statfs);
197         if (rc == 0 && lgi->lgi_statfs.os_bfree > 0) {
198                 __u64 freespace = (lgi->lgi_statfs.os_bfree *
199                                   lgi->lgi_statfs.os_bsize) >> 6;
200                 if (freespace < loghandle->lgh_max_size)
201                         loghandle->lgh_max_size = freespace;
202                 /* shouldn't be > 128MB in any case?
203                  * it's 256K records of 512 bytes each */
204                 if (freespace > (128 << 20))
205                         loghandle->lgh_max_size = 128 << 20;
206         }
207         if (unlikely(OBD_FAIL_PRECHECK(OBD_FAIL_PLAIN_RECORDS) ||
208                      OBD_FAIL_PRECHECK(OBD_FAIL_CATALOG_FULL_CHECK))) {
209                 // limit the numer of plain records for test
210                 loghandle->lgh_max_size = loghandle->lgh_hdr_size +
211                        cfs_fail_val * 64;
212         }
213
214         rc = 0;
215
216 out:
217         if (handle != NULL) {
218                 handle->th_result = rc >= 0 ? 0 : rc;
219                 dt_trans_stop(env, dt, handle);
220         }
221         RETURN(rc);
222
223 out_destroy:
224         /* to signal llog_cat_close() it shouldn't try to destroy the llog,
225          * we want to destroy it in this transaction, otherwise the object
226          * becomes an orphan */
227         loghandle->lgh_hdr->llh_flags &= ~LLOG_F_ZAP_WHEN_EMPTY;
228         /* this is to mimic full log, so another llog_cat_current_log()
229          * can skip it and ask for another onet */
230         loghandle->lgh_last_idx = LLOG_HDR_BITMAP_SIZE(loghandle->lgh_hdr) + 1;
231         llog_trans_destroy(env, loghandle, th);
232         if (handle != NULL)
233                 dt_trans_stop(env, dt, handle);
234         RETURN(rc);
235 }
236
237 static int llog_cat_refresh(const struct lu_env *env,
238                             struct llog_handle *cathandle)
239 {
240         struct llog_handle *loghandle;
241         int rc;
242
243         down_write(&cathandle->lgh_lock);
244         list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
245                             u.phd.phd_entry) {
246                 if (!llog_exist(loghandle))
247                         continue;
248
249                 rc = llog_read_header(env, loghandle, NULL);
250                 if (rc)
251                         goto unlock;
252         }
253
254         rc = llog_read_header(env, cathandle, NULL);
255 unlock:
256         up_write(&loghandle->lgh_lock);
257
258         return rc;
259 }
260
261 /*
262  * prepare current/next log for catalog.
263  *
264  * if \a *ploghandle is NULL, open it, and declare create, NB, if \a
265  * *ploghandle is remote, create it synchronously here, see comments
266  * below.
267  *
268  * \a cathandle->lgh_lock is down_read-ed, it gets down_write-ed if \a
269  * *ploghandle has to be opened.
270  */
271 static int llog_cat_prep_log(const struct lu_env *env,
272                              struct llog_handle *cathandle,
273                              struct llog_handle **ploghandle,
274                              struct thandle *th)
275 {
276         int rc;
277         int sem_upgraded;
278
279 start:
280         rc = 0;
281         sem_upgraded = 0;
282         if (IS_ERR_OR_NULL(*ploghandle)) {
283                 up_read(&cathandle->lgh_lock);
284                 down_write(&cathandle->lgh_lock);
285                 sem_upgraded = 1;
286                 if (IS_ERR_OR_NULL(*ploghandle)) {
287                         struct llog_handle *loghandle;
288
289                         rc = llog_open(env, cathandle->lgh_ctxt, &loghandle,
290                                        NULL, NULL, LLOG_OPEN_NEW);
291                         if (!rc) {
292                                 *ploghandle = loghandle;
293                                 list_add_tail(&loghandle->u.phd.phd_entry,
294                                               &cathandle->u.chd.chd_head);
295                         }
296                 }
297                 if (rc)
298                         GOTO(out, rc);
299         }
300
301         rc = llog_exist(*ploghandle);
302         if (rc < 0)
303                 GOTO(out, rc);
304         if (rc)
305                 GOTO(out, rc = 0);
306
307         if (dt_object_remote(cathandle->lgh_obj)) {
308                 down_write_nested(&(*ploghandle)->lgh_lock, LLOGH_LOG);
309                 if (!llog_exist(*ploghandle)) {
310                         /* For remote operation, if we put the llog object
311                          * creation in the current transaction, then the
312                          * llog object will not be created on the remote
313                          * target until the transaction stop, if other
314                          * operations start before the transaction stop,
315                          * and use the same llog object, will be dependent
316                          * on the success of this transaction. So let's
317                          * create the llog object synchronously here to
318                          * remove the dependency. */
319                         rc = llog_cat_new_log(env, cathandle, *ploghandle,
320                                               NULL);
321                         if (rc == -ESTALE) {
322                                 up_write(&(*ploghandle)->lgh_lock);
323                                 if (sem_upgraded)
324                                         up_write(&cathandle->lgh_lock);
325                                 else
326                                         up_read(&cathandle->lgh_lock);
327
328                                 rc = llog_cat_refresh(env, cathandle);
329                                 down_read_nested(&cathandle->lgh_lock,
330                                                  LLOGH_CAT);
331                                 if (rc)
332                                         return rc;
333                                 /* *ploghandle might become NULL, restart */
334                                 goto start;
335                         }
336                 }
337                 up_write(&(*ploghandle)->lgh_lock);
338         } else {
339                 struct llog_thread_info *lgi = llog_info(env);
340                 struct llog_logid_rec *lirec = &lgi->lgi_logid;
341
342                 rc = llog_declare_create(env, *ploghandle, th);
343                 if (rc)
344                         GOTO(out, rc);
345
346                 lirec->lid_hdr.lrh_len = sizeof(*lirec);
347                 rc = llog_declare_write_rec(env, cathandle, &lirec->lid_hdr, -1,
348                                             th);
349         }
350
351 out:
352         if (sem_upgraded) {
353                 up_write(&cathandle->lgh_lock);
354                 down_read_nested(&cathandle->lgh_lock, LLOGH_CAT);
355                 if (rc == 0)
356                         goto start;
357         }
358         return rc;
359 }
360
361 /* Open an existent log handle and add it to the open list.
362  * This log handle will be closed when all of the records in it are removed.
363  *
364  * Assumes caller has already pushed us into the kernel context and is locking.
365  * We return a lock on the handle to ensure nobody yanks it from us.
366  *
367  * This takes extra reference on llog_handle via llog_handle_get() and require
368  * this reference to be put by caller using llog_handle_put()
369  */
370 int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle,
371                        struct llog_handle **res, struct llog_logid *logid)
372 {
373         struct llog_handle      *loghandle;
374         enum llog_flag           fmt;
375         int                      rc = 0;
376
377         ENTRY;
378
379         if (cathandle == NULL)
380                 RETURN(-EBADF);
381
382         fmt = cathandle->lgh_hdr->llh_flags & LLOG_F_EXT_MASK;
383         down_write(&cathandle->lgh_lock);
384         list_for_each_entry(loghandle, &cathandle->u.chd.chd_head,
385                             u.phd.phd_entry) {
386                 struct llog_logid *cgl = &loghandle->lgh_id;
387
388                 if (ostid_id(&cgl->lgl_oi) == ostid_id(&logid->lgl_oi) &&
389                     ostid_seq(&cgl->lgl_oi) == ostid_seq(&logid->lgl_oi)) {
390                         if (cgl->lgl_ogen != logid->lgl_ogen) {
391                                 CWARN("%s: log "DFID" generation %x != %x\n",
392                                       loghandle2name(loghandle),
393                                       PFID(&logid->lgl_oi.oi_fid),
394                                       cgl->lgl_ogen, logid->lgl_ogen);
395                                 continue;
396                         }
397                         *res = llog_handle_get(loghandle);
398                         if (!*res) {
399                                 CERROR("%s: log "DFID" refcount is zero!\n",
400                                        loghandle2name(loghandle),
401                                        PFID(&logid->lgl_oi.oi_fid));
402                                 continue;
403                         }
404                         loghandle->u.phd.phd_cat_handle = cathandle;
405                         up_write(&cathandle->lgh_lock);
406                         RETURN(rc);
407                 }
408         }
409         up_write(&cathandle->lgh_lock);
410
411         rc = llog_open(env, cathandle->lgh_ctxt, &loghandle, logid, NULL,
412                        LLOG_OPEN_EXISTS);
413         if (rc < 0) {
414                 CERROR("%s: error opening log id "DFID":%x: rc = %d\n",
415                        loghandle2name(cathandle), PFID(&logid->lgl_oi.oi_fid),
416                        logid->lgl_ogen, rc);
417                 RETURN(rc);
418         }
419
420         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN |
421                               LLOG_F_ZAP_WHEN_EMPTY | fmt, NULL);
422         if (rc < 0) {
423                 llog_close(env, loghandle);
424                 *res = NULL;
425                 RETURN(rc);
426         }
427
428         *res = llog_handle_get(loghandle);
429         LASSERT(*res);
430         down_write(&cathandle->lgh_lock);
431         list_add_tail(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head);
432         up_write(&cathandle->lgh_lock);
433
434         loghandle->u.phd.phd_cat_handle = cathandle;
435         loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id;
436         loghandle->u.phd.phd_cookie.lgc_index =
437                                 loghandle->lgh_hdr->llh_cat_idx;
438         RETURN(0);
439 }
440
441 int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle)
442 {
443         struct llog_handle      *loghandle, *n;
444         int                      rc;
445
446         ENTRY;
447
448         list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head,
449                                  u.phd.phd_entry) {
450                 struct llog_log_hdr     *llh = loghandle->lgh_hdr;
451                 int                      index;
452
453                 /* unlink open-not-created llogs */
454                 list_del_init(&loghandle->u.phd.phd_entry);
455                 llh = loghandle->lgh_hdr;
456                 if (loghandle->lgh_obj != NULL && llh != NULL &&
457                     (llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
458                     (llh->llh_count == 1)) {
459                         rc = llog_destroy(env, loghandle);
460                         if (rc)
461                                 CERROR("%s: failure destroying log during "
462                                        "cleanup: rc = %d\n",
463                                        loghandle2name(loghandle), rc);
464
465                         index = loghandle->u.phd.phd_cookie.lgc_index;
466                         llog_cat_cleanup(env, cathandle, NULL, index);
467                 }
468                 llog_close(env, loghandle);
469         }
470         /* if handle was stored in ctxt, remove it too */
471         if (cathandle->lgh_ctxt->loc_handle == cathandle)
472                 cathandle->lgh_ctxt->loc_handle = NULL;
473         rc = llog_close(env, cathandle);
474         RETURN(rc);
475 }
476 EXPORT_SYMBOL(llog_cat_close);
477
478 /** Return the currently active log handle.  If the current log handle doesn't
479  * have enough space left for the current record, start a new one.
480  *
481  * If reclen is 0, we only want to know what the currently active log is,
482  * otherwise we get a lock on this log so nobody can steal our space.
483  *
484  * Assumes caller has already pushed us into the kernel context and is locking.
485  *
486  * NOTE: loghandle is write-locked upon successful return
487  */
488 static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle,
489                                                 struct thandle *th)
490 {
491         struct llog_handle *loghandle = NULL;
492         ENTRY;
493
494
495         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_LLOG_CREATE_FAILED2)) {
496                 down_write_nested(&cathandle->lgh_lock, LLOGH_CAT);
497                 GOTO(next, loghandle);
498         }
499
500         down_read_nested(&cathandle->lgh_lock, LLOGH_CAT);
501         loghandle = cathandle->u.chd.chd_current_log;
502         if (loghandle) {
503                 struct llog_log_hdr *llh;
504
505                 down_write_nested(&loghandle->lgh_lock, LLOGH_LOG);
506                 llh = loghandle->lgh_hdr;
507                 if (llh == NULL || !llog_is_full(loghandle)) {
508                         up_read(&cathandle->lgh_lock);
509                         RETURN(loghandle);
510                 } else {
511                         up_write(&loghandle->lgh_lock);
512                 }
513         }
514         up_read(&cathandle->lgh_lock);
515
516         /* time to use next log */
517
518         /* first, we have to make sure the state hasn't changed */
519         down_write_nested(&cathandle->lgh_lock, LLOGH_CAT);
520         loghandle = cathandle->u.chd.chd_current_log;
521         if (loghandle) {
522                 struct llog_log_hdr *llh;
523
524                 down_write_nested(&loghandle->lgh_lock, LLOGH_LOG);
525                 llh = loghandle->lgh_hdr;
526                 if (llh == NULL || !llog_is_full(loghandle))
527                         GOTO(out_unlock, loghandle);
528                 else
529                         up_write(&loghandle->lgh_lock);
530         }
531
532 next:
533         /* Sigh, the chd_next_log and chd_current_log is initialized
534          * in declare phase, and we do not serialize the catlog
535          * accessing, so it might be possible the llog creation
536          * thread (see llog_cat_declare_add_rec()) did not create
537          * llog successfully, then the following thread might
538          * meet this situation. */
539         if (IS_ERR_OR_NULL(cathandle->u.chd.chd_next_log)) {
540                 CERROR("%s: next log does not exist!\n",
541                        loghandle2name(cathandle));
542                 loghandle = ERR_PTR(-EIO);
543                 if (cathandle->u.chd.chd_next_log == NULL) {
544                         /* Store the error in chd_next_log, so
545                          * the following process can get correct
546                          * failure value */
547                         cathandle->u.chd.chd_next_log = loghandle;
548                 }
549                 GOTO(out_unlock, loghandle);
550         }
551
552         CDEBUG(D_INODE, "use next log\n");
553
554         loghandle = cathandle->u.chd.chd_next_log;
555         cathandle->u.chd.chd_current_log = loghandle;
556         cathandle->u.chd.chd_next_log = NULL;
557         down_write_nested(&loghandle->lgh_lock, LLOGH_LOG);
558
559 out_unlock:
560         up_write(&cathandle->lgh_lock);
561         LASSERT(loghandle);
562         RETURN(loghandle);
563 }
564
565 /* Add a single record to the recovery log(s) using a catalog
566  * Returns as llog_write_record
567  *
568  * Assumes caller has already pushed us into the kernel context.
569  */
570 int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
571                      struct llog_rec_hdr *rec, struct llog_cookie *reccookie,
572                      struct thandle *th)
573 {
574         struct llog_handle *loghandle;
575         int rc, retried = 0;
576         ENTRY;
577
578         LASSERT(rec->lrh_len <= cathandle->lgh_ctxt->loc_chunk_size);
579
580 retry:
581         loghandle = llog_cat_current_log(cathandle, th);
582         if (IS_ERR(loghandle))
583                 RETURN(PTR_ERR(loghandle));
584
585         /* loghandle is already locked by llog_cat_current_log() for us */
586         if (!llog_exist(loghandle)) {
587                 rc = llog_cat_new_log(env, cathandle, loghandle, th);
588                 if (rc < 0) {
589                         up_write(&loghandle->lgh_lock);
590                         /* nobody should be trying to use this llog */
591                         down_write(&cathandle->lgh_lock);
592                         if (cathandle->u.chd.chd_current_log == loghandle)
593                                 cathandle->u.chd.chd_current_log = NULL;
594                         up_write(&cathandle->lgh_lock);
595                         RETURN(rc);
596                 }
597         }
598         /* now let's try to add the record */
599         rc = llog_write_rec(env, loghandle, rec, reccookie, LLOG_NEXT_IDX, th);
600         if (rc < 0) {
601                 CDEBUG_LIMIT(rc == -ENOSPC ? D_HA : D_ERROR,
602                              "llog_write_rec %d: lh=%p\n", rc, loghandle);
603                 /* -ENOSPC is returned if no empty records left
604                  * and when it's lack of space on the stogage.
605                  * there is no point to try again if it's the second
606                  * case. many callers (like llog test) expect ENOSPC,
607                  * so we preserve this error code, but look for the
608                  * actual cause here */
609                 if (rc == -ENOSPC && llog_is_full(loghandle))
610                         rc = -ENOBUFS;
611         }
612         up_write(&loghandle->lgh_lock);
613
614         if (rc == -ENOBUFS) {
615                 if (retried++ == 0)
616                         GOTO(retry, rc);
617                 CERROR("%s: error on 2nd llog: rc = %d\n",
618                        loghandle2name(cathandle), rc);
619         }
620
621         RETURN(rc);
622 }
623 EXPORT_SYMBOL(llog_cat_add_rec);
624
625 int llog_cat_declare_add_rec(const struct lu_env *env,
626                              struct llog_handle *cathandle,
627                              struct llog_rec_hdr *rec, struct thandle *th)
628 {
629         int rc;
630
631         ENTRY;
632
633 start:
634         down_read_nested(&cathandle->lgh_lock, LLOGH_CAT);
635         rc = llog_cat_prep_log(env, cathandle,
636                                &cathandle->u.chd.chd_current_log, th);
637         if (rc)
638                 GOTO(unlock, rc);
639
640         rc = llog_cat_prep_log(env, cathandle, &cathandle->u.chd.chd_next_log,
641                                th);
642         if (rc)
643                 GOTO(unlock, rc);
644
645         rc = llog_declare_write_rec(env, cathandle->u.chd.chd_current_log,
646                                     rec, -1, th);
647         if (rc == -ESTALE && dt_object_remote(cathandle->lgh_obj)) {
648                 up_read(&cathandle->lgh_lock);
649                 rc = llog_cat_refresh(env, cathandle);
650                 if (rc)
651                         RETURN(rc);
652                 goto start;
653         }
654
655 #if 0
656         /*
657          * XXX: we hope for declarations made for existing llog this might be
658          * not correct with some backends where declarations are expected
659          * against specific object like ZFS with full debugging enabled.
660          */
661         rc = llog_declare_write_rec(env, cathandle->u.chd.chd_next_log, rec, -1,
662                                     th);
663 #endif
664 unlock:
665         up_read(&cathandle->lgh_lock);
666         RETURN(rc);
667 }
668 EXPORT_SYMBOL(llog_cat_declare_add_rec);
669
670 int llog_cat_add(const struct lu_env *env, struct llog_handle *cathandle,
671                  struct llog_rec_hdr *rec, struct llog_cookie *reccookie)
672 {
673         struct llog_ctxt        *ctxt;
674         struct dt_device        *dt;
675         struct thandle          *th = NULL;
676         int                      rc;
677
678         ctxt = cathandle->lgh_ctxt;
679         LASSERT(ctxt);
680         LASSERT(ctxt->loc_exp);
681
682         LASSERT(cathandle->lgh_obj != NULL);
683         dt = lu2dt_dev(cathandle->lgh_obj->do_lu.lo_dev);
684
685         th = dt_trans_create(env, dt);
686         if (IS_ERR(th))
687                 RETURN(PTR_ERR(th));
688
689         rc = llog_cat_declare_add_rec(env, cathandle, rec, th);
690         if (rc)
691                 GOTO(out_trans, rc);
692
693         rc = dt_trans_start_local(env, dt, th);
694         if (rc)
695                 GOTO(out_trans, rc);
696         rc = llog_cat_add_rec(env, cathandle, rec, reccookie, th);
697 out_trans:
698         dt_trans_stop(env, dt, th);
699         RETURN(rc);
700 }
701 EXPORT_SYMBOL(llog_cat_add);
702
703 int llog_cat_cancel_arr_rec(const struct lu_env *env,
704                             struct llog_handle *cathandle,
705                             struct llog_logid *lgl, int count, int *index)
706 {
707         struct llog_handle *loghandle;
708         int  rc;
709
710         ENTRY;
711         rc = llog_cat_id2handle(env, cathandle, &loghandle, lgl);
712         if (rc) {
713                 CDEBUG(D_HA, "%s: cannot find llog for handle "DFID":%x"
714                        ": rc = %d\n", loghandle2name(cathandle),
715                        PFID(&lgl->lgl_oi.oi_fid), lgl->lgl_ogen, rc);
716                 RETURN(rc);
717         }
718
719         if ((cathandle->lgh_ctxt->loc_flags &
720              LLOG_CTXT_FLAG_NORMAL_FID) && !llog_exist(loghandle)) {
721                 /* For update log, some of loghandles of cathandle
722                  * might not exist because remote llog creation might
723                  * be failed, so let's skip the record cancellation
724                  * for these non-exist llogs.
725                  */
726                 rc = -ENOENT;
727                 CDEBUG(D_HA, "%s: llog "DFID":%x does not exist"
728                        ": rc = %d\n", loghandle2name(cathandle),
729                        PFID(&lgl->lgl_oi.oi_fid), lgl->lgl_ogen, rc);
730
731                 llog_handle_put(env, loghandle);
732                 RETURN(rc);
733         }
734
735         rc = llog_cancel_arr_rec(env, loghandle, count, index);
736         if (rc == LLOG_DEL_PLAIN) { /* log has been destroyed */
737                 int cat_index;
738
739                 cat_index = loghandle->u.phd.phd_cookie.lgc_index;
740                 rc = llog_cat_cleanup(env, cathandle, loghandle, cat_index);
741                 if (rc)
742                         CERROR("%s: fail to cancel catalog record: rc = %d\n",
743                                loghandle2name(cathandle), rc);
744                 rc = 0;
745
746         }
747         llog_handle_put(env, loghandle);
748
749         if (rc)
750                 CERROR("%s: fail to cancel %d llog-records: rc = %d\n",
751                        loghandle2name(cathandle), count, rc);
752
753         RETURN(rc);
754 }
755 EXPORT_SYMBOL(llog_cat_cancel_arr_rec);
756
757 /* For each cookie in the cookie array, we clear the log in-use bit and either:
758  * - the log is empty, so mark it free in the catalog header and delete it
759  * - the log is not empty, just write out the log header
760  *
761  * The cookies may be in different log files, so we need to get new logs
762  * each time.
763  *
764  * Assumes caller has already pushed us into the kernel context.
765  */
766 int llog_cat_cancel_records(const struct lu_env *env,
767                             struct llog_handle *cathandle, int count,
768                             struct llog_cookie *cookies)
769 {
770         int i, rc = 0, failed = 0;
771
772         ENTRY;
773
774         for (i = 0; i < count; i++, cookies++) {
775                 int lrc;
776
777                 lrc = llog_cat_cancel_arr_rec(env, cathandle, &cookies->lgc_lgl,
778                                              1, &cookies->lgc_index);
779                 if (lrc) {
780                         failed++;
781                         if (!rc)
782                                 rc = lrc;
783                 }
784         }
785         if (failed)
786                 CERROR("%s: fail to cancel %d of %d llog-records: rc = %d\n",
787                        loghandle2name(cathandle), failed, count, rc);
788         RETURN(rc);
789 }
790 EXPORT_SYMBOL(llog_cat_cancel_records);
791
792 static int llog_cat_process_common(const struct lu_env *env,
793                                    struct llog_handle *cat_llh,
794                                    struct llog_rec_hdr *rec,
795                                    struct llog_handle **llhp)
796 {
797         struct llog_logid_rec *lir = container_of(rec, typeof(*lir), lid_hdr);
798         struct llog_log_hdr *hdr;
799         int rc;
800
801         ENTRY;
802         if (rec->lrh_type != le32_to_cpu(LLOG_LOGID_MAGIC)) {
803                 rc = -EINVAL;
804                 CWARN("%s: invalid record in catalog "DFID":%x: rc = %d\n",
805                       loghandle2name(cat_llh),
806                       PFID(&cat_llh->lgh_id.lgl_oi.oi_fid),
807                       cat_llh->lgh_id.lgl_ogen, rc);
808                 RETURN(rc);
809         }
810         CDEBUG(D_HA, "processing log "DFID":%x at index %u of catalog "DFID"\n",
811                PFID(&lir->lid_id.lgl_oi.oi_fid), lir->lid_id.lgl_ogen,
812                le32_to_cpu(rec->lrh_index),
813                PFID(&cat_llh->lgh_id.lgl_oi.oi_fid));
814
815         rc = llog_cat_id2handle(env, cat_llh, llhp, &lir->lid_id);
816         if (rc) {
817                 /* After a server crash, a stub of index record in catlog could
818                  * be kept, because plain log destroy + catlog index record
819                  * deletion are not atomic. So we end up with an index but no
820                  * actual record. Destroy the index and move on. */
821                 if (rc == -ENOENT || rc == -ESTALE)
822                         rc = LLOG_DEL_RECORD;
823                 else if (rc)
824                         CWARN("%s: can't find llog handle "DFID":%x: rc = %d\n",
825                               loghandle2name(cat_llh),
826                               PFID(&lir->lid_id.lgl_oi.oi_fid),
827                               lir->lid_id.lgl_ogen, rc);
828
829                 RETURN(rc);
830         }
831
832         /* clean old empty llogs, do not consider current llog in use */
833         /* ignore remote (lgh_obj == NULL) llogs */
834         hdr = (*llhp)->lgh_hdr;
835         if ((hdr->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
836             hdr->llh_count == 1 && cat_llh->lgh_obj != NULL &&
837             *llhp != cat_llh->u.chd.chd_current_log) {
838                 rc = llog_destroy(env, *llhp);
839                 if (rc)
840                         CWARN("%s: can't destroy empty log "DFID": rc = %d\n",
841                               loghandle2name((*llhp)),
842                               PFID(&lir->lid_id.lgl_oi.oi_fid), rc);
843                 rc = LLOG_DEL_PLAIN;
844         }
845
846         RETURN(rc);
847 }
848
849 static int llog_cat_process_cb(const struct lu_env *env,
850                                struct llog_handle *cat_llh,
851                                struct llog_rec_hdr *rec, void *data)
852 {
853         struct llog_process_data *d = data;
854         struct llog_handle *llh = NULL;
855         int rc;
856
857         ENTRY;
858         rc = llog_cat_process_common(env, cat_llh, rec, &llh);
859         if (rc)
860                 GOTO(out, rc);
861
862         if (rec->lrh_index < d->lpd_startcat) {
863                 /* Skip processing of the logs until startcat */
864                 rc = 0;
865         } else if (d->lpd_startidx > 0) {
866                 struct llog_process_cat_data cd;
867
868                 cd.lpcd_first_idx = d->lpd_startidx;
869                 cd.lpcd_last_idx = 0;
870                 rc = llog_process_or_fork(env, llh, d->lpd_cb, d->lpd_data,
871                                           &cd, false);
872                 /* Continue processing the next log from idx 0 */
873                 d->lpd_startidx = 0;
874         } else {
875                 rc = llog_process_or_fork(env, llh, d->lpd_cb, d->lpd_data,
876                                           NULL, false);
877         }
878         if (rc == -ENOENT && (cat_llh->lgh_hdr->llh_flags & LLOG_F_RM_ON_ERR)) {
879                 /*
880                  * plain llog is reported corrupted, so better to just remove
881                  * it if the caller is fine with that.
882                  */
883                 CERROR("%s: remove corrupted/missing llog "DFID"\n",
884                        loghandle2name(cat_llh),
885                        PFID(&llh->lgh_id.lgl_oi.oi_fid));
886                 rc = LLOG_DEL_PLAIN;
887         }
888
889 out:
890         /* The empty plain log was destroyed while processing */
891         if (rc == LLOG_DEL_PLAIN || rc == LLOG_DEL_RECORD)
892                 /* clear wrong catalog entry */
893                 rc = llog_cat_cleanup(env, cat_llh, llh, rec->lrh_index);
894
895         if (llh)
896                 llog_handle_put(env, llh);
897
898         RETURN(rc);
899 }
900
901 int llog_cat_process_or_fork(const struct lu_env *env,
902                              struct llog_handle *cat_llh, llog_cb_t cat_cb,
903                              llog_cb_t cb, void *data, int startcat,
904                              int startidx, bool fork)
905 {
906         struct llog_process_data d;
907         struct llog_log_hdr *llh = cat_llh->lgh_hdr;
908         int rc;
909
910         ENTRY;
911
912         LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
913         d.lpd_data = data;
914         d.lpd_cb = cb;
915         d.lpd_startcat = (startcat == LLOG_CAT_FIRST ? 0 : startcat);
916         d.lpd_startidx = startidx;
917
918         if (llh->llh_cat_idx >= cat_llh->lgh_last_idx &&
919             llh->llh_count > 1) {
920                 struct llog_process_cat_data cd;
921
922                 CWARN("%s: catlog "DFID" crosses index zero\n",
923                       loghandle2name(cat_llh),
924                       PFID(&cat_llh->lgh_id.lgl_oi.oi_fid));
925                 /*startcat = 0 is default value for general processing */
926                 if ((startcat != LLOG_CAT_FIRST &&
927                     startcat >= llh->llh_cat_idx) || !startcat) {
928                         /* processing the catalog part at the end */
929                         cd.lpcd_first_idx = (startcat ? startcat :
930                                              llh->llh_cat_idx);
931                         if (OBD_FAIL_PRECHECK(OBD_FAIL_CAT_RECORDS))
932                                 cd.lpcd_last_idx = cfs_fail_val;
933                         else
934                                 cd.lpcd_last_idx = 0;
935                         rc = llog_process_or_fork(env, cat_llh, cat_cb,
936                                                   &d, &cd, fork);
937                         /* Reset the startcat becasue it has already reached
938                          * catalog bottom.
939                          */
940                         startcat = 0;
941                         d.lpd_startcat = 0;
942                         if (rc != 0)
943                                 RETURN(rc);
944                 }
945                 /* processing the catalog part at the begining */
946                 cd.lpcd_first_idx = (startcat == LLOG_CAT_FIRST) ? 0 : startcat;
947                 /* Note, the processing will stop at the lgh_last_idx value,
948                  * and it could be increased during processing. So records
949                  * between current lgh_last_idx and lgh_last_idx in future
950                  * would left unprocessed.
951                  */
952                 cd.lpcd_last_idx = cat_llh->lgh_last_idx;
953                 rc = llog_process_or_fork(env, cat_llh, cat_cb,
954                                           &d, &cd, fork);
955         } else {
956                 rc = llog_process_or_fork(env, cat_llh, cat_cb,
957                                           &d, NULL, fork);
958         }
959
960         RETURN(rc);
961 }
962 EXPORT_SYMBOL(llog_cat_process_or_fork);
963
964 int llog_cat_process(const struct lu_env *env, struct llog_handle *cat_llh,
965                      llog_cb_t cb, void *data, int startcat, int startidx)
966 {
967         return llog_cat_process_or_fork(env, cat_llh, llog_cat_process_cb,
968                                         cb, data, startcat, startidx, false);
969 }
970 EXPORT_SYMBOL(llog_cat_process);
971
972 static int llog_cat_size_cb(const struct lu_env *env,
973                              struct llog_handle *cat_llh,
974                              struct llog_rec_hdr *rec, void *data)
975 {
976         struct llog_process_data *d = data;
977         struct llog_handle *llh = NULL;
978         __u64 *cum_size = d->lpd_data;
979         __u64 size;
980         int rc;
981
982         ENTRY;
983         rc = llog_cat_process_common(env, cat_llh, rec, &llh);
984
985         if (rc == LLOG_DEL_PLAIN) {
986                 /* empty log was deleted, don't count it */
987                 rc = llog_cat_cleanup(env, cat_llh, llh,
988                                       llh->u.phd.phd_cookie.lgc_index);
989         } else if (rc == LLOG_DEL_RECORD) {
990                 /* clear wrong catalog entry */
991                 rc = llog_cat_cleanup(env, cat_llh, NULL, rec->lrh_index);
992         } else {
993                 size = llog_size(env, llh);
994                 *cum_size += size;
995
996                 CDEBUG(D_INFO, "Add llog entry "DFID" size=%llu, tot=%llu\n",
997                        PFID(&llh->lgh_id.lgl_oi.oi_fid), size, *cum_size);
998         }
999
1000         if (llh != NULL)
1001                 llog_handle_put(env, llh);
1002
1003         RETURN(0);
1004 }
1005
1006 __u64 llog_cat_size(const struct lu_env *env, struct llog_handle *cat_llh)
1007 {
1008         __u64 size = llog_size(env, cat_llh);
1009
1010         llog_cat_process_or_fork(env, cat_llh, llog_cat_size_cb,
1011                                  NULL, &size, 0, 0, false);
1012
1013         return size;
1014 }
1015 EXPORT_SYMBOL(llog_cat_size);
1016
1017 /* currently returns the number of "free" entries in catalog,
1018  * ie the available entries for a new plain LLOG file creation,
1019  * even if catalog has wrapped
1020  */
1021 __u32 llog_cat_free_space(struct llog_handle *cat_llh)
1022 {
1023         /* simulate almost full Catalog */
1024         if (OBD_FAIL_CHECK(OBD_FAIL_CAT_FREE_RECORDS))
1025                 return cfs_fail_val;
1026
1027         if (cat_llh->lgh_hdr->llh_count == 1)
1028                 return LLOG_HDR_BITMAP_SIZE(cat_llh->lgh_hdr) - 1;
1029
1030         if (cat_llh->lgh_last_idx > cat_llh->lgh_hdr->llh_cat_idx)
1031                 return LLOG_HDR_BITMAP_SIZE(cat_llh->lgh_hdr) - 1 +
1032                        cat_llh->lgh_hdr->llh_cat_idx - cat_llh->lgh_last_idx;
1033
1034         /* catalog is presently wrapped */
1035         return cat_llh->lgh_hdr->llh_cat_idx - cat_llh->lgh_last_idx;
1036 }
1037 EXPORT_SYMBOL(llog_cat_free_space);
1038
1039 static int llog_cat_reverse_process_cb(const struct lu_env *env,
1040                                        struct llog_handle *cat_llh,
1041                                        struct llog_rec_hdr *rec, void *data)
1042 {
1043         struct llog_process_data *d = data;
1044         struct llog_handle *llh;
1045         int rc;
1046
1047         ENTRY;
1048         rc = llog_cat_process_common(env, cat_llh, rec, &llh);
1049
1050         /* The empty plain log was destroyed while processing */
1051         if (rc == LLOG_DEL_PLAIN) {
1052                 rc = llog_cat_cleanup(env, cat_llh, llh,
1053                                       llh->u.phd.phd_cookie.lgc_index);
1054         } else if (rc == LLOG_DEL_RECORD) {
1055                 /* clear wrong catalog entry */
1056                 rc = llog_cat_cleanup(env, cat_llh, NULL, rec->lrh_index);
1057         }
1058         if (rc)
1059                 RETURN(rc);
1060
1061         rc = llog_reverse_process(env, llh, d->lpd_cb, d->lpd_data, NULL);
1062
1063         /* The empty plain was destroyed while processing */
1064         if (rc == LLOG_DEL_PLAIN)
1065                 rc = llog_cat_cleanup(env, cat_llh, llh,
1066                                       llh->u.phd.phd_cookie.lgc_index);
1067
1068         llog_handle_put(env, llh);
1069         RETURN(rc);
1070 }
1071
1072 int llog_cat_reverse_process(const struct lu_env *env,
1073                              struct llog_handle *cat_llh,
1074                              llog_cb_t cb, void *data)
1075 {
1076         struct llog_process_data d;
1077         struct llog_process_cat_data cd;
1078         struct llog_log_hdr *llh = cat_llh->lgh_hdr;
1079         int rc;
1080         ENTRY;
1081
1082         LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
1083         d.lpd_data = data;
1084         d.lpd_cb = cb;
1085
1086         if (llh->llh_cat_idx >= cat_llh->lgh_last_idx &&
1087             llh->llh_count > 1) {
1088                 CWARN("%s: catalog "DFID" crosses index zero\n",
1089                       loghandle2name(cat_llh),
1090                       PFID(&cat_llh->lgh_id.lgl_oi.oi_fid));
1091
1092                 cd.lpcd_first_idx = 0;
1093                 cd.lpcd_last_idx = cat_llh->lgh_last_idx;
1094                 rc = llog_reverse_process(env, cat_llh,
1095                                           llog_cat_reverse_process_cb,
1096                                           &d, &cd);
1097                 if (rc != 0)
1098                         RETURN(rc);
1099
1100                 cd.lpcd_first_idx = le32_to_cpu(llh->llh_cat_idx);
1101                 cd.lpcd_last_idx = 0;
1102                 rc = llog_reverse_process(env, cat_llh,
1103                                           llog_cat_reverse_process_cb,
1104                                           &d, &cd);
1105         } else {
1106                 rc = llog_reverse_process(env, cat_llh,
1107                                           llog_cat_reverse_process_cb,
1108                                           &d, NULL);
1109         }
1110
1111         RETURN(rc);
1112 }
1113 EXPORT_SYMBOL(llog_cat_reverse_process);
1114
1115 static int llog_cat_set_first_idx(struct llog_handle *cathandle, int idx)
1116 {
1117         struct llog_log_hdr *llh = cathandle->lgh_hdr;
1118         int bitmap_size;
1119
1120         ENTRY;
1121
1122         bitmap_size = LLOG_HDR_BITMAP_SIZE(llh);
1123         /*
1124          * The llh_cat_idx equals to the first used index minus 1
1125          * so if we canceled the first index then llh_cat_idx
1126          * must be renewed.
1127          */
1128         if (llh->llh_cat_idx == (idx - 1)) {
1129                 llh->llh_cat_idx = idx;
1130
1131                 while (idx != cathandle->lgh_last_idx) {
1132                         idx = (idx + 1) % bitmap_size;
1133                         if (!test_bit_le(idx, LLOG_HDR_BITMAP(llh))) {
1134                                 /* update llh_cat_idx for each unset bit,
1135                                  * expecting the next one is set */
1136                                 llh->llh_cat_idx = idx;
1137                         } else if (idx == 0) {
1138                                 /* skip header bit */
1139                                 llh->llh_cat_idx = 0;
1140                                 continue;
1141                         } else {
1142                                 /* the first index is found */
1143                                 break;
1144                         }
1145                 }
1146
1147                 CDEBUG(D_HA, "catlog "DFID" first idx %u, last_idx %u\n",
1148                        PFID(&cathandle->lgh_id.lgl_oi.oi_fid),
1149                        llh->llh_cat_idx, cathandle->lgh_last_idx);
1150         }
1151
1152         RETURN(0);
1153 }
1154
1155 /* Cleanup deleted plain llog traces from catalog */
1156 int llog_cat_cleanup(const struct lu_env *env, struct llog_handle *cathandle,
1157                      struct llog_handle *loghandle, int index)
1158 {
1159         int rc;
1160         struct lu_fid fid = {.f_seq = 0, .f_oid = 0, .f_ver = 0};
1161
1162         LASSERT(index);
1163         if (loghandle != NULL) {
1164                 /* remove destroyed llog from catalog list and
1165                  * chd_current_log variable */
1166                 fid = loghandle->lgh_id.lgl_oi.oi_fid;
1167                 down_write(&cathandle->lgh_lock);
1168                 if (cathandle->u.chd.chd_current_log == loghandle)
1169                         cathandle->u.chd.chd_current_log = NULL;
1170                 list_del_init(&loghandle->u.phd.phd_entry);
1171                 up_write(&cathandle->lgh_lock);
1172                 LASSERT(index == loghandle->u.phd.phd_cookie.lgc_index ||
1173                         loghandle->u.phd.phd_cookie.lgc_index == 0);
1174                 /* llog was opened and keep in a list, close it now */
1175                 llog_close(env, loghandle);
1176         }
1177
1178         /* do not attempt to cleanup on-disk llog if on client side */
1179         if (cathandle->lgh_obj == NULL)
1180                 return 0;
1181
1182         /* remove plain llog entry from catalog by index */
1183         llog_cat_set_first_idx(cathandle, index);
1184         rc = llog_cancel_rec(env, cathandle, index);
1185         if (rc == 0)
1186                 CDEBUG(D_HA,
1187                        "cancel plain log "DFID" at index %u of catalog "DFID"\n",
1188                        PFID(&fid), index,
1189                        PFID(&cathandle->lgh_id.lgl_oi.oi_fid));
1190         return rc;
1191 }