From mboxrd@z Thu Jan 1 00:00:00 1970 From: rpeterso@sourceware.org Date: 7 Nov 2006 17:47:51 -0000 Subject: [Cluster-devel] cluster/cman-kernel/src proc.c Message-ID: <20061107174751.17883.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Branch: RHEL4 Changes by: rpeterso at 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)