+ logid_to_fid(&lir->lid_id, &fid);
+
+ CWARN("seeing record at index %d - "DFID" in log "DFID"\n",
+ rec->lrh_index, PFID(&fid),
+ PFID(lu_object_fid(&llh->lgh_obj->do_lu)));
+
+ if (prev_fid->f_oid > fid.f_oid) {
+ CWARN("processing old record, fail\n");
+ prev_fid->f_oid = 0xbad;
+ RETURN(-LLOG_EEMPTY);
+ }
+
+ if (prev_fid->f_oid == 0) {
+ cfs_fail_loc = OBD_FAIL_ONCE | OBD_FAIL_LLOG_PROCESS_TIMEOUT;
+ cfs_fail_val = (unsigned int) (llh->lgh_id.lgl_oi.oi.oi_id &
+ 0xFFFFFFFF);
+ msleep(1 * MSEC_PER_SEC);
+ }
+ *prev_fid = fid;
+
+ RETURN(0);
+}
+
+/* test catalog wrap around */
+static int llog_test_10(const struct lu_env *env, struct obd_device *obd)
+{
+ struct llog_handle *cath;
+ char name[10];
+ int rc, rc2, i, enospc, eok;
+ struct llog_mini_rec lmr;
+ struct llog_ctxt *ctxt;
+ struct lu_attr la;
+ __u64 cat_max_size;
+ struct dt_device *dt;
+
+ 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;
+
+ snprintf(name, sizeof(name), "%x", llog_test_rand + 2);
+ CWARN("10a: create a catalog log with name: %s\n", name);
+ rc = llog_open_create(env, ctxt, &cath, NULL, name);
+ if (rc) {
+ CERROR("10a: 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("10a: can't init llog handle: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ cat_logid = cath->lgh_id;
+ dt = lu2dt_dev(cath->lgh_obj->do_lu.lo_dev);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10c: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /* force catalog wrap for 5th plain LLOG */
+ cfs_fail_loc = CFS_FAIL_SKIP|OBD_FAIL_CAT_RECORDS;
+ cfs_fail_val = 4;
+
+ CWARN("10b: write %d log records\n", llog_test_recnum);
+ for (i = 0; i < llog_test_recnum; i++) {
+ rc = llog_cat_add(env, cath, &lmr.lmr_hdr, NULL);
+ if (rc) {
+ CERROR("10b: write %d records failed at #%d: %d\n",
+ llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ }
+
+ /* make sure 2 new plain llog appears in catalog (+1 with hdr) */
+ rc = verify_handle("10b", cath, 3);
+ if (rc)
+ GOTO(out, rc);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10b: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ CWARN("10c: write %d more log records\n", 2 * llog_test_recnum);
+ for (i = 0; i < 2 * llog_test_recnum; i++) {
+ rc = llog_cat_add(env, cath, &lmr.lmr_hdr, NULL);
+ if (rc) {
+ CERROR("10c: write %d records failed at #%d: %d\n",
+ 2*llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ }
+
+ /* make sure 2 new plain llog appears in catalog (+1 with hdr) */
+ rc = verify_handle("10c", cath, 5);
+ if (rc)
+ GOTO(out, rc);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10c: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /*
+ * fill last allocated plain LLOG and reach -ENOSPC condition
+ * because no slot available in Catalog
+ */
+ enospc = 0;
+ eok = 0;
+ CWARN("10c: 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);
+ if (rc && rc != -ENOSPC) {
+ CERROR("10c: write %d records failed at #%d: %d\n",
+ llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ /*
+ * after last added plain LLOG has filled up, all new
+ * records add should fail with -ENOSPC
+ */
+ if (rc == -ENOSPC) {
+ enospc++;
+ } else {
+ enospc = 0;
+ eok++;
+ }
+ }
+
+ if ((enospc == 0) && (enospc+eok != llog_test_recnum)) {
+ CERROR("10c: all last records adds should have failed with"
+ " -ENOSPC\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ CWARN("10c: wrote %d records then %d failed with ENOSPC\n", eok,
+ enospc);
+
+ /* make sure no new record in Catalog */
+ rc = verify_handle("10c", cath, 5);
+ if (rc)
+ GOTO(out, rc);
+
+ /* Catalog should have reached its max size for test */
+ rc = dt_attr_get(env, cath->lgh_obj, &la);
+ if (rc) {
+ CERROR("10c: failed to get catalog attrs: %d\n", rc);
+ GOTO(out, rc);
+ }
+ cat_max_size = la.la_size;
+
+ /*
+ * cancel all 1st plain llog records to empty it, this will also cause
+ * its catalog entry to be freed for next forced wrap in 10e
+ */
+ CWARN("10d: Cancel %d records, see one log zapped\n", llog_test_recnum);
+ cancel_count = 0;
+ rc = llog_cat_process(env, cath, llog_cancel_rec_cb, "foobar", 0, 0);
+ if (rc != -LLOG_EEMPTY) {
+ CERROR("10d: process with llog_cancel_rec_cb failed: %d\n", rc);
+ /*
+ * need to indicate error if for any reason llog_test_recnum is
+ * not reached
+ */
+ if (rc == 0)
+ rc = -ERANGE;
+ GOTO(out, rc);
+ }
+
+ CWARN("10d: print the catalog entries.. we expect 3\n");
+ cat_counter = 0;
+ rc = llog_process(env, cath, cat_print_cb, "test 10", NULL);
+ if (rc) {
+ CERROR("10d: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 3) {
+ CERROR("10d: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* verify one down in catalog (+1 with hdr) */
+ rc = verify_handle("10d", cath, 4);
+ if (rc)
+ GOTO(out, rc);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10d: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ enospc = 0;
+ eok = 0;
+ CWARN("10e: 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);
+ if (rc && rc != -ENOSPC) {
+ CERROR("10e: write %d records failed at #%d: %d\n",
+ llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ /*
+ * after last added plain LLOG has filled up, all new
+ * records add should fail with -ENOSPC
+ */
+ if (rc == -ENOSPC) {
+ enospc++;
+ } else {
+ enospc = 0;
+ eok++;
+ }
+ }
+
+ if ((enospc == 0) && (enospc+eok != llog_test_recnum)) {
+ CERROR("10e: all last records adds should have failed with"
+ " -ENOSPC\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ CWARN("10e: wrote %d records then %d failed with ENOSPC\n", eok,
+ enospc);
+
+ CWARN("10e: print the catalog entries.. we expect 4\n");
+ cat_counter = 0;
+ rc = llog_cat_process_or_fork(env, cath, cat_print_cb, NULL, "test 10",
+ 0, 0, false);
+ if (rc) {
+ CERROR("10e: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 4) {
+ CERROR("10e: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* make sure 1 new plain llog appears in catalog (+1 with hdr) */
+ rc = verify_handle("10e", cath, 5);
+ if (rc)
+ GOTO(out, rc);
+
+ /* verify catalog has wrap around */
+ if (cath->lgh_last_idx > cath->lgh_hdr->llh_cat_idx) {
+ CERROR("10e: catalog failed to wrap around\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ rc = dt_attr_get(env, cath->lgh_obj, &la);
+ if (rc) {
+ CERROR("10e: failed to get catalog attrs: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ if (la.la_size != cat_max_size) {
+ CERROR("10e: catalog size has changed after it has wrap around,"
+ " current size = %llu, expected size = %llu\n",
+ la.la_size, cat_max_size);
+ GOTO(out, rc = -EINVAL);
+ }
+ CWARN("10e: catalog successfully wrap around, last_idx %d, first %d\n",
+ cath->lgh_last_idx, cath->lgh_hdr->llh_cat_idx);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10e: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /*
+ * cancel more records to free one more slot in Catalog
+ * see if it is re-allocated when adding more records
+ */
+ CWARN("10f: Cancel %d records, see one log zapped\n", llog_test_recnum);
+ cancel_count = 0;
+ rc = llog_cat_process(env, cath, llog_cancel_rec_cb, "foobar", 0, 0);
+ if (rc != -LLOG_EEMPTY) {
+ CERROR("10f: process with llog_cancel_rec_cb failed: %d\n", rc);
+ /*
+ * need to indicate error if for any reason llog_test_recnum is
+ * not reached
+ */
+ if (rc == 0)
+ rc = -ERANGE;
+ GOTO(out, rc);
+ }
+
+ CWARN("10f: print the catalog entries.. we expect 3\n");
+ cat_counter = 0;
+ rc = llog_cat_process_or_fork(env, cath, cat_print_cb, NULL, "test 10",
+ 0, 0, false);
+ if (rc) {
+ CERROR("10f: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 3) {
+ CERROR("10f: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* verify one down in catalog (+1 with hdr) */
+ rc = verify_handle("10f", cath, 4);
+ if (rc)
+ GOTO(out, rc);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10f: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ enospc = 0;
+ eok = 0;
+ CWARN("10f: 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);
+ if (rc && rc != -ENOSPC) {
+ CERROR("10f: write %d records failed at #%d: %d\n",
+ llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ /*
+ * after last added plain LLOG has filled up, all new
+ * records add should fail with -ENOSPC
+ */
+ if (rc == -ENOSPC) {
+ enospc++;
+ } else {
+ enospc = 0;
+ eok++;
+ }
+ }
+
+ if ((enospc == 0) && (enospc+eok != llog_test_recnum)) {
+ CERROR("10f: all last records adds should have failed with"
+ " -ENOSPC\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ CWARN("10f: wrote %d records then %d failed with ENOSPC\n", eok,
+ enospc);
+
+ /* make sure 1 new plain llog appears in catalog (+1 with hdr) */
+ rc = verify_handle("10f", cath, 5);
+ if (rc)
+ GOTO(out, rc);
+
+ /* verify lgh_last_idx = llh_cat_idx = 2 now */
+ if (cath->lgh_last_idx != cath->lgh_hdr->llh_cat_idx ||
+ cath->lgh_last_idx != 2) {
+ CERROR("10f: lgh_last_idx = %d vs 2, llh_cat_idx = %d vs 2\n",
+ cath->lgh_last_idx, cath->lgh_hdr->llh_cat_idx);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ rc = dt_attr_get(env, cath->lgh_obj, &la);
+ if (rc) {
+ CERROR("10f: failed to get catalog attrs: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ if (la.la_size != cat_max_size) {
+ CERROR("10f: catalog size has changed after it has wrap around,"
+ " current size = %llu, expected size = %llu\n",
+ la.la_size, cat_max_size);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10f: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /* will llh_cat_idx also successfully wrap ? */
+
+ /*
+ * cancel all records in the plain LLOGs referenced by 2 last indexes in
+ * Catalog
+ */
+
+ /* cancel more records to free one more slot in Catalog */
+ CWARN("10g: Cancel %d records, see one log zapped\n", llog_test_recnum);
+ cancel_count = 0;
+ rc = llog_cat_process(env, cath, llog_cancel_rec_cb, "foobar", 0, 0);
+ if (rc != -LLOG_EEMPTY) {
+ CERROR("10g: process with llog_cancel_rec_cb failed: %d\n", rc);
+ /* need to indicate error if for any reason llog_test_recnum is
+ * not reached */
+ if (rc == 0)
+ rc = -ERANGE;
+ GOTO(out, rc);
+ }
+
+ CWARN("10g: print the catalog entries.. we expect 3\n");
+ cat_counter = 0;
+ rc = llog_cat_process_or_fork(env, cath, cat_print_cb, NULL, "test 10",
+ 0, 0, false);
+ if (rc) {
+ CERROR("10g: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 3) {
+ CERROR("10g: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* verify one down in catalog (+1 with hdr) */
+ rc = verify_handle("10g", cath, 4);
+ if (rc)
+ GOTO(out, rc);
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10g: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /* cancel more records to free one more slot in Catalog */
+ CWARN("10g: Cancel %d records, see one log zapped\n", llog_test_recnum);
+ cancel_count = 0;
+ rc = llog_cat_process(env, cath, llog_cancel_rec_cb, "foobar", 0, 0);
+ if (rc != -LLOG_EEMPTY) {
+ CERROR("10g: process with llog_cancel_rec_cb failed: %d\n", rc);
+ /*
+ * need to indicate error if for any reason llog_test_recnum is
+ * not reached
+ */
+ if (rc == 0)
+ rc = -ERANGE;
+ GOTO(out, rc);
+ }
+
+ CWARN("10g: print the catalog entries.. we expect 2\n");
+ cat_counter = 0;
+ rc = llog_cat_process_or_fork(env, cath, cat_print_cb, NULL, "test 10",
+ 0, 0, false);
+ if (rc) {
+ CERROR("10g: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 2) {
+ CERROR("10g: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* verify one down in catalog (+1 with hdr) */
+ rc = verify_handle("10g", cath, 3);
+ if (rc)
+ GOTO(out, rc);
+
+ /* verify lgh_last_idx = 2 and llh_cat_idx = 0 now */
+ if (cath->lgh_hdr->llh_cat_idx != 0 ||
+ cath->lgh_last_idx != 2) {
+ CERROR("10g: lgh_last_idx = %d vs 2, llh_cat_idx = %d vs 0\n",
+ cath->lgh_last_idx, cath->lgh_hdr->llh_cat_idx);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /*
+ * sync device to commit all recent LLOG changes to disk and avoid
+ * to consume a huge space with delayed journal commit callbacks
+ * particularly on low memory nodes or VMs
+ */
+ rc = dt_sync(env, dt);
+ if (rc) {
+ CERROR("10g: sync failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ /* cancel more records to free one more slot in Catalog */
+ CWARN("10g: Cancel %d records, see one log zapped\n", llog_test_recnum);
+ cancel_count = 0;
+ rc = llog_cat_process(env, cath, llog_cancel_rec_cb, "foobar", 0, 0);
+ if (rc != -LLOG_EEMPTY) {
+ CERROR("10g: process with llog_cancel_rec_cb failed: %d\n", rc);
+ /*
+ * need to indicate error if for any reason llog_test_recnum is
+ * not reached
+ */
+ if (rc == 0)
+ rc = -ERANGE;
+ GOTO(out, rc);
+ }
+
+ CWARN("10g: print the catalog entries.. we expect 1\n");
+ cat_counter = 0;
+ rc = llog_cat_process_or_fork(env, cath, cat_print_cb, NULL, "test 10",
+ 0, 0, false);
+ if (rc) {
+ CERROR("10g: process with cat_print_cb failed: %d\n", rc);
+ GOTO(out, rc);
+ }
+ if (cat_counter != 1) {
+ CERROR("10g: %d entries in catalog\n", cat_counter);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ /* verify one down in catalog (+1 with hdr) */
+ rc = verify_handle("10g", cath, 2);
+ if (rc)
+ GOTO(out, rc);
+
+ /* verify lgh_last_idx = 2 and llh_cat_idx = 1 now */
+ if (cath->lgh_hdr->llh_cat_idx != 1 ||
+ cath->lgh_last_idx != 2) {
+ CERROR("10g: lgh_last_idx = %d vs 2, llh_cat_idx = %d vs 1\n",
+ cath->lgh_last_idx, cath->lgh_hdr->llh_cat_idx);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ CWARN("10g: llh_cat_idx has also successfully wrapped!\n");
+
+ /*
+ * catalog has only one valid entry other slots has outdated
+ * records. Trying to race the llog_thread_process with llog_add
+ * llog_thread_process read buffer and loop record on it.
+ * llog_add adds a record and mark a record in bitmap.
+ * llog_thread_process process record with old data.
+ */
+ {
+ struct llog_process_info lpi;
+ struct lu_fid test_fid = {0};
+
+ lpi.lpi_loghandle = cath;
+ lpi.lpi_cb = cat_check_old_cb;
+ lpi.lpi_catdata = NULL;
+ lpi.lpi_cbdata = &test_fid;
+ init_completion(&lpi.lpi_completion);
+
+ kthread_run(llog_test_process_thread, &lpi, "llog_test_process_thread");
+
+ msleep(1 * MSEC_PER_SEC / 2);
+ enospc = 0;
+ eok = 0;
+ CWARN("10h: 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);
+ if (rc && rc != -ENOSPC) {
+ CERROR("10h: write %d records failed at #%d: %d\n",
+ llog_test_recnum, i + 1, rc);
+ GOTO(out, rc);
+ }
+ /*
+ * after last added plain LLOG has filled up, all new
+ * records add should fail with -ENOSPC
+ */
+ if (rc == -ENOSPC) {
+ enospc++;
+ } else {
+ enospc = 0;
+ eok++;
+ }
+ }
+
+ if ((enospc == 0) && (enospc+eok != llog_test_recnum)) {
+ CERROR("10h: all last records adds should have failed with"
+ " -ENOSPC\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ CWARN("10h: wrote %d records then %d failed with ENOSPC\n", eok,
+ enospc);
+
+ wait_for_completion(&lpi.lpi_completion);
+
+ if (lpi.lpi_rc != 0) {
+ CERROR("10h: race happened, old record was processed\n");
+ GOTO(out, rc = -EINVAL);
+ }
+ }
+out:
+ cfs_fail_loc = 0;
+ cfs_fail_val = 0;
+
+ CWARN("10: put newly-created catalog\n");
+ rc2 = llog_cat_close(env, cath);
+ if (rc2) {
+ CERROR("10: close log %s failed: %d\n", name, rc2);
+ if (rc == 0)
+ rc = rc2;
+ }
+ctxt_release:
+ 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);
+
+ rc = llog_test_9(env, obd);
+ if (rc != 0)
+ GOTO(cleanup, rc);
+
+ rc = llog_test_10(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;
+}
+
+static int llog_test_cleanup(struct obd_device *obd)
+{
+ struct obd_device *tgt;
+ struct lu_env env;
+ int rc;
+
+ ENTRY;
+
+ rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
+ if (rc)
+ RETURN(rc);
+
+ tgt = obd->obd_lvfs_ctxt.dt->dd_lu_dev.ld_obd;
+ rc = llog_cleanup(&env, llog_get_context(tgt, LLOG_TEST_ORIG_CTXT));
+ if (rc)
+ CERROR("failed to llog_test_llog_finish: %d\n", rc);
+ lu_env_fini(&env);
+ RETURN(rc);
+}
+
+static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
+{
+ struct obd_device *tgt;
+ struct llog_ctxt *ctxt;
+ struct dt_object *o;
+ struct lu_env env;
+ struct lu_context test_session;
+ int rc;
+
+ ENTRY;
+
+ if (lcfg->lcfg_bufcount < 2) {
+ CERROR("requires a TARGET OBD name\n");
+ RETURN(-EINVAL);
+ }
+
+ if (lcfg->lcfg_buflens[1] < 1) {
+ CERROR("requires a TARGET OBD name\n");
+ RETURN(-EINVAL);
+ }
+
+ /* disk obd */
+ tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
+ if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
+ CERROR("target device not attached or not set up (%s)\n",
+ lustre_cfg_string(lcfg, 1));
+ RETURN(-EINVAL);
+ }