struct obd_import *imp = cli->cl_import;
struct obd_export *exp;
struct obd_connect_data *ocd;
+ struct ldlm_namespace *to_be_freed = NULL;
int rc;
ENTRY;
if (rc) {
out_ldlm:
- ldlm_namespace_free(obd->obd_namespace, 0);
+ ldlm_namespace_free_prior(obd->obd_namespace);
+ to_be_freed = obd->obd_namespace;
obd->obd_namespace = NULL;
out_disco:
cli->cl_conn_count--;
}
out_sem:
mutex_up(&cli->cl_sem);
+ if (to_be_freed)
+ ldlm_namespace_free_post(to_be_freed, 0);
return rc;
}
struct obd_device *obd = class_exp2obd(exp);
struct client_obd *cli;
struct obd_import *imp;
+ struct ldlm_namespace *to_be_freed = NULL;
int rc = 0, err;
ENTRY;
ldlm_cli_cancel_unused(obd->obd_namespace, NULL,
obd->obd_no_recov ? LDLM_FL_LOCAL_ONLY:0,
NULL);
- ldlm_namespace_free(obd->obd_namespace, obd->obd_no_recov);
+ ldlm_namespace_free_prior(obd->obd_namespace);
+ to_be_freed = obd->obd_namespace;
obd->obd_namespace = NULL;
}
rc = err;
out_sem:
mutex_up(&cli->cl_sem);
+ if (to_be_freed)
+ ldlm_namespace_free_post(to_be_freed, obd->obd_no_recov);
RETURN(rc);
}
return ELDLM_OK;
}
-/* Cleanup, but also free, the namespace */
-int ldlm_namespace_free(struct ldlm_namespace *ns, int force)
+int ldlm_namespace_free_prior(struct ldlm_namespace *ns)
{
ENTRY;
if (!ns)
/* At shutdown time, don't call the cancellation callback */
ldlm_namespace_cleanup(ns, 0);
-#ifdef LPROCFS
- {
- struct proc_dir_entry *dir;
- dir = lprocfs_srch(ldlm_ns_proc_dir, ns->ns_name);
- if (dir == NULL) {
- CERROR("dlm namespace %s has no procfs dir?\n",
- ns->ns_name);
- } else {
- lprocfs_remove(&dir);
- }
- }
-#endif
-
if (ns->ns_refcount > 0) {
struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL);
int rc;
"dlm namespace %s free done waiting\n", ns->ns_name);
}
+ RETURN(ELDLM_OK);
+}
+
+int ldlm_namespace_free_post(struct ldlm_namespace *ns, int force)
+{
+ ENTRY;
+ if (!ns)
+ RETURN(ELDLM_OK);
+
+#ifdef LPROCFS
+ {
+ struct proc_dir_entry *dir;
+ dir = lprocfs_srch(ldlm_ns_proc_dir, ns->ns_name);
+ if (dir == NULL) {
+ CERROR("dlm namespace %s has no procfs dir?\n",
+ ns->ns_name);
+ } else {
+ lprocfs_remove(&dir);
+ }
+ }
+#endif
+
POISON(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
OBD_VFREE(ns->ns_hash, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
OBD_FREE(ns->ns_name, strlen(ns->ns_name) + 1);
OBD_FREE(ns, sizeof(*ns));
ldlm_put_ref(force);
+ RETURN(ELDLM_OK);
+}
+/* Cleanup the resource, and free namespace.
+ * bug 12864:
+ * Deadlock issue:
+ * proc1: destroy import
+ * class_disconnect_export(grab cl_sem) ->
+ * -> ldlm_namespace_free ->
+ * -> lprocfs_remove(grab _lprocfs_lock).
+ * proc2: read proc info
+ * lprocfs_fops_read(grab _lprocfs_lock) ->
+ * -> osc_rd_active, etc(grab cl_sem).
+ *
+ * So that I have to split the ldlm_namespace_free into two parts - the first
+ * part ldlm_namespace_free_prior is used to cleanup the resource which is
+ * being used; the 2nd part ldlm_namespace_free_post is used to unregister the
+ * lprocfs entries, and then free memory. It will be called w/o cli->cl_sem
+ * held.
+ */
+int ldlm_namespace_free(struct ldlm_namespace *ns, int force)
+{
+ ldlm_namespace_free_prior(ns);
+ ldlm_namespace_free_post(ns, force);
return ELDLM_OK;
}