int llog_copy_handler(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *rec, void *data) { struct llog_handle *copy_llh = data; /* Append all records */ return llog_write(env, copy_llh, rec, NULL, 0, NULL, -1); }
/* returns negative on error; 0 if success; 1 if success & log destroyed */ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle, int index) { struct llog_log_hdr *llh = loghandle->lgh_hdr; int rc = 0; ENTRY; CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n", index, POSTID(&loghandle->lgh_id.lgl_oi)); if (index == 0) { CERROR("Can't cancel index 0 which is header\n"); RETURN(-EINVAL); } spin_lock(&loghandle->lgh_hdr_lock); if (!ext2_clear_bit(index, llh->llh_bitmap)) { spin_unlock(&loghandle->lgh_hdr_lock); CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index); RETURN(-ENOENT); } llh->llh_count--; if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) && (llh->llh_count == 1) && (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) { spin_unlock(&loghandle->lgh_hdr_lock); rc = llog_destroy(env, loghandle); if (rc < 0) { CERROR("%s: can't destroy empty llog #"DOSTID "#%08x: rc = %d\n", loghandle->lgh_ctxt->loc_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, rc); GOTO(out_err, rc); } RETURN(1); } spin_unlock(&loghandle->lgh_hdr_lock); rc = llog_write(env, loghandle, &llh->llh_hdr, NULL, 0, NULL, 0); if (rc < 0) { CERROR("%s: fail to write header for llog #"DOSTID "#%08x: rc = %d\n", loghandle->lgh_ctxt->loc_obd->obd_name, POSTID(&loghandle->lgh_id.lgl_oi), loghandle->lgh_id.lgl_ogen, rc); GOTO(out_err, rc); } RETURN(0); out_err: spin_lock(&loghandle->lgh_hdr_lock); ext2_set_bit(index, llh->llh_bitmap); llh->llh_count++; spin_unlock(&loghandle->lgh_hdr_lock); return rc; }
/** Two things: * 1. Find the smallest record everyone is willing to purge * 2. Update the last purgeable record for this user */ static int mdd_changelog_user_purge_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_rec_hdr *hdr, void *data) { struct llog_changelog_user_rec *rec; struct mdd_changelog_user_data *mcud = data; int rc; ENTRY; LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN); rec = (struct llog_changelog_user_rec *)hdr; mcud->mcud_usercount++; /* If we have a new endrec for this id, use it for the following min check instead of its old value */ if (rec->cur_id == mcud->mcud_id) rec->cur_endrec = max(rec->cur_endrec, mcud->mcud_endrec); /* Track the minimum referenced record */ if (mcud->mcud_minid == 0 || mcud->mcud_minrec > rec->cur_endrec) { mcud->mcud_minid = rec->cur_id; mcud->mcud_minrec = rec->cur_endrec; } if (rec->cur_id != mcud->mcud_id) RETURN(0); /* Update this user's record */ mcud->mcud_found = 1; /* Special case: unregister this user */ if (mcud->mcud_endrec == MCUD_UNREGISTER) { struct llog_cookie cookie; cookie.lgc_lgl = llh->lgh_id; cookie.lgc_index = hdr->lrh_index; rc = llog_cat_cancel_records(env, llh->u.phd.phd_cat_handle, 1, &cookie); if (rc == 0) mcud->mcud_usercount--; RETURN(rc); } /* Update the endrec */ CDEBUG(D_IOCTL, "Rewriting changelog user %d endrec to "LPU64"\n", mcud->mcud_id, rec->cur_endrec); rc = llog_write(env, llh, hdr, hdr->lrh_index); 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 record writing, single and in bulk */ static int llog_test_3(const struct lu_env *env, struct obd_device *obd, struct llog_handle *llh) { struct llog_gen_rec lgr; int rc, i; int num_recs = 1; /* 1 for the header */ lgr.lgr_hdr.lrh_len = lgr.lgr_tail.lrt_len = sizeof(lgr); lgr.lgr_hdr.lrh_type = LLOG_GEN_REC; CWARN("3a: write one create_rec\n"); rc = llog_write(env, llh, &lgr.lgr_hdr, NULL, 0, NULL, -1); num_recs++; if (rc < 0) { CERROR("3a: write one log record failed: %d\n", rc); return rc; } rc = verify_handle("3a", llh, num_recs); if (rc) return rc; CWARN("3b: write 10 cfg log records with 8 bytes bufs\n"); for (i = 0; i < 10; i++) { struct llog_rec_hdr hdr; char buf[8]; hdr.lrh_len = 8; hdr.lrh_type = OBD_CFG_REC; memset(buf, 0, sizeof(buf)); rc = llog_write(env, llh, &hdr, NULL, 0, buf, -1); if (rc < 0) { CERROR("3b: write 10 records failed at #%d: %d\n", i + 1, rc); return rc; } num_recs++; } rc = verify_handle("3b", llh, num_recs); if (rc) return rc; CWARN("3c: write 1000 more log records\n"); for (i = 0; i < 1000; i++) { rc = llog_write(env, llh, &lgr.lgr_hdr, NULL, 0, NULL, -1); if (rc < 0) { CERROR("3c: write 1000 records failed at #%d: %d\n", i + 1, rc); return rc; } num_recs++; } rc = verify_handle("3c", llh, num_recs); if (rc) return rc; CWARN("3d: write log more than BITMAP_SIZE, return -ENOSPC\n"); for (i = 0; i < LLOG_BITMAP_SIZE(llh->lgh_hdr) + 1; i++) { struct llog_rec_hdr hdr; char buf_even[24]; char buf_odd[32]; memset(buf_odd, 0, sizeof(buf_odd)); memset(buf_even, 0, sizeof(buf_even)); if ((i % 2) == 0) { hdr.lrh_len = 24; hdr.lrh_type = OBD_CFG_REC; rc = llog_write(env, llh, &hdr, NULL, 0, buf_even, -1); } else { hdr.lrh_len = 32; hdr.lrh_type = OBD_CFG_REC; rc = llog_write(env, llh, &hdr, NULL, 0, buf_odd, -1); } if (rc == -ENOSPC) { break; } else if (rc < 0) { CERROR("3d: write recs failed at #%d: %d\n", i + 1, rc); return rc; } num_recs++; } if (rc != -ENOSPC) { CWARN("3d: write record more than BITMAP size!\n"); return -EINVAL; } CWARN("3d: wrote %d more records before end of llog is reached\n", num_recs); rc = verify_handle("3d", llh, num_recs); return rc; }
/* Test record writing, single and in bulk */ static int llog_test_3(const struct lu_env *env, struct obd_device *obd, struct llog_handle *llh) { struct llog_gen_rec lgr; int rc, i; int num_recs = 1; /* 1 for the header */ ENTRY; lgr.lgr_hdr.lrh_len = lgr.lgr_tail.lrt_len = sizeof(lgr); lgr.lgr_hdr.lrh_type = LLOG_GEN_REC; CWARN("3a: write one create_rec\n"); rc = llog_write(env, llh, &lgr.lgr_hdr, LLOG_NEXT_IDX); num_recs++; if (rc < 0) { CERROR("3a: write one log record failed: %d\n", rc); RETURN(rc); } rc = verify_handle("3a", llh, num_recs); if (rc) RETURN(rc); CWARN("3c: write 1000 more log records\n"); for (i = 0; i < 1000; i++) { rc = llog_write(env, llh, &lgr.lgr_hdr, LLOG_NEXT_IDX); if (rc < 0) { CERROR("3c: write 1000 records failed at #%d: %d\n", i + 1, rc); RETURN(rc); } num_recs++; } rc = verify_handle("3c", llh, num_recs); if (rc) RETURN(rc); CWARN("3d: write records with variable size until BITMAP_SIZE, " "return -ENOSPC\n"); for (i = 0; i < LLOG_BITMAP_SIZE(llh->lgh_hdr) + 1; i++) { char buf[64]; struct llog_rec_hdr *hdr = (void *)&buf; memset(buf, 0, sizeof buf); if ((i % 2) == 0) hdr->lrh_len = 40; else hdr->lrh_len = 64; hdr->lrh_type = OBD_CFG_REC; rc = llog_write(env, llh, hdr, LLOG_NEXT_IDX); if (rc == -ENOSPC) { break; } else if (rc < 0) { CERROR("3d: write recs failed at #%d: %d\n", i + 1, rc); RETURN(rc); } num_recs++; } if (rc != -ENOSPC) { CWARN("3d: write record more than BITMAP size!\n"); RETURN(-EINVAL); } CWARN("3d: wrote %d more records before end of llog is reached\n", num_recs); rc = verify_handle("3d", llh, num_recs); RETURN(rc); }