+static int cleanup_resource(struct ldlm_resource *res, struct list_head *q)
+{
+ struct list_head *tmp, *pos;
+ int rc = 0;
+
+ list_for_each_safe(tmp, pos, q) {
+ struct ldlm_lock *lock;
+
+ if (rc) {
+ /* Res was already cleaned up. */
+ LBUG();
+ }
+
+ lock = list_entry(tmp, struct ldlm_lock, l_res_link);
+
+ ldlm_resource_del_lock(lock);
+ ldlm_lock_free(lock);
+ rc = ldlm_resource_put(res);
+ }
+
+ return rc;
+}
+
+static int do_free_namespace(struct ldlm_namespace *ns)
+{
+ struct list_head *tmp, *pos;
+ int i, rc;
+
+ for (i = 0; i < RES_HASH_SIZE; i++) {
+ list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
+ struct ldlm_resource *res;
+ res = list_entry(tmp, struct ldlm_resource, lr_hash);
+ list_del_init(&res->lr_hash);
+
+ rc = cleanup_resource(res, &res->lr_granted);
+ if (!rc)
+ rc = cleanup_resource(res, &res->lr_converting);
+ if (!rc)
+ rc = cleanup_resource(res, &res->lr_waiting);
+
+ while (rc == 0)
+ rc = ldlm_resource_put(res);
+ }
+ }
+
+ return ldlm_namespace_free(ns);
+}
+
+static int ldlm_free_all(struct obd_device *obddev)
+{
+ struct list_head *tmp, *pos;
+ int rc = 0;
+
+ ldlm_lock();
+
+ list_for_each_safe(tmp, pos, &ldlm_namespaces) {
+ struct ldlm_namespace *ns;
+ ns = list_entry(tmp, struct ldlm_namespace, ns_link);
+
+ rc |= do_free_namespace(ns);
+ }
+
+ ldlm_unlock();
+
+ return rc;
+}
+