Skip to content
Snippets Groups Projects
Commit 7d5a46f9 authored by Jinshan Xiong's avatar Jinshan Xiong
Browse files

b=12864
r=wangdi,nathan

Fixed a deadlock issue for LPROCFS.
parent 07f1efe4
No related merge requests found
......@@ -19,6 +19,8 @@ int ldlm_cancel_lru_local(struct ldlm_namespace *ns, struct list_head *cancels,
int ldlm_resource_putref_locked(struct ldlm_resource *res);
void ldlm_resource_insert_lock_after(struct ldlm_lock *original,
struct ldlm_lock *new);
int ldlm_namespace_free_prior(struct ldlm_namespace *ns);
int ldlm_namespace_free_post(struct ldlm_namespace *ns, int force);
/* ldlm_lock.c */
......
......@@ -355,6 +355,7 @@ int client_connect_import(struct lustre_handle *dlm_handle,
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;
......@@ -404,7 +405,8 @@ int client_connect_import(struct lustre_handle *dlm_handle,
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--;
......@@ -414,6 +416,8 @@ out_disco:
}
out_sem:
mutex_up(&cli->cl_sem);
if (to_be_freed)
ldlm_namespace_free_post(to_be_freed, 0);
return rc;
}
......@@ -422,6 +426,7 @@ int client_disconnect_export(struct obd_export *exp)
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;
......@@ -462,7 +467,8 @@ int client_disconnect_export(struct obd_export *exp)
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;
}
......@@ -482,6 +488,8 @@ int client_disconnect_export(struct obd_export *exp)
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);
}
......
......@@ -419,8 +419,7 @@ int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int flags)
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)
......@@ -433,19 +432,6 @@ int ldlm_namespace_free(struct ldlm_namespace *ns, int force)
/* 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;
......@@ -466,13 +452,58 @@ int ldlm_namespace_free(struct ldlm_namespace *ns, int force)
"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;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment