/** * set llog methods and create LLOG_AGENT_ORIG_CTXT llog * object in obd_device */ static int mdd_hsm_actions_llog_init(const struct lu_env *env, struct mdd_device *m) { struct obd_device *obd = mdd2obd_dev(m); struct llog_ctxt *ctxt = NULL; int rc; ENTRY; OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt); obd->obd_lvfs_ctxt.dt = m->mdd_bottom; rc = llog_setup(env, obd, &obd->obd_olg, LLOG_AGENT_ORIG_CTXT, obd, &hsm_actions_logops); if (rc) { CERROR("%s: hsm actions llog setup failed: rc = %d\n", obd->obd_name, rc); RETURN(rc); } ctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT); LASSERT(ctxt); rc = llog_open_create(env, ctxt, &ctxt->loc_handle, NULL, HSM_ACTIONS); if (rc) { CERROR("%s: hsm actions llog open_create failed: rc = %d\n", obd->obd_name, rc); GOTO(out_cleanup, rc); } rc = llog_cat_init_and_process(env, ctxt->loc_handle); if (rc) GOTO(out_close, rc); llog_ctxt_put(ctxt); RETURN(0); out_close: llog_cat_close(env, ctxt->loc_handle); ctxt->loc_handle = NULL; out_cleanup: llog_cleanup(env, ctxt); return rc; }
/* Test named-log create/open, close */ static int llog_test_1(const struct lu_env *env, struct obd_device *obd, char *name) { struct llog_handle *llh; struct llog_ctxt *ctxt; int rc; int rc2; ENTRY; CWARN("1a: create a log with name: %s\n", name); ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); rc = llog_open_create(env, ctxt, &llh, NULL, name); if (rc) { CERROR("1a: llog_create with name %s failed: %d\n", name, rc); GOTO(out, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, &uuid); if (rc) { CERROR("1a: can't init llog handle: %d\n", rc); GOTO(out_close, rc); } rc = verify_handle("1", llh, 1); CWARN("1b: close newly-created log\n"); out_close: rc2 = llog_close(env, llh); if (rc2) { CERROR("1b: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; } out: llog_ctxt_put(ctxt); RETURN(rc); }
static int llog_test_7_sub(const struct lu_env *env, struct llog_ctxt *ctxt) { struct llog_handle *llh; int rc = 0, i, process_count; int num_recs = 0; rc = llog_open_create(env, ctxt, &llh, NULL, NULL); if (rc) { CERROR("7_sub: create log failed\n"); return rc; } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN | LLOG_F_ZAP_WHEN_EMPTY, &uuid); if (rc) { CERROR("7_sub: can't init llog handle: %d\n", rc); GOTO(out_close, rc); } for (i = 0; i < LLOG_BITMAP_SIZE(llh->lgh_hdr); i++) { rc = llog_write(env, llh, &llog_records.lrh, NULL, 0, NULL, -1); if (rc == -ENOSPC) { break; } else if (rc < 0) { CERROR("7_sub: write recs failed at #%d: %d\n", i + 1, rc); GOTO(out_close, rc); } num_recs++; } if (rc != -ENOSPC) { CWARN("7_sub: write record more than BITMAP size!\n"); GOTO(out_close, rc = -EINVAL); } rc = verify_handle("7_sub", llh, num_recs + 1); if (rc) { CERROR("7_sub: verify handle failed: %d\n", rc); GOTO(out_close, rc); } if (num_recs < LLOG_BITMAP_SIZE(llh->lgh_hdr) - 1) CWARN("7_sub: records are not aligned, written %d from %u\n", num_recs, LLOG_BITMAP_SIZE(llh->lgh_hdr) - 1); plain_counter = 0; rc = llog_process(env, llh, test_7_print_cb, "test 7", NULL); if (rc) { CERROR("7_sub: llog process failed: %d\n", rc); GOTO(out_close, rc); } process_count = plain_counter; if (process_count != num_recs) { CERROR("7_sub: processed %d records from %d total\n", process_count, num_recs); GOTO(out_close, rc = -EINVAL); } plain_counter = 0; rc = llog_reverse_process(env, llh, test_7_cancel_cb, "test 7", NULL); if (rc) { CERROR("7_sub: reverse llog process failed: %d\n", rc); GOTO(out_close, rc); } if (process_count != plain_counter) { CERROR("7_sub: Reverse/direct processing found different" "number of records: %d/%d\n", plain_counter, process_count); GOTO(out_close, rc = -EINVAL); } if (llog_exist(llh)) { CERROR("7_sub: llog exists but should be zapped\n"); GOTO(out_close, rc = -EEXIST); } rc = verify_handle("7_sub", llh, 1); out_close: if (rc) llog_destroy(env, llh); llog_close(env, llh); return rc; }
/* Test catalogue additions */ static int llog_test_4(const struct lu_env *env, struct obd_device *obd) { struct llog_handle *cath; char name[10]; int rc, rc2, i, buflen; struct llog_mini_rec lmr; struct llog_cookie cookie; struct llog_ctxt *ctxt; int num_recs = 0; char *buf; struct llog_rec_hdr rec; ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE; lmr.lmr_hdr.lrh_type = 0xf00f00; sprintf(name, "%x", llog_test_rand + 1); CWARN("4a: create a catalog log with name: %s\n", name); rc = llog_open_create(env, ctxt, &cath, NULL, name); if (rc) { CERROR("4a: llog_create with name %s failed: %d\n", name, rc); GOTO(ctxt_release, rc); } rc = llog_init_handle(env, cath, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("4a: can't init llog handle: %d\n", rc); GOTO(out, rc); } num_recs++; cat_logid = cath->lgh_id; CWARN("4b: write 1 record into the catalog\n"); rc = llog_cat_add(env, cath, &lmr.lmr_hdr, &cookie, NULL); if (rc != 1) { CERROR("4b: write 1 catalog record failed at: %d\n", rc); GOTO(out, rc); } num_recs++; rc = verify_handle("4b", cath, 2); if (rc) GOTO(out, rc); rc = verify_handle("4b", cath->u.chd.chd_current_log, num_recs); if (rc) GOTO(out, rc); CWARN("4c: cancel 1 log record\n"); rc = llog_cat_cancel_records(env, cath, 1, &cookie); if (rc) { CERROR("4c: cancel 1 catalog based record failed: %d\n", rc); GOTO(out, rc); } num_recs--; rc = verify_handle("4c", cath->u.chd.chd_current_log, num_recs); if (rc) GOTO(out, rc); CWARN("4d: write %d more log records\n", LLOG_TEST_RECNUM); for (i = 0; i < LLOG_TEST_RECNUM; i++) { rc = llog_cat_add(env, cath, &lmr.lmr_hdr, NULL, NULL); if (rc) { CERROR("4d: write %d records failed at #%d: %d\n", LLOG_TEST_RECNUM, i + 1, rc); GOTO(out, rc); } num_recs++; } /* make sure new plain llog appears */ rc = verify_handle("4d", cath, 3); if (rc) GOTO(out, rc); CWARN("4e: add 5 large records, one record per block\n"); buflen = LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr) - sizeof(struct llog_rec_tail); OBD_ALLOC(buf, buflen); if (buf == NULL) GOTO(out, rc = -ENOMEM); for (i = 0; i < 5; i++) { rec.lrh_len = buflen; rec.lrh_type = OBD_CFG_REC; rc = llog_cat_add(env, cath, &rec, NULL, buf); if (rc) { CERROR("4e: write 5 records failed at #%d: %d\n", i + 1, rc); GOTO(out_free, rc); } num_recs++; } out_free: OBD_FREE(buf, buflen); out: CWARN("4f: put newly-created catalog\n"); rc2 = llog_cat_close(env, cath); if (rc2) { CERROR("4: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; } ctxt_release: llog_ctxt_put(ctxt); return rc; }
/* Test named-log reopen; returns opened log on success */ static int llog_test_2(const struct lu_env *env, struct obd_device *obd, char *name, struct llog_handle **llh) { struct llog_ctxt *ctxt; struct llog_handle *loghandle; struct llog_logid logid; int rc; CWARN("2a: re-open a log with name: %s\n", name); ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); rc = llog_open(env, ctxt, llh, NULL, name, LLOG_OPEN_EXISTS); if (rc) { CERROR("2a: re-open log with name %s failed: %d\n", name, rc); GOTO(out_put, rc); } rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &uuid); if (rc) { CERROR("2a: can't init llog handle: %d\n", rc); GOTO(out_close_llh, rc); } rc = verify_handle("2", *llh, 1); if (rc) GOTO(out_close_llh, rc); /* XXX: there is known issue with tests 2b, MGS is not able to create * anonymous llog, exit now to allow following tests run. * It is fixed in upcoming llog over OSD code */ GOTO(out_put, rc); CWARN("2b: create a log without specified NAME & LOGID\n"); rc = llog_open_create(env, ctxt, &loghandle, NULL, NULL); if (rc) { CERROR("2b: create log failed\n"); GOTO(out_close_llh, rc); } rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, &uuid); if (rc) { CERROR("2b: can't init llog handle: %d\n", rc); GOTO(out_close, rc); } logid = loghandle->lgh_id; llog_close(env, loghandle); CWARN("2c: re-open the log by LOGID\n"); rc = llog_open(env, ctxt, &loghandle, &logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("2c: re-open log by LOGID failed\n"); GOTO(out_close_llh, rc); } rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, &uuid); if (rc) { CERROR("2c: can't init llog handle: %d\n", rc); GOTO(out_close, rc); } CWARN("2b: destroy this log\n"); rc = llog_destroy(env, loghandle); if (rc) CERROR("2d: destroy log failed\n"); out_close: llog_close(env, loghandle); out_close_llh: if (rc) llog_close(env, *llh); out_put: llog_ctxt_put(ctxt); return rc; }
/* backup plain llog */ int llog_backup(const struct lu_env *env, struct obd_device *obd, struct llog_ctxt *ctxt, struct llog_ctxt *bctxt, char *name, char *backup) { struct llog_handle *llh, *bllh; int rc; /* open original log */ rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); if (rc < 0) { /* the -ENOENT case is also reported to the caller * but silently so it should handle that if needed. */ if (rc != -ENOENT) CERROR("%s: failed to open log %s: rc = %d\n", obd->obd_name, name, rc); return rc; } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); if (rc) GOTO(out_close, rc); /* Make sure there's no old backup log */ rc = llog_erase(env, bctxt, NULL, backup); if (rc < 0 && rc != -ENOENT) GOTO(out_close, rc); /* open backup log */ rc = llog_open_create(env, bctxt, &bllh, NULL, backup); if (rc) { CERROR("%s: failed to open backup logfile %s: rc = %d\n", obd->obd_name, backup, rc); GOTO(out_close, rc); } /* check that backup llog is not the same object as original one */ if (llh->lgh_obj == bllh->lgh_obj) { CERROR("%s: backup llog %s to itself (%s), objects %p/%p\n", obd->obd_name, name, backup, llh->lgh_obj, bllh->lgh_obj); GOTO(out_backup, rc = -EEXIST); } rc = llog_init_handle(env, bllh, LLOG_F_IS_PLAIN, NULL); if (rc) GOTO(out_backup, rc); /* Copy log record by record */ rc = llog_process_or_fork(env, llh, llog_copy_handler, (void *)bllh, NULL, false); if (rc) CERROR("%s: failed to backup log %s: rc = %d\n", obd->obd_name, name, rc); out_backup: llog_close(env, bllh); out_close: llog_close(env, llh); return rc; }
static int mdd_changelog_llog_init(const struct lu_env *env, struct mdd_device *mdd) { struct obd_device *obd = mdd2obd_dev(mdd); struct llog_ctxt *ctxt = NULL, *uctxt = NULL; int rc; ENTRY; /* LU-2844 mdd setup failure should not cause umount oops */ if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CHANGELOG_INIT)) RETURN(-EIO); OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt); obd->obd_lvfs_ctxt.dt = mdd->mdd_bottom; rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CHANGELOG_ORIG_CTXT, obd, &changelog_orig_logops); if (rc) { CERROR("%s: changelog llog setup failed: rc = %d\n", obd->obd_name, rc); RETURN(rc); } ctxt = llog_get_context(obd, LLOG_CHANGELOG_ORIG_CTXT); LASSERT(ctxt); rc = llog_open_create(env, ctxt, &ctxt->loc_handle, NULL, CHANGELOG_CATALOG); if (rc) GOTO(out_cleanup, rc); rc = llog_cat_init_and_process(env, ctxt->loc_handle); if (rc) GOTO(out_close, rc); rc = llog_cat_reverse_process(env, ctxt->loc_handle, changelog_init_cb, mdd); if (rc < 0) { CERROR("%s: changelog init failed: rc = %d\n", obd->obd_name, rc); GOTO(out_close, rc); } CDEBUG(D_IOCTL, "changelog starting index="LPU64"\n", mdd->mdd_cl.mc_index); /* setup user changelog */ rc = llog_setup(env, obd, &obd->obd_olg, LLOG_CHANGELOG_USER_ORIG_CTXT, obd, &changelog_orig_logops); if (rc) { CERROR("%s: changelog users llog setup failed: rc = %d\n", obd->obd_name, rc); GOTO(out_close, rc); } uctxt = llog_get_context(obd, LLOG_CHANGELOG_USER_ORIG_CTXT); LASSERT(ctxt); rc = llog_open_create(env, uctxt, &uctxt->loc_handle, NULL, CHANGELOG_USERS); if (rc) GOTO(out_ucleanup, rc); uctxt->loc_handle->lgh_logops->lop_add = llog_cat_add_rec; uctxt->loc_handle->lgh_logops->lop_declare_add = llog_cat_declare_add_rec; rc = llog_cat_init_and_process(env, uctxt->loc_handle); if (rc) GOTO(out_uclose, rc); rc = llog_cat_reverse_process(env, uctxt->loc_handle, changelog_user_init_cb, mdd); if (rc < 0) { CERROR("%s: changelog user init failed: rc = %d\n", obd->obd_name, rc); GOTO(out_uclose, rc); } /* If we have registered users, assume we want changelogs on */ if (mdd->mdd_cl.mc_lastuser > 0) { rc = mdd_changelog_on(env, mdd, 1); if (rc < 0) GOTO(out_uclose, rc); } llog_ctxt_put(ctxt); llog_ctxt_put(uctxt); RETURN(0); out_uclose: llog_cat_close(env, uctxt->loc_handle); out_ucleanup: llog_cleanup(env, uctxt); out_close: llog_cat_close(env, ctxt->loc_handle); out_cleanup: llog_cleanup(env, ctxt); return rc; }