static int mdd_changelog_users_seq_show(struct seq_file *m, void *data) { struct lu_env env; struct mdd_device *mdd = m->private; struct llog_ctxt *ctxt; __u64 cur; int rc; ctxt = llog_get_context(mdd2obd_dev(mdd), LLOG_CHANGELOG_USER_ORIG_CTXT); if (ctxt == NULL) return -ENXIO; LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = lu_env_init(&env, LCT_LOCAL); if (rc) { llog_ctxt_put(ctxt); return rc; } spin_lock(&mdd->mdd_cl.mc_lock); cur = mdd->mdd_cl.mc_index; spin_unlock(&mdd->mdd_cl.mc_lock); seq_printf(m, "current index: %llu\n", cur); seq_printf(m, "%-5s %s\n", "ID", "index"); llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb, m, 0, 0); lu_env_fini(&env); llog_ctxt_put(ctxt); return 0; }
static int mdd_changelog_user_purge(const struct lu_env *env, struct mdd_device *mdd, int id, long long endrec) { struct mdd_changelog_user_data data; struct llog_ctxt *ctxt; int rc; ENTRY; CDEBUG(D_IOCTL, "Purge request: id=%d, endrec=%lld\n", id, endrec); data.mcud_id = id; data.mcud_minid = 0; data.mcud_minrec = 0; data.mcud_usercount = 0; data.mcud_endrec = endrec; spin_lock(&mdd->mdd_cl.mc_lock); endrec = mdd->mdd_cl.mc_index; spin_unlock(&mdd->mdd_cl.mc_lock); if ((data.mcud_endrec == 0) || ((data.mcud_endrec > endrec) && (data.mcud_endrec != MCUD_UNREGISTER))) data.mcud_endrec = endrec; ctxt = llog_get_context(mdd2obd_dev(mdd), LLOG_CHANGELOG_USER_ORIG_CTXT); if (ctxt == NULL) return -ENXIO; LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = llog_cat_process(env, ctxt->loc_handle, mdd_changelog_user_purge_cb, (void *)&data, 0, 0); if ((rc >= 0) && (data.mcud_minrec > 0)) { CDEBUG(D_IOCTL, "Purging changelog entries up to "LPD64 ", referenced by "CHANGELOG_USER_PREFIX"%d\n", data.mcud_minrec, data.mcud_minid); rc = mdd_changelog_llog_cancel(env, mdd, data.mcud_minrec); } else { CWARN("Could not determine changelog records to purge; rc=%d\n", rc); } llog_ctxt_put(ctxt); if (!data.mcud_found) { CWARN("No entry for user %d. Last changelog reference is " LPD64" by changelog user %d\n", data.mcud_id, data.mcud_minrec, data.mcud_minid); rc = -ENOENT; } if (!rc && data.mcud_usercount == 0) /* No more users; turn changelogs off */ rc = mdd_changelog_on(env, mdd, 0); RETURN (rc); }
static int lprocfs_rd_changelog_users(char *page, char **start, off_t off, int count, int *eof, void *data) { struct lu_env env; struct mdd_device *mdd = data; struct llog_ctxt *ctxt; struct cucb_data cucb; __u64 cur; int rc; *eof = 1; ctxt = llog_get_context(mdd2obd_dev(mdd), LLOG_CHANGELOG_USER_ORIG_CTXT); if (ctxt == NULL) return -ENXIO; LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = lu_env_init(&env, LCT_LOCAL); if (rc) { llog_ctxt_put(ctxt); return rc; } spin_lock(&mdd->mdd_cl.mc_lock); cur = mdd->mdd_cl.mc_index; spin_unlock(&mdd->mdd_cl.mc_lock); cucb.count = count; cucb.page = page; cucb.idx = 0; cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, "current index: "LPU64"\n", cur); cucb.idx += snprintf(cucb.page + cucb.idx, cucb.count - cucb.idx, "%-5s %s\n", "ID", "index"); llog_cat_process(&env, ctxt->loc_handle, lprocfs_changelog_users_cb, &cucb, 0, 0); lu_env_fini(&env); llog_ctxt_put(ctxt); return cucb.idx; }
static int llog_changelog_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm, int count, struct llog_cookie *cookies, int flags) { struct llog_handle *cathandle = ctxt->loc_handle; int rc; ENTRY; /* This should only be called with the catalog handle */ LASSERT(cathandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = llog_cat_process(cathandle, llog_changelog_cancel_cb, (void *)cookies, 0, 0); if (rc >= 0) /* 0 or 1 means we're done */ rc = 0; else CERROR("cancel idx %u of catalog "LPX64" rc=%d\n", cathandle->lgh_last_idx, cathandle->lgh_id.lgl_oid, rc); RETURN(rc); }
static int llog_changelog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_cookie *cookies, int flags) { struct llog_handle *cathandle = ctxt->loc_handle; int rc; ENTRY; /* This should only be called with the catalog handle */ LASSERT(cathandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT); rc = llog_cat_process(env, cathandle, llog_changelog_cancel_cb, (void *)cookies, 0, 0); if (rc >= 0) /* 0 or 1 means we're done */ rc = 0; else CERROR("%s: cancel idx %u of catalog "DOSTID" rc=%d\n", ctxt->loc_obd->obd_name, cathandle->lgh_last_idx, POSTID(&cathandle->lgh_id.lgl_oi), rc); RETURN(rc); }
/* Test log and catalogue processing */ static int llog_test_5(const struct lu_env *env, struct obd_device *obd) { struct llog_handle *llh = NULL; char name[10]; int rc, rc2; struct llog_mini_rec lmr; struct llog_ctxt *ctxt; 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; CWARN("5a: re-open catalog by id\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("5a: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("5a: can't init llog handle: %d\n", rc); GOTO(out, rc); } CWARN("5b: print the catalog entries.. we expect 2\n"); cat_counter = 0; rc = llog_process(env, llh, cat_print_cb, "test 5", NULL); if (rc) { CERROR("5b: process with cat_print_cb failed: %d\n", rc); GOTO(out, rc); } if (cat_counter != 2) { CERROR("5b: %d entries in catalog\n", cat_counter); GOTO(out, rc = -EINVAL); } CWARN("5c: Cancel %d records, see one log zapped\n", LLOG_TEST_RECNUM); cancel_count = 0; rc = llog_cat_process(env, llh, llog_cancel_rec_cb, "foobar", 0, 0); if (rc != -LLOG_EEMPTY) { CERROR("5c: process with cat_cancel_cb failed: %d\n", rc); GOTO(out, rc); } CWARN("5c: print the catalog entries.. we expect 1\n"); cat_counter = 0; rc = llog_process(env, llh, cat_print_cb, "test 5", NULL); if (rc) { CERROR("5c: process with cat_print_cb failed: %d\n", rc); GOTO(out, rc); } if (cat_counter != 1) { CERROR("5c: %d entries in catalog\n", cat_counter); GOTO(out, rc = -EINVAL); } CWARN("5d: add 1 record to the log with many canceled empty pages\n"); rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL, NULL); if (rc) { CERROR("5d: add record to the log with many canceled empty " "pages failed\n"); GOTO(out, rc); } CWARN("5e: print plain log entries.. expect 6\n"); plain_counter = 0; rc = llog_cat_process(env, llh, plain_print_cb, "foobar", 0, 0); if (rc) { CERROR("5e: process with plain_print_cb failed: %d\n", rc); GOTO(out, rc); } if (plain_counter != 6) { CERROR("5e: found %d records\n", plain_counter); GOTO(out, rc = -EINVAL); } CWARN("5f: print plain log entries reversely.. expect 6\n"); plain_counter = 0; rc = llog_cat_reverse_process(env, llh, plain_print_cb, "foobar"); if (rc) { CERROR("5f: reversely process with plain_print_cb failed:" "%d\n", rc); GOTO(out, rc); } if (plain_counter != 6) { CERROR("5f: found %d records\n", plain_counter); GOTO(out, rc = -EINVAL); } out: CWARN("5g: close re-opened catalog\n"); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("5g: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; } out_put: llog_ctxt_put(ctxt); return rc; }
/* Test log and catalogue processing */ static int llog_test_5(struct obd_device *obd) { struct llog_handle *llh = NULL; char name[10]; int rc; struct llog_mini_rec lmr; struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); ENTRY; lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE; lmr.lmr_hdr.lrh_type = 0xf00f00; CWARN("5a: re-open catalog by id\n"); rc = llog_create(ctxt, &llh, &cat_logid, NULL); if (rc) { CERROR("5a: llog_create with logid failed: %d\n", rc); GOTO(out, rc); } llog_init_handle(llh, LLOG_F_IS_CAT, &uuid); CWARN("5b: print the catalog entries.. we expect 2\n"); rc = llog_process(llh, cat_print_cb, "test 5", NULL); if (rc) { CERROR("5b: process with cat_print_cb failed: %d\n", rc); GOTO(out, rc); } CWARN("5c: Cancel 40000 records, see one log zapped\n"); rc = llog_cat_process(llh, llog_cancel_rec_cb, "foobar", 0, 0); if (rc != -4711) { CERROR("5c: process with cat_cancel_cb failed: %d\n", rc); GOTO(out, rc); } CWARN("5d: add 1 record to the log with many canceled empty pages\n"); rc = llog_cat_add_rec(llh, &lmr.lmr_hdr, NULL, NULL); if (rc) { CERROR("5d: add record to the log with many canceled empty\ pages failed\n"); GOTO(out, rc); } CWARN("5b: print the catalog entries.. we expect 1\n"); rc = llog_process(llh, cat_print_cb, "test 5", NULL); if (rc) { CERROR("5b: process with cat_print_cb failed: %d\n", rc); GOTO(out, rc); } CWARN("5e: print plain log entries.. expect 6\n"); rc = llog_cat_process(llh, plain_print_cb, "foobar", 0, 0); if (rc) { CERROR("5e: process with plain_print_cb failed: %d\n", rc); GOTO(out, rc); } CWARN("5f: print plain log entries reversely.. expect 6\n"); rc = llog_cat_reverse_process(llh, plain_print_cb, "foobar"); if (rc) { CERROR("5f: reversely process with plain_print_cb failed: %d\n", rc); GOTO(out, rc); } out: CWARN("5: close re-opened catalog\n"); if (llh) rc = llog_cat_put(llh); if (rc) CERROR("1b: close log %s failed: %d\n", name, rc); llog_ctxt_put(ctxt); RETURN(rc); }
static int llog_test_8(const struct lu_env *env, struct obd_device *obd) { struct llog_handle *llh = NULL; char name[10]; int rc, rc2, i; int orig_counter; struct llog_mini_rec lmr; struct llog_ctxt *ctxt; struct dt_object *obj = NULL; ENTRY; 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; CWARN("8a: fill the first plain llog\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8a: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8a: can't init llog handle: %d\n", rc); GOTO(out, rc); } plain_counter = 0; rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0); if (rc != 0) { CERROR("5a: process with test_8_cb failed: %d\n", rc); GOTO(out, rc); } orig_counter = plain_counter; for (i = 0; i < 100; i++) { rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL); if (rc) { CERROR("5a: add record failed\n"); GOTO(out, rc); } } /* grab the current plain llog, we'll corrupt it later */ obj = llh->u.chd.chd_current_log->lgh_obj; LASSERT(obj); lu_object_get(&obj->do_lu); CWARN("8a: pin llog "DFID"\n", PFID(lu_object_fid(&obj->do_lu))); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8a: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; GOTO(out_put, rc); } CWARN("8b: fill the second plain llog\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8b: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8b: can't init llog handle: %d\n", rc); GOTO(out, rc); } for (i = 0; i < 100; i++) { rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL); if (rc) { CERROR("8b: add record failed\n"); GOTO(out, rc); } } CWARN("8b: second llog "DFID"\n", PFID(lu_object_fid(&llh->u.chd.chd_current_log->lgh_obj->do_lu))); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8b: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; GOTO(out_put, rc); } CWARN("8c: drop two records from the first plain llog\n"); llog_truncate(env, obj); CWARN("8d: count survived records\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8d: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8d: can't init llog handle: %d\n", rc); GOTO(out, rc); } plain_counter = 0; rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0); if (rc != 0) { CERROR("8d: process with test_8_cb failed: %d\n", rc); GOTO(out, rc); } if (orig_counter + 200 - 2 != plain_counter) { CERROR("found %d records (expected %d)\n", plain_counter, orig_counter + 200 - 2); rc = -EIO; } out: CWARN("8d: close re-opened catalog\n"); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8d: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; } out_put: llog_ctxt_put(ctxt); if (obj != NULL) lu_object_put(env, &obj->do_lu); RETURN(rc); }