+
+ cfs_spin_lock(&olg->olg_lock);
+ if (!cfs_atomic_dec_and_test(&ctxt->loc_refcount)) {
+ cfs_spin_unlock(&olg->olg_lock);
+ return rc;
+ }
+ olg->olg_ctxts[ctxt->loc_idx] = NULL;
+ cfs_spin_unlock(&olg->olg_lock);
+
+ if (ctxt->loc_lcm)
+ lcm_put(ctxt->loc_lcm);
+
+ obd = ctxt->loc_obd;
+ cfs_spin_lock(&obd->obd_dev_lock);
+ /* sync with llog ctxt user thread */
+ cfs_spin_unlock(&obd->obd_dev_lock);
+
+ /* obd->obd_starting is needed for the case of cleanup
+ * in error case while obd is starting up. */
+ LASSERTF(obd->obd_starting == 1 ||
+ obd->obd_stopping == 1 || obd->obd_set_up == 0,
+ "wrong obd state: %d/%d/%d\n", !!obd->obd_starting,
+ !!obd->obd_stopping, !!obd->obd_set_up);
+
+ /* cleanup the llog ctxt here */
+ if (CTXTP(ctxt, cleanup))
+ rc = CTXTP(ctxt, cleanup)(NULL, ctxt);
+
+ llog_ctxt_destroy(ctxt);
+ cfs_waitq_signal(&olg->olg_waitq);
+ return rc;
+}
+EXPORT_SYMBOL(__llog_ctxt_put);
+
+int llog_cleanup(struct llog_ctxt *ctxt)
+{
+ struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
+ struct obd_llog_group *olg;
+ int rc, idx;
+ ENTRY;
+
+ LASSERT(ctxt != NULL);
+ LASSERT(ctxt != LP_POISON);
+
+ olg = ctxt->loc_olg;
+ LASSERT(olg != NULL);
+ LASSERT(olg != LP_POISON);
+
+ idx = ctxt->loc_idx;
+
+ /*
+ * Banlance the ctxt get when calling llog_cleanup()
+ */
+ LASSERT(cfs_atomic_read(&ctxt->loc_refcount) < LI_POISON);
+ LASSERT(cfs_atomic_read(&ctxt->loc_refcount) > 1);
+ llog_ctxt_put(ctxt);
+
+ /*
+ * Try to free the ctxt.
+ */
+ rc = __llog_ctxt_put(ctxt);
+ if (rc)
+ CERROR("Error %d while cleaning up ctxt %p\n",
+ rc, ctxt);
+
+ l_wait_event(olg->olg_waitq,
+ llog_group_ctxt_null(olg, idx), &lwi);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_cleanup);
+
+int llog_setup_named(struct obd_device *obd, struct obd_llog_group *olg,
+ int index, struct obd_device *disk_obd, int count,
+ struct llog_logid *logid, const char *logname,
+ struct llog_operations *op)
+{