Introduce md_cluster_info

md_cluster_info stores the cluster information in the MD device.

The join() is called when mddev detects it is a clustered device.
The main responsibilities are:
	1. Setup a DLM lockspace
	2. Setup all initial locks such as super block locks and bitmap lock (will come later)

The leave() clears up the lockspace and all the locks held.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index e223560..d141d48 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -22,8 +22,16 @@
 	struct dlm_lksb lksb;
 	char *name; /* lock name. */
 	uint32_t flags; /* flags to pass to dlm_lock() */
-	void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
 	struct completion completion; /* completion for synchronized locking */
+	void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
+	struct mddev *mddev; /* pointing back to mddev. */
+};
+
+struct md_cluster_info {
+	/* dlm lock space and resources for clustered raid. */
+	dlm_lockspace_t *lockspace;
+	struct dlm_lock_resource *sb_lock;
+	struct mutex sb_mutex;
 };
 
 static void sync_ast(void *arg)
@@ -53,16 +61,18 @@
 	return dlm_lock_sync(res, DLM_LOCK_NL);
 }
 
-static struct dlm_lock_resource *lockres_init(dlm_lockspace_t *lockspace,
+static struct dlm_lock_resource *lockres_init(struct mddev *mddev,
 		char *name, void (*bastfn)(void *arg, int mode), int with_lvb)
 {
 	struct dlm_lock_resource *res = NULL;
 	int ret, namelen;
+	struct md_cluster_info *cinfo = mddev->cluster_info;
 
 	res = kzalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL);
 	if (!res)
 		return NULL;
-	res->ls = lockspace;
+	res->ls = cinfo->lockspace;
+	res->mddev = mddev;
 	namelen = strlen(name);
 	res->name = kzalloc(namelen + 1, GFP_KERNEL);
 	if (!res->name) {
@@ -114,13 +124,62 @@
 	kfree(res);
 }
 
+static char *pretty_uuid(char *dest, char *src)
+{
+	int i, len = 0;
+
+	for (i = 0; i < 16; i++) {
+		if (i == 4 || i == 6 || i == 8 || i == 10)
+			len += sprintf(dest + len, "-");
+		len += sprintf(dest + len, "%02x", (__u8)src[i]);
+	}
+	return dest;
+}
+
 static int join(struct mddev *mddev, int nodes)
 {
+	struct md_cluster_info *cinfo;
+	int ret;
+	char str[64];
+
+	if (!try_module_get(THIS_MODULE))
+		return -ENOENT;
+
+	cinfo = kzalloc(sizeof(struct md_cluster_info), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	memset(str, 0, 64);
+	pretty_uuid(str, mddev->uuid);
+	ret = dlm_new_lockspace(str, NULL, DLM_LSFL_FS, LVB_SIZE,
+				NULL, NULL, NULL, &cinfo->lockspace);
+	if (ret)
+		goto err;
+	cinfo->sb_lock = lockres_init(mddev, "cmd-super",
+					NULL, 0);
+	if (!cinfo->sb_lock) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	mutex_init(&cinfo->sb_mutex);
+	mddev->cluster_info = cinfo;
 	return 0;
+err:
+	if (cinfo->lockspace)
+		dlm_release_lockspace(cinfo->lockspace, 2);
+	kfree(cinfo);
+	module_put(THIS_MODULE);
+	return ret;
 }
 
 static int leave(struct mddev *mddev)
 {
+	struct md_cluster_info *cinfo = mddev->cluster_info;
+
+	if (!cinfo)
+		return 0;
+	lockres_free(cinfo->sb_lock);
+	dlm_release_lockspace(cinfo->lockspace, 2);
 	return 0;
 }