static int llog_origin_close(const struct lu_env *env, struct llog_handle *lgh) { if (lgh->lgh_hdr != NULL && lgh->lgh_hdr->llh_flags & LLOG_F_IS_CAT) return llog_cat_close(env, lgh); else return llog_close(env, lgh); }
/** * Helper function to delete existent llog. */ int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_logid *logid, char *name) { struct llog_handle *handle; int rc = 0, rc2; ENTRY; /* nothing to erase */ if (name == NULL && logid == NULL) RETURN(0); rc = llog_open(env, ctxt, &handle, logid, name, LLOG_OPEN_EXISTS); if (rc < 0) RETURN(rc); rc = llog_init_handle(env, handle, LLOG_F_IS_PLAIN, NULL); if (rc == 0) rc = llog_destroy(env, handle); rc2 = llog_close(env, handle); if (rc == 0) rc = rc2; RETURN(rc); }
/** * Helper function to get the llog size in records. It is used by MGS * mostly to check that config llog exists and contains data. * * \param[in] env execution environment * \param[in] ctxt llog context * \param[in] name llog name * * \retval true if there are records in llog besides a header * \retval false on error or llog without records */ int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt, char *name) { struct llog_handle *llh; int rc = 0; rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); if (rc < 0) { if (likely(rc == -ENOENT)) rc = 0; GOTO(out, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); if (rc) GOTO(out_close, rc); rc = llog_get_size(llh); out_close: llog_close(env, llh); out: /* The header is record 1, the llog is still considered as empty * if there is only header */ return (rc <= 1); }
static int llog_catinfo_cb(struct llog_handle *cat, struct llog_rec_hdr *rec, void *data) { static char *out = NULL; static int remains = 0; struct llog_ctxt *ctxt = NULL; struct llog_handle *handle = NULL; struct llog_logid *logid; struct llog_logid_rec *lir; int l, rc, index, count = 0; struct cb_data *cbd = (struct cb_data*)data; ENTRY; if (cbd->init) { out = cbd->out; remains = cbd->remains; cbd->init = 0; } if (!(cat->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) RETURN(-EINVAL); if (!cbd->ctxt) RETURN(-ENODEV); lir = (struct llog_logid_rec *)rec; logid = &lir->lid_id; rc = llog_create(ctxt, &handle, logid, NULL); if (rc) RETURN(-EINVAL); rc = llog_init_handle(handle, 0, NULL); if (rc) GOTO(out_close, rc); for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index++) { if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap)) count++; } l = snprintf(out, remains, "\t[Log ID]: #"LPX64"#"LPX64"#%08x\n" "\tLog Size: %llu\n\tLast Index: %d\n" "\tUncanceled Records: %d\n", logid->lgl_oid, logid->lgl_oseq, logid->lgl_ogen, i_size_read(handle->lgh_file->f_dentry->d_inode), handle->lgh_last_idx, count); out += l; remains -= l; cbd->out = out; cbd->remains = remains; if (remains <= 0) { CWARN("Not enough memory\n"); rc = -ENOMEM; } EXIT; out_close: llog_close(handle); return rc; }
int llog_origin_handle_create(struct ptlrpc_request *req) { struct obd_export *exp = req->rq_export; struct obd_device *obd = exp->exp_obd; struct obd_device *disk_obd; struct llog_handle *loghandle; struct llogd_body *body; struct lvfs_run_ctxt saved; struct llog_logid *logid = NULL; struct llog_ctxt *ctxt; char *name = NULL; int rc, rc2; ENTRY; body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); if (body->lgd_logid.lgl_oid > 0) logid = &body->lgd_logid; if (req_capsule_field_present(&req->rq_pill, &RMF_NAME, RCL_CLIENT)) { name = req_capsule_client_get(&req->rq_pill, &RMF_NAME); if (name == NULL) RETURN(-EFAULT); CDEBUG(D_INFO, "%s: opening log %s\n", obd->obd_name, name); } ctxt = llog_get_context(obd, body->lgd_ctxt_idx); if (ctxt == NULL) { CDEBUG(D_WARNING, "%s: no ctxt. group=%p idx=%d name=%s\n", obd->obd_name, &obd->obd_olg, body->lgd_ctxt_idx, name); RETURN(-ENODEV); } disk_obd = ctxt->loc_exp->exp_obd; push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); rc = llog_create(ctxt, &loghandle, logid, name); if (rc) GOTO(out_pop, rc); rc = req_capsule_server_pack(&req->rq_pill); if (rc) GOTO(out_close, rc = -ENOMEM); body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); body->lgd_logid = loghandle->lgh_id; GOTO(out_close, rc); out_close: rc2 = llog_close(loghandle); if (!rc) rc = rc2; out_pop: pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); llog_ctxt_put(ctxt); return rc; }
/* ------------------------------------------------------------------------- * Tests above, boring obd functions below * ------------------------------------------------------------------------- */ static int llog_run_tests(const struct lu_env *env, struct obd_device *obd) { struct llog_handle *llh = NULL; struct llog_ctxt *ctxt; int rc, err; char name[10]; ENTRY; ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); sprintf(name, "%x", llog_test_rand); rc = llog_test_1(env, obd, name); if (rc) GOTO(cleanup_ctxt, rc); rc = llog_test_2(env, obd, name, &llh); if (rc) GOTO(cleanup_ctxt, rc); rc = llog_test_3(env, obd, llh); if (rc) GOTO(cleanup, rc); rc = llog_test_4(env, obd); if (rc) GOTO(cleanup, rc); rc = llog_test_5(env, obd); if (rc) GOTO(cleanup, rc); rc = llog_test_6(env, obd, name); if (rc) GOTO(cleanup, rc); rc = llog_test_7(env, obd); if (rc) GOTO(cleanup, rc); rc = llog_test_8(env, obd); if (rc) GOTO(cleanup, rc); cleanup: err = llog_destroy(env, llh); if (err) CERROR("cleanup: llog_destroy failed: %d\n", err); llog_close(env, llh); if (rc == 0) rc = err; cleanup_ctxt: llog_ctxt_put(ctxt); return rc; }
/* ------------------------------------------------------------------------- * Tests above, boring obd functions below * ------------------------------------------------------------------------- */ static int llog_run_tests(struct obd_device *obd) { struct llog_handle *llh; struct lvfs_run_ctxt saved; struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); int rc, err, cleanup_phase = 0; char name[10]; ENTRY; sprintf(name, "%x", llog_test_rand); push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); rc = llog_test_1(obd, name); if (rc) GOTO(cleanup, rc); rc = llog_test_2(obd, name, &llh); if (rc) GOTO(cleanup, rc); cleanup_phase = 1; /* close llh */ rc = llog_test_3(obd, llh); if (rc) GOTO(cleanup, rc); rc = llog_test_4(obd); if (rc) GOTO(cleanup, rc); rc = llog_test_5(obd); if (rc) GOTO(cleanup, rc); rc = llog_test_6(obd, name); if (rc) GOTO(cleanup, rc); rc = llog_test_7(obd); if (rc) GOTO(cleanup, rc); cleanup: switch (cleanup_phase) { case 1: err = llog_close(llh); if (err) CERROR("cleanup: llog_close failed: %d\n", err); if (!rc) rc = err; case 0: pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); } llog_ctxt_put(ctxt); return rc; }
int llog_origin_handle_read_header(struct ptlrpc_request *req) { struct obd_export *exp = req->rq_export; struct obd_device *obd = exp->exp_obd; struct obd_device *disk_obd; struct llog_handle *loghandle; struct llogd_body *body; struct llog_log_hdr *hdr; struct lvfs_run_ctxt saved; struct llog_ctxt *ctxt; __u32 flags; int rc, rc2; ENTRY; body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); ctxt = llog_get_context(obd, body->lgd_ctxt_idx); if (ctxt == NULL) RETURN(-ENODEV); disk_obd = ctxt->loc_exp->exp_obd; push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL); if (rc) GOTO(out_pop, rc); /* * llog_init_handle() reads the llog header */ flags = body->lgd_llh_flags; rc = llog_init_handle(loghandle, flags, NULL); if (rc) GOTO(out_close, rc); rc = req_capsule_server_pack(&req->rq_pill); if (rc) GOTO(out_close, rc = -ENOMEM); hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR); *hdr = *loghandle->lgh_hdr; GOTO(out_close, rc); out_close: rc2 = llog_close(loghandle); if (!rc) rc = rc2; out_pop: pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); llog_ctxt_put(ctxt); return rc; }
int llog_origin_handle_destroy(struct ptlrpc_request *req) { struct obd_export *exp = req->rq_export; struct obd_device *obd = exp->exp_obd; struct obd_device *disk_obd; struct llog_handle *loghandle; struct llogd_body *body; struct lvfs_run_ctxt saved; struct llog_logid *logid = NULL; struct llog_ctxt *ctxt; int rc; ENTRY; body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); if (body->lgd_logid.lgl_oid > 0) logid = &body->lgd_logid; ctxt = llog_get_context(obd, body->lgd_ctxt_idx); if (ctxt == NULL) RETURN(-ENODEV); disk_obd = ctxt->loc_exp->exp_obd; push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); rc = llog_create(ctxt, &loghandle, logid, NULL); if (rc) GOTO(out_pop, rc); rc = req_capsule_server_pack(&req->rq_pill); if (rc) GOTO(out_close, rc = -ENOMEM); body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); body->lgd_logid = loghandle->lgh_id; rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL); if (rc) GOTO(out_close, rc); rc = llog_destroy(loghandle); if (rc) GOTO(out_close, rc); llog_free_handle(loghandle); GOTO(out_close, rc); out_close: if (rc) llog_close(loghandle); out_pop: pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); llog_ctxt_put(ctxt); return rc; }
/* Test named-log reopen; returns opened log on success */ static int llog_test_2(struct obd_device *obd, char *name, struct llog_handle **llh) { struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); int rc; ENTRY; CWARN("2a: re-open a log with name: %s\n", name); rc = llog_create(ctxt, llh, NULL, name); if (rc) { CERROR("2a: re-open log with name %s failed: %d\n", name, rc); GOTO(out, rc); } llog_init_handle(*llh, LLOG_F_IS_PLAIN, &uuid); if ((rc = verify_handle("2", *llh, 1))) GOTO(out, rc); #if 0 CWARN("2b: create a log without specified NAME & LOGID\n"); rc = llog_create(ctxt, &loghandle, NULL, NULL); if (rc) { CERROR("2b: create log failed\n"); GOTO(out, rc); } llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid); logid = loghandle->lgh_id; llog_close(loghandle); CWARN("2b: re-open the log by LOGID\n"); rc = llog_create(ctxt, &loghandle, &logid, NULL); if (rc) { CERROR("2b: re-open log by LOGID failed\n"); GOTO(out, rc); } llog_init_handle(loghandle, LLOG_F_IS_PLAIN, &uuid); CWARN("2b: destroy this log\n"); rc = llog_destroy(loghandle); if (rc) { CERROR("2b: destroy log failed\n"); GOTO(out, rc); } llog_free_handle(loghandle); #endif out: llog_ctxt_put(ctxt); RETURN(rc); }
/** * Helper function to open llog or create it if doesn't exist. * It hides all transaction handling from caller. */ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle **res, struct llog_logid *logid, char *name) { struct dt_device *d; struct thandle *th; int rc; ENTRY; rc = llog_open(env, ctxt, res, logid, name, LLOG_OPEN_NEW); if (rc) RETURN(rc); if (llog_exist(*res)) RETURN(0); LASSERT((*res)->lgh_obj != NULL); d = lu2dt_dev((*res)->lgh_obj->do_lu.lo_dev); th = dt_trans_create(env, d); if (IS_ERR(th)) GOTO(out, rc = PTR_ERR(th)); /* Create update llog object synchronously, which * happens during inialization process see * lod_sub_prep_llog(), to make sure the update * llog object is created before corss-MDT writing * updates into the llog object */ if (ctxt->loc_flags & LLOG_CTXT_FLAG_NORMAL_FID) th->th_sync = 1; th->th_wait_submit = 1; rc = llog_declare_create(env, *res, th); if (rc == 0) { rc = dt_trans_start_local(env, d, th); if (rc == 0) rc = llog_create(env, *res, th); } dt_trans_stop(env, d, th); out: if (rc) llog_close(env, *res); 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); }
/** * Helper function to open llog or create it if doesn't exist. * It hides all transaction handling from caller. */ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle **res, struct llog_logid *logid, char *name) { struct dt_device *d; struct thandle *th; int rc; rc = llog_open(env, ctxt, res, logid, name, LLOG_OPEN_NEW); if (rc) return rc; if (llog_exist(*res)) return 0; LASSERT((*res)->lgh_obj != NULL); d = lu2dt_dev((*res)->lgh_obj->do_lu.lo_dev); th = dt_trans_create(env, d); if (IS_ERR(th)) { rc = PTR_ERR(th); goto out; } rc = llog_declare_create(env, *res, th); if (rc == 0) { rc = dt_trans_start_local(env, d, th); if (rc == 0) rc = llog_create(env, *res, th); } dt_trans_stop(env, d, th); out: if (rc) llog_close(env, *res); return rc; }
int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt, char *name) { struct llog_handle *llh; int rc = 0; rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); if (rc < 0) { if (likely(rc == -ENOENT)) rc = 0; goto out; } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); if (rc) goto out_close; rc = llog_get_size(llh); out_close: llog_close(env, llh); out: /* header is record 1 */ return rc <= 1; }
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 client api; open log by name and process */ static int llog_test_6(const struct lu_env *env, struct obd_device *obd, char *name) { struct obd_device *mgc_obd; struct llog_ctxt *ctxt; struct obd_uuid *mgs_uuid; struct obd_export *exp; struct obd_uuid uuid = { "LLOG_TEST6_UUID" }; struct llog_handle *llh = NULL; struct llog_ctxt *nctxt; int rc, rc2; ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); mgs_uuid = &ctxt->loc_exp->exp_obd->obd_uuid; CWARN("6a: re-open log %s using client API\n", name); mgc_obd = class_find_client_obd(mgs_uuid, LUSTRE_MGC_NAME, NULL); if (mgc_obd == NULL) { CERROR("6a: no MGC devices connected to %s found.\n", mgs_uuid->uuid); GOTO(ctxt_release, rc = -ENOENT); } rc = obd_connect(NULL, &exp, mgc_obd, &uuid, NULL /* obd_connect_data */, NULL); if (rc != -EALREADY) { CERROR("6a: connect on connected MGC (%s) failed to return" " -EALREADY", mgc_obd->obd_name); if (rc == 0) obd_disconnect(exp); GOTO(ctxt_release, rc = -EINVAL); } nctxt = llog_get_context(mgc_obd, LLOG_CONFIG_REPL_CTXT); rc = llog_open(env, nctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); if (rc) { CERROR("6a: llog_open failed %d\n", rc); GOTO(nctxt_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL); if (rc) { CERROR("6a: llog_init_handle failed %d\n", rc); GOTO(parse_out, rc); } plain_counter = 1; /* llog header is first record */ CWARN("6b: process log %s using client API\n", name); rc = llog_process(env, llh, plain_print_cb, NULL, NULL); if (rc) CERROR("6b: llog_process failed %d\n", rc); CWARN("6b: processed %d records\n", plain_counter); rc = verify_handle("6b", llh, plain_counter); if (rc) GOTO(parse_out, rc); plain_counter = 1; /* llog header is first record */ CWARN("6c: process log %s reversely using client API\n", name); rc = llog_reverse_process(env, llh, plain_print_cb, NULL, NULL); if (rc) CERROR("6c: llog_reverse_process failed %d\n", rc); CWARN("6c: processed %d records\n", plain_counter); rc = verify_handle("6c", llh, plain_counter); if (rc) GOTO(parse_out, rc); parse_out: rc2 = llog_close(env, llh); if (rc2) { CERROR("6: llog_close failed: rc = %d\n", rc2); if (rc == 0) rc = rc2; } nctxt_put: llog_ctxt_put(nctxt); 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 llog_check_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, void *data) { struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data; static int l, remains, from, to; static char *out; char *endp; int cur_index, rc = 0; ENTRY; cur_index = rec->lrh_index; if (ioc_data && (ioc_data->ioc_inllen1)) { l = 0; remains = ioc_data->ioc_inllen4 + cfs_size_round(ioc_data->ioc_inllen1) + cfs_size_round(ioc_data->ioc_inllen2) + cfs_size_round(ioc_data->ioc_inllen3); from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') RETURN(-EINVAL); ioc_data->ioc_inllen1 = 0; out = ioc_data->ioc_bulk; if (cur_index < from) RETURN(0); if (to > 0 && cur_index > to) RETURN(-LLOG_EEMPTY); } if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; struct llog_handle *log_handle; if (rec->lrh_type != LLOG_LOGID_MAGIC) { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d failed\n", cur_index, rec->lrh_type, rec->lrh_len); } if (handle->lgh_ctxt == NULL) RETURN(-EOPNOTSUPP); rc = llog_cat_id2handle(handle, &log_handle, &lir->lid_id); if (rc) { CDEBUG(D_IOCTL, "cannot find log #"LPX64"#"LPX64"#%08x\n", lir->lid_id.lgl_oid, lir->lid_id.lgl_oseq, lir->lid_id.lgl_ogen); RETURN(rc); } rc = llog_process(log_handle, llog_check_cb, NULL, NULL); llog_close(log_handle); } else { switch (rec->lrh_type) { case OST_SZ_REC: case OST_RAID1_REC: case MDS_UNLINK_REC: case MDS_SETATTR_REC: case MDS_SETATTR64_REC: case OBD_CFG_REC: case LLOG_HDR_MAGIC: { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d ok\n", cur_index, rec->lrh_type, rec->lrh_len); out += l; remains -= l; if (remains <= 0) { CERROR("no space to print log records\n"); RETURN(-LLOG_EEMPTY); } RETURN(0); } default: { l = snprintf(out, remains, "[index]: %05d [type]: " "%02x [len]: %04d failed\n", cur_index, rec->lrh_type, rec->lrh_len); out += l; remains -= l; if (remains <= 0) { CERROR("no space to print log records\n"); RETURN(-LLOG_EEMPTY); } RETURN(0); } } } RETURN(rc); }
int llog_ioctl(struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data) { struct llog_logid logid; int err = 0; struct llog_handle *handle = NULL; ENTRY; if (*data->ioc_inlbuf1 == '#') { err = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1); if (err) GOTO(out, err); err = llog_create(ctxt, &handle, &logid, NULL); if (err) GOTO(out, err); } else if (*data->ioc_inlbuf1 == '$') { char *name = data->ioc_inlbuf1 + 1; err = llog_create(ctxt, &handle, NULL, name); if (err) GOTO(out, err); } else { GOTO(out, err = -EINVAL); } err = llog_init_handle(handle, 0, NULL); if (err) GOTO(out_close, err = -ENOENT); switch (cmd) { case OBD_IOC_LLOG_INFO: { int l; int remains = data->ioc_inllen2 + cfs_size_round(data->ioc_inllen1); char *out = data->ioc_bulk; l = snprintf(out, remains, "logid: #"LPX64"#"LPX64"#%08x\n" "flags: %x (%s)\n" "records count: %d\n" "last index: %d\n", handle->lgh_id.lgl_oid, handle->lgh_id.lgl_oseq, handle->lgh_id.lgl_ogen, handle->lgh_hdr->llh_flags, handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT ? "cat" : "plain", handle->lgh_hdr->llh_count, handle->lgh_last_idx); out += l; remains -= l; if (remains <= 0) CERROR("not enough space for log header info\n"); GOTO(out_close, err); } case OBD_IOC_LLOG_CHECK: { LASSERT(data->ioc_inllen1); err = llog_process(handle, llog_check_cb, data, NULL); if (err == -LLOG_EEMPTY) err = 0; GOTO(out_close, err); } case OBD_IOC_LLOG_PRINT: { LASSERT(data->ioc_inllen1); err = llog_process(handle, class_config_dump_handler,data,NULL); if (err == -LLOG_EEMPTY) err = 0; else err = llog_process(handle, llog_print_cb, data, NULL); GOTO(out_close, err); } case OBD_IOC_LLOG_CANCEL: { struct llog_cookie cookie; struct llog_logid plain; char *endp; cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') GOTO(out_close, err = -EINVAL); if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) { cfs_down_write(&handle->lgh_lock); err = llog_cancel_rec(handle, cookie.lgc_index); cfs_up_write(&handle->lgh_lock); GOTO(out_close, err); } err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (err) GOTO(out_close, err); cookie.lgc_lgl = plain; if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) GOTO(out_close, err = -EINVAL); err = llog_cat_cancel_records(handle, 1, &cookie); GOTO(out_close, err); } case OBD_IOC_LLOG_REMOVE: { struct llog_logid plain; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { err = llog_destroy(handle); if (!err) llog_free_handle(handle); GOTO(out, err); } if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) GOTO(out_close, err = -EINVAL); if (data->ioc_inlbuf2) { /*remove indicate log from the catalog*/ err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (err) GOTO(out_close, err); err = llog_remove_log(handle, &plain); } else { /*remove all the log of the catalog*/ llog_process(handle, llog_delete_cb, NULL, NULL); } GOTO(out_close, err); } } out_close: if (handle->lgh_hdr && handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) llog_cat_put(handle); else llog_close(handle); out: RETURN(err); }
int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data) { struct llog_logid logid; int rc = 0; struct llog_handle *handle = NULL; if (*data->ioc_inlbuf1 == '#') { rc = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1); if (rc) return rc; rc = llog_open(env, ctxt, &handle, &logid, NULL, LLOG_OPEN_EXISTS); if (rc) return rc; } else if (*data->ioc_inlbuf1 == '$') { char *name = data->ioc_inlbuf1 + 1; rc = llog_open(env, ctxt, &handle, NULL, name, LLOG_OPEN_EXISTS); if (rc) return rc; } else { return -EINVAL; } rc = llog_init_handle(env, handle, 0, NULL); if (rc) GOTO(out_close, rc = -ENOENT); switch (cmd) { case OBD_IOC_LLOG_INFO: { int l; int remains = data->ioc_inllen2 + cfs_size_round(data->ioc_inllen1); char *out = data->ioc_bulk; l = snprintf(out, remains, "logid: #"DOSTID"#%08x\n" "flags: %x (%s)\n" "records count: %d\n" "last index: %d\n", POSTID(&handle->lgh_id.lgl_oi), handle->lgh_id.lgl_ogen, handle->lgh_hdr->llh_flags, handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT ? "cat" : "plain", handle->lgh_hdr->llh_count, handle->lgh_last_idx); out += l; remains -= l; if (remains <= 0) { CERROR("%s: not enough space for log header info\n", ctxt->loc_obd->obd_name); rc = -ENOSPC; } break; } case OBD_IOC_LLOG_CHECK: LASSERT(data->ioc_inllen1 > 0); rc = llog_process(env, handle, llog_check_cb, data, NULL); if (rc == -LLOG_EEMPTY) rc = 0; else if (rc) GOTO(out_close, rc); break; case OBD_IOC_LLOG_PRINT: LASSERT(data->ioc_inllen1 > 0); rc = llog_process(env, handle, llog_print_cb, data, NULL); if (rc == -LLOG_EEMPTY) rc = 0; else if (rc) GOTO(out_close, rc); break; case OBD_IOC_LLOG_CANCEL: { struct llog_cookie cookie; struct llog_logid plain; char *endp; cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0); if (*endp != '\0') GOTO(out_close, rc = -EINVAL); if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { rc = llog_cancel_rec(NULL, handle, cookie.lgc_index); GOTO(out_close, rc); } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) { GOTO(out_close, rc = -EINVAL); } if (data->ioc_inlbuf2 == NULL) /* catalog but no logid */ GOTO(out_close, rc = -ENOTTY); rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (rc) GOTO(out_close, rc); cookie.lgc_lgl = plain; rc = llog_cat_cancel_records(env, handle, 1, &cookie); if (rc) GOTO(out_close, rc); break; } case OBD_IOC_LLOG_REMOVE: { struct llog_logid plain; if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) { rc = llog_destroy(env, handle); GOTO(out_close, rc); } else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) { GOTO(out_close, rc = -EINVAL); } if (data->ioc_inlbuf2 > 0) { /* remove indicate log from the catalog */ rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2); if (rc) GOTO(out_close, rc); rc = llog_remove_log(env, handle, &plain); } else { /* remove all the log of the catalog */ rc = llog_process(env, handle, llog_delete_cb, NULL, NULL); if (rc) GOTO(out_close, rc); } break; } default: CERROR("%s: Unknown ioctl cmd %#x\n", ctxt->loc_obd->obd_name, cmd); GOTO(out_close, rc = -ENOTTY); } out_close: if (handle->lgh_hdr && handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) llog_cat_close(env, handle); else llog_close(env, handle); return rc; }
/* Test client api; open log by name and process */ static int llog_test_6(struct obd_device *obd, char *name) { struct obd_device *mgc_obd; struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); struct obd_uuid *mgs_uuid = &ctxt->loc_exp->exp_obd->obd_uuid; struct obd_export *exp; struct obd_uuid uuid = {"LLOG_TEST6_UUID"}; struct llog_handle *llh = NULL; struct llog_ctxt *nctxt; int rc; CWARN("6a: re-open log %s using client API\n", name); mgc_obd = class_find_client_obd(mgs_uuid, LUSTRE_MGC_NAME, NULL); if (mgc_obd == NULL) { CERROR("6: no MGC devices connected to %s found.\n", mgs_uuid->uuid); GOTO(ctxt_release, rc = -ENOENT); } rc = obd_connect(NULL, &exp, mgc_obd, &uuid, NULL /* obd_connect_data */, NULL); if (rc != -EALREADY) { CERROR("6: connect on connected MDC (%s) failed to return" " -EALREADY", mgc_obd->obd_name); if (rc == 0) obd_disconnect(exp); GOTO(ctxt_release, rc = -EINVAL); } nctxt = llog_get_context(mgc_obd, LLOG_CONFIG_REPL_CTXT); rc = llog_create(nctxt, &llh, NULL, name); if (rc) { CERROR("6: llog_create failed %d\n", rc); llog_ctxt_put(nctxt); GOTO(ctxt_release, rc); } rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL); if (rc) { CERROR("6: llog_init_handle failed %d\n", rc); GOTO(parse_out, rc); } rc = llog_process(llh, plain_print_cb, NULL, NULL); if (rc) CERROR("6: llog_process failed %d\n", rc); rc = llog_reverse_process(llh, plain_print_cb, NULL, NULL); if (rc) CERROR("6: llog_reverse_process failed %d\n", rc); parse_out: rc = llog_close(llh); llog_ctxt_put(nctxt); if (rc) { CERROR("6: llog_close failed: rc = %d\n", rc); } ctxt_release: llog_ctxt_put(ctxt); RETURN(rc); }
static int llog_catinfo_deletions(struct obd_device *obd, char *buf, int buf_len) { struct mds_obd *mds = &obd->u.mds; struct llog_handle *handle; struct lvfs_run_ctxt saved; int size, i, count; struct llog_catid *idarray; char name[32] = CATLIST; struct cb_data data; struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); int rc; ENTRY; if (ctxt == NULL || mds == NULL) GOTO(release_ctxt, rc = -ENODEV); count = mds->mds_lov_desc.ld_tgt_count; size = sizeof(*idarray) * count; OBD_ALLOC_LARGE(idarray, size); if (!idarray) GOTO(release_ctxt, rc = -ENOMEM); cfs_mutex_lock(&obd->obd_olg.olg_cat_processing); rc = llog_get_cat_list(obd, name, 0, count, idarray); if (rc) GOTO(out_free, rc); push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); data.ctxt = ctxt; data.out = buf; data.remains = buf_len; for (i = 0; i < count; i++) { int l, index, uncanceled = 0; rc = llog_create(ctxt, &handle, &idarray[i].lci_logid, NULL); if (rc) GOTO(out_pop, rc); rc = llog_init_handle(handle, 0, NULL); if (rc) { llog_close(handle); GOTO(out_pop, rc = -ENOENT); } for (index = 1; index < (LLOG_BITMAP_BYTES * 8); index++) { if (ext2_test_bit(index, handle->lgh_hdr->llh_bitmap)) uncanceled++; } l = snprintf(data.out, data.remains, "\n[Catlog ID]: #"LPX64"#"LPX64"#%08x " "[Log Count]: %d\n", idarray[i].lci_logid.lgl_oid, idarray[i].lci_logid.lgl_oseq, idarray[i].lci_logid.lgl_ogen, uncanceled); data.out += l; data.remains -= l; data.init = 1; llog_process(handle, llog_catinfo_cb, &data, NULL); llog_close(handle); if (data.remains <= 0) break; } EXIT; out_pop: pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL); out_free: cfs_mutex_unlock(&obd->obd_olg.olg_cat_processing); OBD_FREE_LARGE(idarray, size); release_ctxt: llog_ctxt_put(ctxt); return rc; }
int llog_origin_handle_prev_block(struct ptlrpc_request *req) { struct obd_export *exp = req->rq_export; struct obd_device *obd = exp->exp_obd; struct llog_handle *loghandle; struct llogd_body *body; struct llogd_body *repbody; struct obd_device *disk_obd; struct lvfs_run_ctxt saved; struct llog_ctxt *ctxt; __u32 flags; __u8 *buf; void *ptr; int rc, rc2; ENTRY; body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); OBD_ALLOC(buf, LLOG_CHUNK_SIZE); if (!buf) RETURN(-ENOMEM); ctxt = llog_get_context(obd, body->lgd_ctxt_idx); if (ctxt == NULL) GOTO(out_free, rc = -ENODEV); disk_obd = ctxt->loc_exp->exp_obd; push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL); if (rc) GOTO(out_pop, rc); flags = body->lgd_llh_flags; rc = llog_init_handle(loghandle, flags, NULL); if (rc) GOTO(out_close, rc); memset(buf, 0, LLOG_CHUNK_SIZE); rc = llog_prev_block(loghandle, body->lgd_index, buf, LLOG_CHUNK_SIZE); if (rc) GOTO(out_close, rc); req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER, LLOG_CHUNK_SIZE); rc = req_capsule_server_pack(&req->rq_pill); if (rc) GOTO(out_close, rc = -ENOMEM); repbody = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); *repbody = *body; ptr = req_capsule_server_get(&req->rq_pill, &RMF_EADATA); memcpy(ptr, buf, LLOG_CHUNK_SIZE); GOTO(out_close, rc); out_close: rc2 = llog_close(loghandle); if (!rc) rc = rc2; out_pop: pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL); llog_ctxt_put(ctxt); out_free: OBD_FREE(buf, LLOG_CHUNK_SIZE); return rc; }