[Ocfs2-tools-devel] [PATCH 09/32] o2cb_scandisk: Scan heartbeat devices

Sunil Mushran sunil.mushran at oracle.com
Tue Sep 14 15:54:39 PDT 2010


o2cb_scandisk uses the scandisk library to scan all the partitions to locate
the given heartbeat devices.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 o2cb_ctl/Makefile        |    6 ++
 o2cb_ctl/o2cb_scandisk.c |  199 ++++++++++++++++++++++++++++++++++++++++++++++
 o2cb_ctl/o2cb_scandisk.h |   43 ++++++++++
 3 files changed, 248 insertions(+), 0 deletions(-)
 create mode 100644 o2cb_ctl/o2cb_scandisk.c
 create mode 100644 o2cb_ctl/o2cb_scandisk.h

diff --git a/o2cb_ctl/Makefile b/o2cb_ctl/Makefile
index d2710e6..0a6cb8b 100644
--- a/o2cb_ctl/Makefile
+++ b/o2cb_ctl/Makefile
@@ -7,12 +7,18 @@ SBIN_PROGRAMS = o2cb_ctl
 
 INCLUDES = -I$(TOPDIR)/include
 
+LIBTOOLS_INTERNAL_LIBS = -L$(TOPDIR)/libtools-internal -ltools-internal
+LIBTOOLS_INTERNAL_DEPS = $(TOPDIR)/libtools-internal/libtools-internal.a
+
 LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
 LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
 
 LIBO2CB_LIBS  = -L$(TOPDIR)/libo2cb -lo2cb
 LIBO2CB_DEPS = $(TOPDIR)/libo2cb/libo2cb.a
 
+LIBO2DLM_LIBS = -L$(TOPDIR)/libo2dlm -lo2dlm $(DL_LIBS)
+LIBO2DLM_DEPS = $(TOPDIR)/libo2dlm/libo2dlm.a
+
 ifndef OCFS2_DYNAMIC_CTL
 LDFLAGS += -static
 endif
diff --git a/o2cb_ctl/o2cb_scandisk.c b/o2cb_ctl/o2cb_scandisk.c
new file mode 100644
index 0000000..94d0b55
--- /dev/null
+++ b/o2cb_ctl/o2cb_scandisk.c
@@ -0,0 +1,199 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2cb_scandisk.c
+ *
+ * Reads all the partitions and get the ocfs2 uuids
+ *
+ * Copyright (C) 2010 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "o2cb_scandisk.h"
+#include "ocfs2/ocfs2.h"
+#include "tools-internal/verbose.h"
+
+struct hb_devices {
+	struct list_head hb_list;
+	char *hb_path;
+};
+
+struct scan_context {
+	struct list_head sc_devlist;
+	int sc_rescan;
+};
+
+static int fill_desc(char *device, struct o2cb_region_desc *reg,
+		     struct o2cb_cluster_desc *cluster)
+{
+	ocfs2_filesys *fs;
+	errcode_t ret;
+
+	ret = ocfs2_open(device, OCFS2_FLAG_RO | OCFS2_FLAG_HEARTBEAT_DEV_OK,
+			 0, 0, &fs);
+	if (ret)
+		return ret;
+
+	ret = ocfs2_fill_heartbeat_desc(fs, reg);
+	if (!ret)
+		ret = ocfs2_fill_cluster_desc(fs, cluster);
+
+	if (!ret) {
+		/* TODO free this alloc... or not */
+		reg->r_name = strdup(reg->r_name);
+		reg->r_device_name = strdup(reg->r_device_name);
+	}
+
+	ocfs2_close(fs);
+
+	return ret;
+}
+
+static void get_device_uuids(struct scan_context *ctxt, struct list_head *hbdevs)
+{
+	struct o2cb_device *od;
+	struct list_head *pos, *pos1;
+	struct hb_devices *hb;
+	struct o2cb_region_desc rd;
+	struct o2cb_cluster_desc cd;
+	int numhbdevs = 0;
+
+	list_for_each(pos, hbdevs) {
+		++numhbdevs;
+	}
+
+	if (!numhbdevs)
+		return;
+
+	list_for_each(pos, &ctxt->sc_devlist) {
+		hb = list_entry(pos, struct hb_devices, hb_list);
+
+		if (fill_desc(hb->hb_path, &rd, &cd))
+			continue;
+
+		list_for_each(pos1, hbdevs) {
+			od = list_entry(pos1, struct o2cb_device, od_list);
+			if (od->od_flags & O2CB_DEVICE_FOUND)
+				continue;
+			if (strcmp(rd.r_name, od->od_uuid))
+				continue;
+			od->od_flags |= O2CB_DEVICE_FOUND;
+			memcpy(&od->od_region, &rd, sizeof(od->od_region));
+			memcpy(&od->od_cluster, &cd, sizeof(od->od_cluster));
+
+			verbosef(VL_DEBUG, "Region %s matched to device %s\n",
+				 rd.r_name, rd.r_device_name);
+			--numhbdevs;
+			break;
+		}
+		if (!numhbdevs)
+			break;
+	}
+}
+
+static void free_scan_context(struct scan_context *ctxt)
+{
+	struct list_head *pos, *pos1;
+	struct hb_devices *hb;
+
+	if (!ctxt)
+		return ;
+
+	list_for_each_safe(pos, pos1, &ctxt->sc_devlist) {
+		hb = list_entry(pos, struct hb_devices, hb_list);
+		list_del(pos);
+		free(hb);
+	}
+}
+
+static void add_to_list(struct list_head *device_list, struct devnode *node)
+{
+	struct devpath *path;
+	struct hb_devices *hb;
+	int add = 0;
+
+	path = node->devpath;
+	while (path) {
+		if (node->mapper)
+			add = !strncmp(path->path, "/dev/mapper/", 12);
+		else
+			add = !strncmp(path->path, "/dev/sd", 7);
+		if (add) {
+			hb = malloc(sizeof(struct hb_devices));
+			if (hb) {
+				hb->hb_path = strdup(path->path);
+				list_add_tail(&hb->hb_list, device_list);
+				break;
+			}
+		}
+		path = path->next;
+	}
+}
+
+static void filter_devices(struct devnode *node, void *user_data)
+{
+	struct scan_context *ctxt = user_data;
+
+	/* No information in sysfs?  Ignore it! */
+	if (!node->sysfsattrs.sysfs)
+		return;
+
+	/* Not a disk?  Ignore it! */
+	if (!node->sysfsattrs.disk)
+		return;
+
+	/* It's part of some other device?  Ignore it! */
+	if (node->sysfsattrs.holders)
+		return;
+
+	/*
+	 * No path in /dev?  Well, udev probably hasn't gotten there. Trigger
+	 * a rescan
+	 */
+	if (!node->devpath) {
+		ctxt->sc_rescan = 1;
+		return;
+	}
+
+	add_to_list(&ctxt->sc_devlist, node);
+}
+
+void o2cb_scandisk(struct list_head *hbdevs)
+{
+	struct devlisthead *dev = NULL;
+	int delay = 1;
+	struct scan_context scan_ctxt, *ctxt = &scan_ctxt;
+
+	INIT_LIST_HEAD(&ctxt->sc_devlist);
+
+	do {
+		ctxt->sc_rescan = 0;
+		if (delay > 5)
+			break;
+
+		if (dev) {
+			free_scan_context(ctxt);
+			free_dev_list(dev);
+			sleep(delay);
+			delay += 2;
+		}
+
+		dev = scan_for_dev(NULL, 5, filter_devices, ctxt);
+		if (!dev)
+			goto bail;
+	} while (ctxt->sc_rescan);
+
+	get_device_uuids(ctxt, hbdevs);
+
+bail:
+	free_scan_context(ctxt);
+	free_dev_list(dev);
+}
diff --git a/o2cb_ctl/o2cb_scandisk.h b/o2cb_ctl/o2cb_scandisk.h
new file mode 100644
index 0000000..7ff1fe4
--- /dev/null
+++ b/o2cb_ctl/o2cb_scandisk.h
@@ -0,0 +1,43 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2cb_scandisk.h
+ *
+ * Copyright (C) 2010 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <sys/sysmacros.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "tools-internal/scandisk.h"
+#include "o2cb/o2cb.h"
+
+#include "ocfs2-kernel/kernel-list.h"
+
+struct o2cb_device {
+	struct list_head od_list;
+	char *od_uuid;
+#define O2CB_DEVICE_FOUND		0x01
+#define O2CB_DEVICE_HB_STARTED		0x02
+	int od_flags;
+	struct o2cb_region_desc od_region;
+	struct o2cb_cluster_desc od_cluster;
+};
+
+void o2cb_scandisk(struct list_head *hbdevs);
-- 
1.7.0.4




More information about the Ocfs2-tools-devel mailing list