--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+
+#ifndef _LUSTRE_DLM_H__
+#define _LUSTRE_DLM_H__
+
+#include <linux/kp30.h>
+#include <linux/list.h>
+
+#define OBD_LDLM_DEVICENAME "ldlm"
+
+typedef int cluster_host;
+typedef int cluster_pid;
+
+/* lock types */
+typedef enum {
+ LCK_EX,
+ LCK_PW,
+ LCK_PR,
+ LCK_CW,
+ LCK_CR,
+ LCK_NL
+} ldlm_mode_t;
+
+#define L2B(c) (1<<c)
+
+/* compatibility matrix */
+#define LCK_COMPAT_EX L2B(LCK_NL)
+#define LCK_COMPAT_PW (LCK_COMPAT_EX | L2B(LCK_CR))
+#define LCK_COMPAT_PR (LCK_COMPAT_PW | L2B(LCK_PR))
+#define LCK_COMPAT_CW (LCK_COMPAT_PW | L2B(LCK_CW))
+#define LCK_COMPAT_CR (LCK_COMPAT_CW | L2B(LCK_PR) | L2B(LCK_PW))
+#define LCK_COMPAT_NL (LCK_COMPAT_CR | L2B(LCK_EX))
+
+static ldlm_mode_t lck_compat_array[] = {
+ LCK_COMPAT_EX,
+ LCK_COMPAT_PW,
+ LCK_COMPAT_PR,
+ LCK_COMPAT_CW,
+ LCK_COMPAT_CR,
+ LCK_COMPAT_NL
+};
+
+static inline int lockmode_compat(ldlm_mode_t a, ldlm_mode_t b)
+{
+ if ( 0 <= a && a <= 5 ) {
+ BUG();
+ }
+ if( 0 <= b && b <= 5 ) {
+ BUG();
+ }
+
+ return 1 && (lck_compat_array[a] & L2B(b));
+}
+
+/*
+ *
+ * cluster name spaces
+ *
+ */
+
+#define DLM_OST_NAMESPACE 1
+#define DLM_MDS_NAMESPACE 2
+
+/* XXX
+ - do we just separate this by security domains and use a prefix for
+ multiple namespaces in the same domain?
+ -
+*/
+
+struct ldlm_namespace {
+ struct list_head ns_link; /* in the list of ns's */
+ __u32 ns_id; /* identifier of ns */
+ struct list_head *ns_hash; /* hash table for ns */
+ struct list_head ns_root_list; /* all root resources in ns */
+};
+
+/*
+ *
+ * Resource hash table
+ *
+ */
+
+#define RES_HASH_BITS 18
+#define RES_HASH_SIZE (1UL << RES_HASH_BITS)
+#define RES_HASH_MASK (RES_HASH_SIZE - 1)
+
+#define RES_NAME_SIZE 6
+#define RES_VERSION_SIZE 4
+
+struct ldlm_resource {
+ struct list_head lr_hash;
+ struct list_head lr_rootlink; /* link all root resources in NS */
+ struct ldlm_resource *lr_parent; /* 0 for a root resource */
+ struct list_head lr_children; /* list head for child resources */
+ struct list_head lr_childof; /* part of child list of parent */
+
+ struct list_head lr_granted;
+ struct list_head lr_converting;
+ struct list_head lr_waiting;
+ ldlm_mode_t lr_most_restr;
+ struct ldlm_resource *lr_root;
+ //XXX cluster_host lr_master;
+ __u32 lr_name[RES_NAME_SIZE];
+ __u32 lr_version[RES_VERSION_SIZE];
+};
+
+struct ldlm_lock {
+ struct ldlm_resource *lb_resource;
+ struct ldlm_lock *lb_parent;
+ struct list_head lb_children;
+ struct list_head lb_childof;
+ unsigned long lb_id;
+ ldlm_mode_t lb_req_mode;
+ ldlm_mode_t lb_granted_mode;
+ void *lb_completion_ast;
+ void *lb_blocking_ast;
+ void *lb_event;
+ //XXX cluster_host lb_holder;
+ __u32 lb_version[RES_VERSION_SIZE];
+};
+
+struct ldlm_obd {
+ struct list_head ldlm_namespaces;
+};
+
+extern struct obd_ops ldlm_obd_ops;
+
+#endif
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * obd/ldlm/resource.c
+ *
+ * Copyright (C) 2002 Cluster File Systems, Inc.
+ *
+ * This code is issued under the GNU General Public License.
+ * See the file COPYING in this distribution
+ *
+ * by Cluster File Systems, Inc.
+ */
+
+#define EXPORT_SYMTAB
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/unistd.h>
+
+#define DEBUG_SUBSYSTEM S_LDLM
+
+#include <linux/obd_support.h>
+#include <linux/obd_class.h>
+
+#include <linux/lustre_dlm.h>
+
+static kmem_cache_t *ldlm_resource_slab;
+static kmem_cache_t *ldlm_lock_slab;
+
+struct ldlm_namespace *ldlm_namespace_find(struct obd_device *obddev, __u32 id)
+{
+ struct list_head *tmp;
+ struct ldlm_namespace *res;
+
+ res = NULL;
+ list_for_each(tmp, &obddev->u.ldlm.ldlm_namespaces) {
+ struct ldlm_namespace *chk;
+ chk = list_entry(tmp, struct ldlm_namespace, ns_link);
+
+ if ( chk->ns_id == id ) {
+ res = chk;
+ break;
+ }
+ }
+ return res;
+}
+
+static void res_hash_init(struct ldlm_namespace *name_space)
+{
+ struct list_head *res_hash;
+ struct list_head *bucket;
+
+ OBD_ALLOC(res_hash, sizeof(struct list_head) * RES_HASH_SIZE);
+ if (!res_hash)
+ BUG();
+
+ for (bucket = res_hash + RES_HASH_SIZE-1 ; bucket >= res_hash ;
+ bucket--) {
+ INIT_LIST_HEAD(bucket);
+ }
+
+ name_space->ns_hash = res_hash;
+}
+
+struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obddev, __u32 id)
+{
+ struct ldlm_namespace *ns;
+
+ if (ldlm_namespace_find(obddev, id))
+ BUG();
+
+ OBD_ALLOC(ns, sizeof(*ns));
+ if (!ns)
+ BUG();
+
+ ns->ns_id = id;
+ INIT_LIST_HEAD(&ns->ns_root_list);
+ list_add(&ns->ns_link, &obddev->u.ldlm.ldlm_namespaces);
+
+ res_hash_init(ns);
+ return ns;
+}
+
+__u32 ldlm_hash_fn(struct ldlm_resource *parent, __u32 *name)
+{
+ __u32 hash = 0;
+ int i;
+
+ for (i = 0; i < RES_NAME_SIZE; i++) {
+ hash += name[i];
+ }
+
+ hash += (__u32)((unsigned long)parent >> 4);
+
+ return (hash & RES_HASH_MASK);
+}
+
+struct ldlm_resource *ldlm_resource_find(struct ldlm_namespace *ns,
+ struct ldlm_resource *parent,
+ __u32 *name)
+{
+ struct list_head *bucket;
+ struct list_head *tmp = bucket;
+ struct ldlm_resource *res;
+
+ if (ns->ns_hash == NULL)
+ BUG();
+ bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
+
+ res = NULL;
+ list_for_each(tmp, bucket) {
+ struct ldlm_resource *chk;
+ chk = list_entry(tmp, struct ldlm_resource, lr_hash);
+
+ if (memcmp(chk->lr_name, name, RES_NAME_SIZE * sizeof(__u32))){
+ res = chk;
+ break;
+ }
+ }
+
+ return res;
+}
+
+struct ldlm_resource *ldlm_resource_new(void)
+{
+ struct ldlm_resource *res;
+
+ res = kmem_cache_alloc(ldlm_resource_slab, SLAB_KERNEL);
+ if (res == NULL)
+ BUG();
+ memset(res, 0, sizeof(*res));
+
+ INIT_LIST_HEAD(&res->lr_children);
+ INIT_LIST_HEAD(&res->lr_granted);
+ INIT_LIST_HEAD(&res->lr_converting);
+ INIT_LIST_HEAD(&res->lr_waiting);
+
+ return res;
+}
+
+struct ldlm_resource *ldlm_resource_add(struct obd_device *obddev, __u32 id,
+ struct ldlm_resource *parent,
+ __u32 *name)
+{
+ struct ldlm_namespace *ns;
+ struct list_head *bucket;
+ struct ldlm_resource *res;
+
+ ns = ldlm_namespace_find(obddev, id);
+ if (ns == NULL || ns->ns_hash == NULL)
+ BUG();
+
+ bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
+
+ if (ldlm_resource_find(ns, parent, name) != NULL)
+ BUG();
+
+ res = ldlm_resource_new();
+ if (!res)
+ BUG();
+
+ memcpy(res->lr_name, name, RES_NAME_SIZE * sizeof(__u32));
+ list_add(&res->lr_hash, bucket);
+ if (parent == NULL) {
+ res->lr_parent = res;
+ list_add(&res->lr_rootlink, &ns->ns_root_list);
+ } else {
+ res->lr_parent = parent;
+ list_add(&res->lr_childof, &parent->lr_children);
+ }
+
+ return res;
+}
+
+static int ldlm_obd_setup(struct obd_device *obddev, obd_count len, void *data)
+{
+ INIT_LIST_HEAD(&obddev->u.ldlm.ldlm_namespaces);
+
+ return 0;
+}
+
+struct obd_ops ldlm_obd_ops = {
+ o_setup: ldlm_obd_setup,
+ o_connect: gen_connect,
+ o_disconnect: gen_disconnect,
+};
+
+static int __init ldlm_init(void)
+{
+ int rc = obd_register_type(&ldlm_obd_ops, OBD_LDLM_DEVICENAME);
+ if (rc != 0)
+ return rc;
+
+ ldlm_resource_slab = kmem_cache_create("ldlm_resources",
+ sizeof(struct ldlm_resource), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (ldlm_resource_slab == NULL)
+ return -ENOMEM;
+
+ ldlm_lock_slab = kmem_cache_create("ldlm_locks",
+ sizeof(struct ldlm_lock), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (ldlm_lock_slab == NULL) {
+ kmem_cache_destroy(ldlm_resource_slab);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void __exit ldlm_exit(void)
+{
+ obd_unregister_type(OBD_LDLM_DEVICENAME);
+ kmem_cache_destroy(ldlm_resource_slab);
+ kmem_cache_destroy(ldlm_lock_slab);
+}
+
+MODULE_AUTHOR("Cluster File Systems, Inc. <braam@clusterfs.com>");
+MODULE_DESCRIPTION("Lustre Lock Management Module v0.1");
+MODULE_LICENSE("GPL");
+
+module_init(ldlm_init);
+module_exit(ldlm_exit);