[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] cluster/cman-kernel/src proc.c



CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL4
Changes by:	rpeterso sourceware org	2006-11-07 17:47:50

Modified files:
	cman-kernel/src: proc.c 

Log message:
	This is the fix for Bugzilla Bug 213723: [CS4] system crashes
	with the command less /proc/cluster/status.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman-kernel/src/proc.c.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.11.2.6&r2=1.11.2.7

--- cluster/cman-kernel/src/Attic/proc.c	2006/04/24 12:32:13	1.11.2.6
+++ cluster/cman-kernel/src/Attic/proc.c	2006/11/07 17:47:50	1.11.2.7
@@ -41,6 +41,33 @@
 extern char nodename[];
 extern struct cluster_node *us;
 static struct seq_operations cluster_info_op;
+static struct seq_operations cluster_status_info_op;
+
+enum status_state {
+	state_protocol_version,
+	state_config_version,
+	state_cluster_name,
+	state_cluster_id,
+	state_cluster_member,
+	state_cluster_member_state,
+	state_nodes,
+	state_expected_votes,
+	state_total_votes,
+	state_quorum,
+	state_active_subsystems,
+	state_nodename,
+	state_nodeid,
+	state_nodeaddrs,
+	state_done
+};
+
+struct cluster_status_info {
+	enum status_state state;
+	unsigned int total_votes;
+	unsigned int max_expected;
+	int node_addr_count;
+	struct sockaddr_in6 *saddr;
+};
 
 int sm_proc_open(struct inode *inode, struct file *file);
 int sm_debug_info(char *b, char **start, off_t offset, int length);
@@ -97,88 +124,203 @@
 
 };
 
-
-static int proc_cluster_status(char *b, char **start, off_t offset, int length)
+static void cluster_status_state_mch(struct seq_file *m,
+									 struct cluster_status_info *csi)
 {
-    struct list_head *nodelist;
-    struct cluster_node *node;
-    struct cluster_node_addr *node_addr;
-    unsigned int total_votes = 0;
-    unsigned int max_expected = 0;
-    int c = 0;
-
-    c += sprintf(b+c,
-		 "Protocol version: %d.%d.%d\n",
-		 CNXMAN_MAJOR_VERSION, CNXMAN_MINOR_VERSION,
-		 CNXMAN_PATCH_VERSION);
-
-    c += sprintf(b+c,
-		 "Config version: %d\nCluster name: %s\nCluster ID: %d\nCluster Member: %s\nMembership state: ",
-		 config_version,
-		 cluster_name, cluster_id,
-		 we_are_a_cluster_member?"Yes":"No");
-
-    membership_state(b+c, length-c);
-    c += strlen(b+c);
-    c += sprintf(b+c, "\n");
-
-    if (!we_are_a_cluster_member)
-	return c;
-
-    /* Total the votes */
-    down(&cluster_members_lock);
-    list_for_each(nodelist, &cluster_members_list) {
-	node = list_entry(nodelist, struct cluster_node, list);
-	if (node->state == NODESTATE_MEMBER) {
-	    total_votes += node->votes;
-	    max_expected =
-		max(max_expected, node->expected_votes);
+	int i;
+
+	if (!csi ||
+		(!we_are_a_cluster_member && csi->state > state_cluster_member_state))
+		return;
+
+	switch (csi->state) {
+	case state_protocol_version:
+		seq_printf(m, "Protocol version: %d.%d.%d\n",
+				   CNXMAN_MAJOR_VERSION, CNXMAN_MINOR_VERSION,
+				   CNXMAN_PATCH_VERSION);
+		break;
+
+	case state_config_version:
+		seq_printf(m, "Config version: %d\n", config_version);
+		break;
+
+	case state_cluster_name:
+		seq_printf(m,"Cluster name: %s\n", cluster_name);
+		break;
+
+	case state_cluster_id:
+		seq_printf(m, "Cluster ID: %d\n", cluster_id);
+		break;
+
+	case state_cluster_member:
+		seq_printf(m,"Cluster Member: %s\n",
+				   we_are_a_cluster_member ? "Yes" : "No");
+		break;
+
+	case state_cluster_member_state:
+	{
+		char node_state_buf[256];
+
+		membership_state(node_state_buf, sizeof(node_state_buf));
+		seq_printf(m, "Membership state: %s\n",node_state_buf);
+		break;
 	}
-    }
-    up(&cluster_members_lock);
+	case state_nodes:
+		seq_printf(m, "Nodes: %d\n", cluster_members);
+		break;
+
+	case state_expected_votes:
+		seq_printf(m, "Expected_votes: %d\n", csi->max_expected);
+		break;
+
+	case state_total_votes:
+		seq_printf(m, "Total_votes: %d\n", csi->total_votes);
+		break;
+
+	case state_quorum:
+		seq_printf(m, "Quorum: %d  %s\n", get_quorum(),
+				   cluster_is_quorate ? " " : "Activity blocked");
+		break;
+
+	case state_active_subsystems:
+		seq_printf(m, "Active subsystems: %d\n", atomic_read(&use_count));
+		break;
+
+	case state_nodename:
+		seq_printf(m, "Node name: %s\n", nodename);
+		break;
 
-    if (quorum_device && quorum_device->state == NODESTATE_MEMBER)
-	total_votes += quorum_device->votes;
+	case state_nodeid:
+		if (!us)
+			break;
+		seq_printf(m, "Node ID: %d\n", us->node_id);
+		break;
 
-    c += sprintf(b+c,
-		 "Nodes: %d\nExpected_votes: %d\nTotal_votes: %d\nQuorum: %d  %s\n",
-		 cluster_members, max_expected, total_votes,
-		 get_quorum(),
-		 cluster_is_quorate ? " " : "Activity blocked");
-    c += sprintf(b+c, "Active subsystems: %d\n",
-		 atomic_read(&use_count));
-
-    c += sprintf(b+c, "Node name: %s\n", nodename);
-
-    if (us) {
-	    c += sprintf(b+c, "Node ID: %d\n", us->node_id);
-
-	    c += sprintf(b+c, "Node addresses: ");
-	    list_for_each_entry(node_addr, &us->addr_list, list) {
-		    struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)node_addr->addr;
-		    if (saddr->sin6_family == AF_INET6) {
-			    c += sprintf(b+c, "%x:%x:%x:%x:%x:%x:%x:%x  ",
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[0]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[1]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[2]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[3]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[4]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[5]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[6]),
-					 be16_to_cpu(saddr->sin6_addr.s6_addr16[7]));
+	case state_nodeaddrs:
+		seq_printf(m, "Node addresses: ");
+		for (i = 0; i < csi->node_addr_count; i++) {
+			if (csi->saddr[i].sin6_family == AF_INET6) {
+			    seq_printf(m, "%x:%x:%x:%x:%x:%x:%x:%x  ",
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[0]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[1]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[2]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[3]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[4]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[5]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[6]),
+						   be16_to_cpu(csi->saddr[i].sin6_addr.s6_addr16[7]));
 		    }
 		    else {
-			    struct sockaddr_in *saddr4 = (struct sockaddr_in *)saddr;
+			    struct sockaddr_in *saddr4 = (struct sockaddr_in *)&csi->saddr[i];
 			    uint8_t *addr = (uint8_t *)&saddr4->sin_addr;
-			    c+= sprintf(b+c, "%u.%u.%u.%u  ",
-					addr[0], addr[1], addr[2], addr[3]);
+				seq_printf(m, "%u.%u.%u.%u  ",
+						   addr[0], addr[1], addr[2], addr[3]);
 		    }
-	    }
-	    c += sprintf(b+c, "\n\n");
-    }
-    return c;
+		}
+		seq_printf(m, "\n\n");
+		break;
+
+	case state_done:
+		break;
+
+	default:
+		break;
+	}
 }
 
+static void *cluster_status_seq_start(struct seq_file *m, loff_t * pos)
+{
+	struct cluster_status_info *csi;
+    struct list_head *nodelist;
+    struct cluster_node *node;
+    struct cluster_node_addr *node_addr;
+
+	if (!m->private) {
+		csi = kmalloc(sizeof(struct cluster_status_info), GFP_KERNEL);
+		m->private = csi;
+		if (!csi)
+			return NULL;
+		memset(csi, 0, sizeof(struct cluster_status_info));
+	}
+	else
+		csi = m->private;
+
+	csi->state = *pos;
+	if (*pos == 0) {
+		if (!we_are_a_cluster_member)
+			return csi;
+
+		/* Total the votes */
+		down(&cluster_members_lock);
+		list_for_each(nodelist, &cluster_members_list) {
+			node = list_entry(nodelist, struct cluster_node, list);
+			if (node->state == NODESTATE_MEMBER) {
+				csi->total_votes += node->votes;
+				csi->max_expected =
+					max(csi->max_expected, node->expected_votes);
+			}
+		}
+		up(&cluster_members_lock);
+		if (quorum_device && quorum_device->state == NODESTATE_MEMBER)
+			csi->total_votes += quorum_device->votes;
+
+		if (us) {
+			int i;
+
+			csi->node_addr_count = 0;
+			list_for_each_entry(node_addr, &us->addr_list, list) {
+				csi->node_addr_count++;
+			}
+			csi->saddr = kmalloc(csi->node_addr_count *
+									sizeof(struct sockaddr_in6), GFP_KERNEL);
+			if (!csi->saddr) {
+				csi->node_addr_count = 0;
+				return csi;
+			}
+			i = 0;
+			list_for_each_entry(node_addr, &us->addr_list, list) {
+				memcpy(&csi->saddr[i++],
+					   node_addr->addr, sizeof(struct sockaddr_in6));
+			}
+		}
+	}
+
+    return csi;
+}
+
+static void *cluster_status_seq_next(struct seq_file *m, void *p, loff_t * pos)
+{
+	struct cluster_status_info *csi = p;
+
+	csi->state++;
+	if (!we_are_a_cluster_member && csi->state >= state_cluster_member_state)
+		csi->state = state_done;
+	*pos = csi->state;
+	if (csi->state >= state_done)
+		return NULL;
+	return csi;
+}
+
+static int cluster_status_seq_show(struct seq_file *m, void *p)
+{
+	struct cluster_status_info *csi = p;
+
+	if (csi->state < state_done)
+		cluster_status_state_mch(m, csi);
+	return 0;
+}
+
+static void cluster_status_seq_stop(struct seq_file *m, void *p)
+{
+	struct cluster_status_info *csi = m->private;
+
+	if (m->private) {
+		if (csi->saddr)
+			kfree(csi->saddr);
+		kfree(m->private);
+		m->private = NULL;
+	}
+}
 
 /* Allocate one of these for /proc/cluster/nodes so we can keep a track of where
  * we are */
@@ -192,6 +334,11 @@
 	return seq_open(file, &cluster_info_op);
 }
 
+static int cluster_status_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &cluster_status_info_op);
+}
+
 static void *cluster_seq_start(struct seq_file *m, loff_t * pos)
 {
 	struct cluster_seq_info *csi;
@@ -290,6 +437,21 @@
 	.owner = THIS_MODULE,
 };
 
+static struct seq_operations cluster_status_info_op = {
+	.start = cluster_status_seq_start,
+	.next = cluster_status_seq_next,
+	.stop = cluster_status_seq_stop,
+	.show = cluster_status_seq_show
+};
+
+static struct file_operations cluster_status_fops = {
+	.open = cluster_status_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+	.owner = THIS_MODULE,
+};
+
 static struct file_operations service_fops = {
 	.open = sm_proc_open,
 	.read = seq_read,
@@ -351,7 +513,7 @@
 
 	procentry = create_proc_entry("cluster/status", S_IRUGO, NULL);
 	if (procentry)
-	        procentry->get_info = proc_cluster_status;
+	        procentry->proc_fops = &cluster_status_fops ;
 
 	procentry = create_proc_entry("cluster/services", S_IRUGO, NULL);
 	if (procentry)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]