+ ENTRY;
+ if (rec->lrh_type != LLOG_LOGID_MAGIC) {
+ CERROR("invalid record in catalog\n");
+ RETURN(-EINVAL);
+ }
+ CDEBUG(D_HA, "processing log "LPX64":%x at index %u of catalog "
+ LPX64"\n", lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
+ rec->lrh_index, cat_llh->lgh_id.lgl_oid);
+
+ rc = llog_cat_id2handle(cat_llh, &llh, &lir->lid_id);
+ if (rc) {
+ CERROR("Cannot find handle for log "LPX64"\n",
+ lir->lid_id.lgl_oid);
+ RETURN(rc);
+ }
+
+ if (rec->lrh_index < d->lpd_startcat)
+ /* Skip processing of the logs until startcat */
+ RETURN(0);
+
+ if (d->lpd_startidx > 0) {
+ struct llog_process_cat_data cd;
+
+ cd.lpcd_first_idx = d->lpd_startidx;
+ cd.lpcd_last_idx = 0;
+ rc = llog_process_flags(llh, d->lpd_cb, d->lpd_data, &cd,
+ d->lpd_flags);
+ /* Continue processing the next log from idx 0 */
+ d->lpd_startidx = 0;
+ } else {
+ rc = llog_process_flags(llh, d->lpd_cb, d->lpd_data, NULL,
+ d->lpd_flags);
+ }
+
+ RETURN(rc);
+}
+
+int llog_cat_process_flags(struct llog_handle *cat_llh, llog_cb_t cb,
+ void *data, int flags, int startcat, int startidx)
+{
+ struct llog_process_data d;
+ struct llog_log_hdr *llh = cat_llh->lgh_hdr;
+ int rc;
+ ENTRY;
+
+ LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
+ d.lpd_data = data;
+ d.lpd_cb = cb;
+ d.lpd_startcat = startcat;
+ d.lpd_startidx = startidx;
+ d.lpd_flags = flags;
+
+ if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
+ struct llog_process_cat_data cd;
+
+ CWARN("catlog "LPX64" crosses index zero\n",
+ cat_llh->lgh_id.lgl_oid);
+
+ cd.lpcd_first_idx = llh->llh_cat_idx;
+ cd.lpcd_last_idx = 0;
+ rc = llog_process_flags(cat_llh, llog_cat_process_cb, &d, &cd,
+ flags);
+ if (rc != 0)
+ RETURN(rc);
+
+ cd.lpcd_first_idx = 0;
+ cd.lpcd_last_idx = cat_llh->lgh_last_idx;
+ rc = llog_process_flags(cat_llh, llog_cat_process_cb, &d, &cd,
+ flags);
+ } else {
+ rc = llog_process_flags(cat_llh, llog_cat_process_cb, &d, NULL,
+ flags);
+ }
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_cat_process_flags);
+
+int llog_cat_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data,
+ int startcat, int startidx)
+{
+ return llog_cat_process_flags(cat_llh, cb, data, 0, startcat, startidx);
+}
+EXPORT_SYMBOL(llog_cat_process);
+
+#ifdef __KERNEL__
+int llog_cat_process_thread(void *data)
+{
+ struct llog_process_cat_args *args = data;
+ struct llog_ctxt *ctxt = args->lpca_ctxt;
+ struct llog_handle *llh = NULL;
+ llog_cb_t cb = args->lpca_cb;
+ struct llog_logid logid;
+ int rc;
+ ENTRY;
+
+ cfs_daemonize_ctxt("ll_log_process");
+
+ logid = *(struct llog_logid *)(args->lpca_arg);
+ rc = llog_create(ctxt, &llh, &logid, NULL);
+ if (rc) {
+ CERROR("llog_create() failed %d\n", rc);
+ GOTO(out, rc);
+ }
+ rc = llog_init_handle(llh, LLOG_F_IS_CAT, NULL);
+ if (rc) {
+ CERROR("llog_init_handle failed %d\n", rc);
+ GOTO(release_llh, rc);
+ }
+
+ if (cb) {
+ rc = llog_cat_process(llh, cb, NULL, 0, 0);
+ if (rc != LLOG_PROC_BREAK && rc != 0)
+ CERROR("llog_cat_process() failed %d\n", rc);
+ cb(llh, NULL, NULL);
+ } else {
+ CWARN("No callback function for recovery\n");
+ }
+
+ /*
+ * Make sure that all cached data is sent.
+ */
+ llog_sync(ctxt, NULL, 0);
+ GOTO(release_llh, rc);
+release_llh:
+ rc = llog_cat_put(llh);
+ if (rc)
+ CERROR("llog_cat_put() failed %d\n", rc);
+out:
+ llog_ctxt_put(ctxt);
+ OBD_FREE_PTR(args);
+ return rc;
+}
+EXPORT_SYMBOL(llog_cat_process_thread);
+#endif
+
+static int llog_cat_reverse_process_cb(struct llog_handle *cat_llh,
+ struct llog_rec_hdr *rec, void *data)
+{
+ struct llog_process_data *d = data;
+ struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
+ struct llog_handle *llh;
+ int rc;
+