int ldlm_proc_setup(struct obd_device *obd)
{
ENTRY;
-
- if (obd->obd_proc_entry == NULL)
- RETURN(-EINVAL);
-
- ldlm_ns_proc_dir = proc_mkdir("namespaces", obd->obd_proc_entry);
- if (ldlm_ns_proc_dir == NULL) {
- CERROR("Couldn't create /proc/lustre/ldlm/namespaces\n");
- RETURN(-EPERM);
- }
+ LASSERT(ldlm_ns_proc_dir == NULL);
+ ldlm_ns_proc_dir=obd->obd_type->typ_procroot;
RETURN(0);
}
void ldlm_proc_cleanup(struct obd_device *obd)
{
- proc_lustre_remove_obd_entry("namespaces", obd);
+ ldlm_ns_proc_dir = NULL;
}
-/* FIXME: This can go away when we start to really use lprocfs */
-static int lprocfs_ll_rd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+#define MAX_STRING_SIZE 100
+void ldlm_proc_namespace(struct ldlm_namespace *ns)
{
- int len;
- __u64 *temp = (__u64 *)data;
+ struct lprocfs_vars lock_vars[2];
+ char lock_names[MAX_STRING_SIZE+1];
+
+ memset(lock_vars, 0, sizeof(lock_vars));
+ snprintf(lock_names, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name);
+ lock_names[MAX_STRING_SIZE] = '\0';
+ lock_vars[0].name = lock_names;
+ lock_vars[0].read_fptr = lprocfs_ll_rd;
+ lock_vars[0].write_fptr = NULL;
+ lock_vars[0].data = &ns->ns_resources;
+ lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
+
+ memset(lock_vars, 0, sizeof(lock_vars));
+ snprintf(lock_names, MAX_STRING_SIZE, "%s/lock_count", ns->ns_name);
+ lock_names[MAX_STRING_SIZE] = '\0';
+ lock_vars[0].name = lock_names;
+ lock_vars[0].read_fptr = lprocfs_ll_rd;
+ lock_vars[0].write_fptr = NULL;
+ lock_vars[0].data = &ns->ns_locks;
+ lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
- len = snprintf(page, count, "%Lu\n", *temp);
-
- return len;
}
+#undef MAX_STRING_SIZE
+#define LDLM_MAX_UNUSED 20
struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
{
struct ldlm_namespace *ns = NULL;
struct list_head *bucket;
- struct proc_dir_entry *proc_entry;
+
+
OBD_ALLOC(ns, sizeof(*ns));
if (!ns) {
bucket--)
INIT_LIST_HEAD(bucket);
+ INIT_LIST_HEAD(&ns->ns_unused_list);
+ ns->ns_nr_unused = 0;
+ ns->ns_max_unused = LDLM_MAX_UNUSED;
+
spin_lock(&ldlm_namespace_lock);
list_add(&ns->ns_list_chain, &ldlm_namespace_list);
spin_unlock(&ldlm_namespace_lock);
-
- ns->ns_proc_dir = proc_mkdir(ns->ns_name, ldlm_ns_proc_dir);
- if (ns->ns_proc_dir == NULL)
- CERROR("Unable to create proc directory for namespace.\n");
- proc_entry = create_proc_entry("resource_count", 0444, ns->ns_proc_dir);
- proc_entry->read_proc = lprocfs_ll_rd;
- proc_entry->data = &ns->ns_resources;
- proc_entry = create_proc_entry("lock_count", 0444, ns->ns_proc_dir);
- proc_entry->read_proc = lprocfs_ll_rd;
- proc_entry->data = &ns->ns_locks;
-
+ ldlm_proc_namespace(ns);
RETURN(ns);
out:
extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
-/* If 'local' is true, don't try to tell the server, just cleanup. */
+/* If 'local_only' is true, don't try to tell the server, just cleanup. */
static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
- int local)
+ int local_only)
{
struct list_head *tmp, *pos;
int rc = 0, client = res->lr_namespace->ns_client;
lock = list_entry(tmp, struct ldlm_lock, l_res_link);
LDLM_LOCK_GET(lock);
+ /* At shutdown time, don't call the cancellation callback */
+ lock->l_flags |= LDLM_FL_CANCEL;
+
if (client) {
struct lustre_handle lockh;
ldlm_lock2handle(lock, &lockh);
- if (!local) {
+ if (!local_only) {
rc = ldlm_cli_cancel(&lockh);
if (rc)
CERROR("ldlm_cli_cancel: %d\n", rc);
}
/* Force local cleanup on errors, too. */
- if (local || rc != ELDLM_OK)
+ if (local_only || rc != ELDLM_OK)
ldlm_lock_cancel(lock);
} else {
LDLM_DEBUG(lock, "Freeing a lock still held by a "
}
}
-int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local)
+int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only)
{
int i;
res = list_entry(tmp, struct ldlm_resource, lr_hash);
ldlm_resource_getref(res);
- cleanup_resource(res, &res->lr_granted, local);
- cleanup_resource(res, &res->lr_converting, local);
- cleanup_resource(res, &res->lr_waiting, local);
+ cleanup_resource(res, &res->lr_granted, local_only);
+ cleanup_resource(res, &res->lr_converting, local_only);
+ cleanup_resource(res, &res->lr_waiting, local_only);
- if (!ldlm_resource_put(res)) {
+ /* XXX this is a bit counter-intuitive and should
+ * probably be cleaner: don't force cleanup if we're
+ * local_only (which is only used by recovery). We
+ * probably still have outstanding lock refs which
+ * reference these resources. -phil */
+ if (!ldlm_resource_put(res) && !local_only) {
CERROR("Resource refcount nonzero (%d) after "
"lock cleanup; forcing cleanup.\n",
atomic_read(&res->lr_refcount));
spin_lock(&ldlm_namespace_lock);
list_del(&ns->ns_list_chain);
- remove_proc_entry("resource_count", ns->ns_proc_dir);
- remove_proc_entry("lock_count", ns->ns_proc_dir);
- remove_proc_entry(ns->ns_name, ldlm_ns_proc_dir);
+
spin_unlock(&ldlm_namespace_lock);
ldlm_namespace_cleanup(ns, 0);