diff --git a/lustre/ldlm/ldlm_internal.h b/lustre/ldlm/ldlm_internal.h index fe460c0f74855575373bd7bf5609ed6efbad2ef3..165fd6f54c20688ba8fe9f5b02762660d4a082e1 100644 --- a/lustre/ldlm/ldlm_internal.h +++ b/lustre/ldlm/ldlm_internal.h @@ -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 */ diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index f270616b375306f4e7a50b0ba5a8850f141b63dc..a3133eb3912a4a610597932c6b3416a6f14bb207 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.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); } diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index 0d489ce21b9f916b5e92dc23e0e568f26a8adaba..4c40151ea7fe18284b305af1e0e7ce881e079a57 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -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; }