+static int llog_declare_destroy(const struct lu_env *env,
+ struct llog_handle *handle,
+ struct thandle *th)
+{
+ struct llog_operations *lop;
+ int rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_declare_destroy == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ rc = lop->lop_declare_destroy(env, handle, th);
+
+ RETURN(rc);
+}
+
+int llog_trans_destroy(const struct lu_env *env, struct llog_handle *handle,
+ struct thandle *th)
+{
+ struct llog_operations *lop;
+ int rc;
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc < 0)
+ RETURN(rc);
+ if (lop->lop_destroy == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ LASSERT(handle->lgh_obj != NULL);
+ if (!dt_object_exists(handle->lgh_obj))
+ RETURN(0);
+
+ rc = lop->lop_destroy(env, handle, th);
+
+ RETURN(rc);
+}
+
+int llog_destroy(const struct lu_env *env, struct llog_handle *handle)
+{
+ struct llog_operations *lop;
+ struct dt_device *dt;
+ struct thandle *th;
+ int rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc < 0)
+ RETURN(rc);
+ if (lop->lop_destroy == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ if (handle->lgh_obj == NULL) {
+ /* if lgh_obj == NULL, then it is from client side destroy */
+ rc = lop->lop_destroy(env, handle, NULL);
+ RETURN(rc);
+ }
+
+ if (!dt_object_exists(handle->lgh_obj))
+ RETURN(0);
+
+ dt = lu2dt_dev(handle->lgh_obj->do_lu.lo_dev);
+
+ th = dt_trans_create(env, dt);
+ if (IS_ERR(th))
+ RETURN(PTR_ERR(th));
+
+ rc = llog_declare_destroy(env, handle, th);
+ if (rc != 0)
+ GOTO(out_trans, rc);
+
+ rc = dt_trans_start_local(env, dt, th);
+ if (rc < 0)
+ GOTO(out_trans, rc);
+
+ rc = lop->lop_destroy(env, handle, th);
+
+out_trans:
+ dt_trans_stop(env, dt, th);
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_destroy);
+