+ ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0);
+
+ if (ns->ns_refcount > 0) {
+ struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
+ int rc;
+ CDEBUG(D_DLMTRACE,
+ "dlm namespace %s free waiting on refcount %d\n",
+ ns->ns_name, ns->ns_refcount);
+force_wait:
+ if (force)
+ lwi = LWI_TIMEOUT(obd_timeout * CFS_HZ / 4, NULL, NULL);
+
+ rc = l_wait_event(ns->ns_waitq,
+ ns->ns_refcount == 0, &lwi);
+
+ /* Forced cleanups should be able to reclaim all references,
+ * so it's safe to wait forever... we can't leak locks... */
+ if (force && rc == -ETIMEDOUT) {
+ LCONSOLE_ERROR("Forced cleanup waiting for %s "
+ "namespace with %d resources in use, "
+ "(rc=%d)\n", ns->ns_name,
+ ns->ns_refcount, rc);
+ GOTO(force_wait, rc);
+ }
+
+ if (ns->ns_refcount) {
+ LCONSOLE_ERROR("Cleanup waiting for %s namespace "
+ "with %d resources in use, (rc=%d)\n",
+ ns->ns_name,
+ ns->ns_refcount, rc);
+ RETURN(ELDLM_NAMESPACE_EXISTS);
+ }
+ CDEBUG(D_DLMTRACE,
+ "dlm namespace %s free done waiting\n", ns->ns_name);
+ }
+
+ RETURN(ELDLM_OK);
+}
+
+/**
+ * Performs various cleanups for passed \a ns to make it drop refc and be ready
+ * for freeing. Waits for refc == 0.
+ *
+ * The following is done:
+ * (0) Unregister \a ns from its list to make inaccessible for potential users
+ * like pools thread and others;
+ * (1) Clear all locks in \a ns.
+ */
+void ldlm_namespace_free_prior(struct ldlm_namespace *ns,
+ struct obd_import *imp,
+ int force)
+{
+ int rc;
+ ENTRY;
+ if (!ns) {
+ EXIT;
+ return;
+ }
+
+
+ /*
+ * Can fail with -EINTR when force == 0 in which case try harder.
+ */
+ rc = __ldlm_namespace_free(ns, force);
+ if (rc != ELDLM_OK) {
+ if (imp) {
+ ptlrpc_disconnect_import(imp, 0);
+ ptlrpc_invalidate_import(imp);
+ }
+
+ /*
+ * With all requests dropped and the import inactive
+ * we are gaurenteed all reference will be dropped.
+ */
+ rc = __ldlm_namespace_free(ns, 1);
+ LASSERT(rc == 0);
+ }
+ EXIT;
+}
+
+/**
+ * Performs freeing memory structures related to \a ns. This is only done when
+ * ldlm_namespce_free_prior() successfully removed all resources referencing
+ * \a ns and its refc == 0.
+ */
+void ldlm_namespace_free_post(struct ldlm_namespace *ns)
+{
+ ENTRY;
+ if (!ns) {
+ EXIT;
+ return;
+ }
+
+
+ /*
+ * Make sure that nobody can find this ns in its list.
+ */
+ ldlm_namespace_unregister(ns, ns->ns_client);
+ /*
+ * Fini pool _before_ parent proc dir is removed. This is important as
+ * ldlm_pool_fini() removes own proc dir which is child to @dir. Removing
+ * it after @dir may cause oops.
+ */
+ ldlm_pool_fini(&ns->ns_pool);