cluster: RHEL58 - GFS: add ability to turn off inode pre-fetch on readdir
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 6689362008847088660603c7a041968fb33b50be
Parent: 1a810eac13bb49f85e0e3c5a17e05d06ba6a5037
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 14 15:03:10 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Sep 14 15:08:15 2011 -0500
GFS: add ability to turn off inode pre-fetch on readdir
This patch adds a new GFS mount option "noprefetch" which turns off
inode pre-fetch when doing readdir. This option changes the performance
characteristics and lets some use cases run much faster.
rhbz#732129
---
gfs-kernel/src/gfs/incore.h | 1 +
gfs-kernel/src/gfs/mount.c | 6 ++++++
gfs-kernel/src/gfs/ops_file.c | 3 +++
gfs-kernel/src/gfs/ops_inode.c | 6 ++++--
gfs-kernel/src/gfs/ops_super.c | 3 +++
5 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/gfs-kernel/src/gfs/incore.h b/gfs-kernel/src/gfs/incore.h
index 67f7e10..af53aef 100644
--- a/gfs-kernel/src/gfs/incore.h
+++ b/gfs-kernel/src/gfs/incore.h
@@ -867,6 +867,7 @@ struct gfs_args {
int ar_suiddir; /* suiddir support */
int ar_noquota; /* Turn off quota support */
int ar_noatime; /* Turn off atime updates */
+ int ar_noprefetch; /* Turn on/off inode pre-fetch from readdir */
};
struct gfs_tune {
diff --git a/gfs-kernel/src/gfs/mount.c b/gfs-kernel/src/gfs/mount.c
index 741667a..4a16486 100644
--- a/gfs-kernel/src/gfs/mount.c
+++ b/gfs-kernel/src/gfs/mount.c
@@ -162,6 +162,12 @@ gfs_make_args(char *data_arg, struct gfs_args *args, int remount)
else if (!strcmp(x, "noacl"))
args->ar_posix_acls = FALSE;
+ else if (!strcmp(x, "noprefetch"))
+ args->ar_noprefetch = TRUE;
+
+ else if (!strcmp(x, "prefetch"))
+ args->ar_noprefetch = FALSE;
+
else if (!strcmp(x, "suiddir"))
args->ar_suiddir = TRUE;
diff --git a/gfs-kernel/src/gfs/ops_file.c b/gfs-kernel/src/gfs/ops_file.c
index 03fcc73..aa2ed3b 100644
--- a/gfs-kernel/src/gfs/ops_file.c
+++ b/gfs-kernel/src/gfs/ops_file.c
@@ -1175,7 +1175,10 @@ high_stat_rate(struct gfs_inode *ip)
struct timeval now, diff;
unsigned long milli = 0;
unsigned int rate = 0; /* stats per second in this dir */
+ struct gfs_sbd *sdp = ip->i_sbd;
+ if (sdp->sd_args.ar_noprefetch)
+ return 1;
do_gettimeofday(&now);
diff.tv_sec = now.tv_sec - ip->i_dir_stat_st.tv_sec;
diff.tv_usec = now.tv_usec - ip->i_dir_stat_st.tv_usec;
diff --git a/gfs-kernel/src/gfs/ops_inode.c b/gfs-kernel/src/gfs/ops_inode.c
index ae836dc..7607926 100644
--- a/gfs-kernel/src/gfs/ops_inode.c
+++ b/gfs-kernel/src/gfs/ops_inode.c
@@ -1511,6 +1511,7 @@ gfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
struct inode *inode = dentry->d_inode, *p_inode = NULL;
struct gfs_inode *ip = get_v2ip(inode), *pi = NULL;
struct gfs_holder gh;
+ struct gfs_sbd *sdp = ip->i_sbd;
int error;
atomic_inc(&ip->i_sbd->sd_ops_inode);
@@ -1518,8 +1519,9 @@ gfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
error = gfs_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
if (!error) {
generic_fillattr(inode, stat);
- if (S_ISREG(inode->i_mode) && dentry->d_parent
- && dentry->d_parent->d_inode) {
+ if (!sdp->sd_args.ar_noprefetch &&
+ S_ISREG(inode->i_mode) && dentry->d_parent &&
+ dentry->d_parent->d_inode) {
p_inode = igrab(dentry->d_parent->d_inode);
if (p_inode) {
pi = get_v2ip(p_inode);
diff --git a/gfs-kernel/src/gfs/ops_super.c b/gfs-kernel/src/gfs/ops_super.c
index 1838e5d..1fa7faf 100644
--- a/gfs-kernel/src/gfs/ops_super.c
+++ b/gfs-kernel/src/gfs/ops_super.c
@@ -330,6 +330,7 @@ gfs_remount_fs(struct super_block *sb, int *flags, char *data)
sdp->sd_args.ar_posix_acls = FALSE;
sb->s_flags &= ~MS_POSIXACL;
}
+ sdp->sd_args.ar_noprefetch = args->ar_noprefetch;
if (*flags & (MS_NOATIME | MS_NODIRATIME))
set_bit(SDF_NOATIME, &sdp->sd_flags);
@@ -453,6 +454,8 @@ gfs_show_options(struct seq_file *s, struct vfsmount *mnt)
seq_printf(s, ",noquota");
if (args->ar_suiddir)
seq_printf(s, ",suiddir");
+ if (args->ar_noprefetch)
+ seq_printf(s, ",noprefetch");
if (args->ar_errors) {
seq_printf(s, ",errors=");
if (args->ar_errors == GFS_ERRORS_PANIC)
12 years, 7 months
cluster: RHEL58 - cman: improve cman/qdisk interactions
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 1a810eac13bb49f85e0e3c5a17e05d06ba6a5037
Parent: 0b79766fc2af6b7815a7a3620027f48550728ea8
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Wed Sep 7 14:26:06 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Tue Sep 13 13:58:27 2011 +0200
cman: improve cman/qdisk interactions
- libcman/cman: add new quorum API call to update name and votes of a quorum device
- cman: simplify common code to free quorum_device infrastructure
- cman: do better logging/error reports of the quorum API usage
- cman: use strdup instead of malloc+strcpy (code is more readable)
- libcman: perform better error checking in register_quorum_device/update_quorum_device
- Allow qdisk to update device name in cman using a new libcman quorum API call
- Perform slight better error checking of some update opertaions
Resolves: rhbz#704243
(this backport of commit c79c32e88e from RHEL6 branch)
Acked-by: Lon Hohberger <lhh(a)redhat.com>
Acked-by: Christine Caulfield <ccaulfie(a)redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/daemon/cnxman-socket.h | 1 +
cman/daemon/commands.c | 86 ++++++++++++++++++++++++++++++++++++-------
cman/lib/libcman.c | 18 +++++++-
cman/lib/libcman.h | 4 ++
cman/qdisk/main.c | 35 ++++++++++-------
5 files changed, 113 insertions(+), 31 deletions(-)
diff --git a/cman/daemon/cnxman-socket.h b/cman/daemon/cnxman-socket.h
index cc1de6a..351c97c 100644
--- a/cman/daemon/cnxman-socket.h
+++ b/cman/daemon/cnxman-socket.h
@@ -45,6 +45,7 @@
#define CMAN_CMD_REG_QUORUMDEV 0x800000b5
#define CMAN_CMD_UNREG_QUORUMDEV 0x800000b6
#define CMAN_CMD_POLL_QUORUMDEV 0x800000b7
+#define CMAN_CMD_UPDATE_QUORUMDEV 0x800000b8
#define CMAN_CMD_TRY_SHUTDOWN 0x800000bb
#define CMAN_CMD_SHUTDOWN_REPLY 0x000000bc
#define CMAN_CMD_UPDATE_FENCE_INFO 0x800000bd
diff --git a/cman/daemon/commands.c b/cman/daemon/commands.c
index 6e0160b..ddc85ec 100644
--- a/cman/daemon/commands.c
+++ b/cman/daemon/commands.c
@@ -971,44 +971,69 @@ static int do_cmd_try_shutdown(struct connection *con, char *cmdbuf)
}
}
+static void free_quorum_device(void)
+{
+ if (!quorum_device)
+ return;
+
+ if (quorum_device->name)
+ free(quorum_device->name);
+
+ free(quorum_device);
+
+ quorum_device = NULL;
+}
+
static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
{
int votes;
char *name = cmdbuf+sizeof(int);
- if (!ais_running)
+ if (!ais_running) {
+ log_msg(LOG_ERR, "unable to register quorum device: aisexec is not running\n");
return -ENOTCONN;
+ }
- if (!we_are_a_cluster_member)
+ if (!we_are_a_cluster_member) {
+ log_msg(LOG_ERR, "unable to register quorum device: this node is not part of a cluster\n");
return -ENOENT;
+ }
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) {
+ log_msg(LOG_ERR, "unable to register quorum device: name is too long\n");
return -EINVAL;
+ }
/* Allow re-registering of a quorum device if the name is the same */
- if (quorum_device && strcmp(name, quorum_device->name))
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ log_msg(LOG_ERR, "unable to re-register quorum device: device names do not match\n");
+ log_msg(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
return -EBUSY;
+ }
- if (find_node_by_name(name))
+ if (find_node_by_name(name)) {
+ log_msg(LOG_ERR, "unable to register quorum device: a node with the same name (%s) already exists\n", name);
return -EALREADY;
+ }
memcpy(&votes, cmdbuf, sizeof(int));
if (!quorum_device)
{
quorum_device = malloc(sizeof(struct cluster_node));
- if (!quorum_device)
+ if (!quorum_device) {
+ log_msg(LOG_ERR, "unable to register quorum device: not enough memory\n");
return -ENOMEM;
+ }
memset(quorum_device, 0, sizeof(struct cluster_node));
- quorum_device->name = malloc(strlen(name) + 1);
+ quorum_device->name = strdup(name);
if (!quorum_device->name) {
- free(quorum_device);
- quorum_device = NULL;
+ log_msg(LOG_ERR, "unable to register quorum device: not enough memory\n");
+ free_quorum_device();
return -ENOMEM;
}
- strcpy(quorum_device->name, name);
quorum_device->state = NODESTATE_DEAD;
gettimeofday(&quorum_device->join_time, NULL);
@@ -1034,15 +1059,44 @@ static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
if (quorum_device->state == NODESTATE_MEMBER)
return -EBUSY;
- free(quorum_device->name);
- free(quorum_device);
-
- quorum_device = NULL;
+ free_quorum_device();
log_msg(LOG_INFO, "quorum device unregistered\n");
return 0;
}
+static int do_cmd_update_quorum_device(char *cmdbuf, int *retlen)
+{
+ int votes, ret = 0;
+ char *name = cmdbuf+sizeof(int);
+
+ if (!quorum_device)
+ return -EINVAL;
+
+ memcpy(&votes, cmdbuf, sizeof(int));
+
+ /* allow name change of the quorum device */
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ char *newname = NULL;
+ char *oldname = NULL;
+
+ newname = strdup(name);
+ if (!newname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ oldname = quorum_device->name;
+ quorum_device->name = newname;
+ free(oldname);
+ }
+
+out:
+ quorum_device->votes = votes;
+
+ return ret;
+}
+
static void ccsd_timer_fn(void *arg)
{
int ccs_err;
@@ -1354,6 +1408,10 @@ int process_command(struct connection *con, int cmd, char *cmdbuf,
err = do_cmd_unregister_quorum_device(cmdbuf, retlen);
break;
+ case CMAN_CMD_UPDATE_QUORUMDEV:
+ err = do_cmd_update_quorum_device(cmdbuf, retlen);
+ break;
+
case CMAN_CMD_POLL_QUORUMDEV:
err = do_cmd_poll_quorum_device(cmdbuf, retlen);
break;
diff --git a/cman/lib/libcman.c b/cman/lib/libcman.c
index 3ce6de4..a4f73d3 100644
--- a/cman/lib/libcman.c
+++ b/cman/lib/libcman.c
@@ -1008,13 +1008,15 @@ int cman_replyto_shutdown(cman_handle_t handle, int yesno)
}
-int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+static int cman_set_quorum_device(cman_handle_t handle,
+ int ops,
+ char *name, int votes)
{
struct cman_handle *h = (struct cman_handle *)handle;
char buf[strlen(name)+1 + sizeof(int)];
VALIDATE_HANDLE(h);
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if ((!name) || (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) || (votes < 0))
{
errno = EINVAL;
return -1;
@@ -1022,7 +1024,12 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
memcpy(buf, &votes, sizeof(int));
strcpy(buf+sizeof(int), name);
- return info_call(h, CMAN_CMD_REG_QUORUMDEV, buf, strlen(name)+1+sizeof(int), NULL, 0);
+ return info_call(h, ops, buf, strlen(name)+1+sizeof(int), NULL, 0);
+}
+
+int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_REG_QUORUMDEV, name, votes);
}
int cman_unregister_quorum_device(cman_handle_t handle)
@@ -1058,6 +1065,11 @@ int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info)
return ret;
}
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_UPDATE_QUORUMDEV, name, votes);
+}
+
int cman_get_fenceinfo(cman_handle_t handle, int nodeid, uint64_t *time, int *fenced, char *agent)
{
struct cman_handle *h = (struct cman_handle *)handle;
diff --git a/cman/lib/libcman.h b/cman/lib/libcman.h
index 857ba33..3069038 100644
--- a/cman/lib/libcman.h
+++ b/cman/lib/libcman.h
@@ -391,10 +391,14 @@ int cman_barrier_delete(cman_handle_t handle, const char *name);
* After creating a quorum device you will need to call 'poll_quorum_device'
* at least once every (default) 10 seconds (this can be changed in CCS)
* otherwise it will time-out and the cluster will lose its vote.
+ *
+ * register_quorum and update_quorum arguments are mandatory.
+ * name has to be a valid null-terminated string and votes >= 0.
*/
int cman_register_quorum_device(cman_handle_t handle, char *name, int votes);
int cman_unregister_quorum_device(cman_handle_t handle);
int cman_poll_quorum_device(cman_handle_t handle, int isavailable);
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes);
/*
* Sets the dirty bit inside cman. This indicates that the node has
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index 153b190..0d7bb3d 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -1670,24 +1670,31 @@ main(int argc, char **argv)
if (!_running)
goto out;
-
- cman_register_quorum_device(ctx.qc_ch,
+
+ if ((rv = cman_register_quorum_device(ctx.qc_ch,
(ctx.qc_flags&RF_CMAN_LABEL)?
ctx.qc_cman_label:
ctx.qc_device,
- ctx.qc_votes);
- /*
- XXX this always returns -1 / EBUSY even when it works?!!!
-
- if ((rv = cman_register_quorum_device(ctx.qc_ch, ctx.qc_device,
- ctx.qc_votes)) < 0) {
- clulog_and_print(LOG_CRIT,
- "Could not register %s with CMAN; "
- "return = %d; error = %s\n",
- ctx.qc_device, rv, strerror(errno));
- goto out;
+ ctx.qc_votes)) < 0) {
+ if (errno == EBUSY) {
+ if ((rv = cman_update_quorum_device(ctx.qc_ch,
+ (ctx.qc_flags&RF_CMAN_LABEL)?
+ ctx.qc_cman_label:
+ ctx.qc_device,
+ ctx.qc_votes)) < 0) {
+ clulog_and_print(LOG_CRIT,
+ "Could not update %s with CMAN; "
+ "return = %d; error = %s\n",
+ ctx.qc_device, rv, strerror(errno));
+ }
+ } else {
+ clulog_and_print(LOG_CRIT,
+ "Could not register %s with CMAN; "
+ "return = %d; error = %s\n",
+ ctx.qc_device, rv, strerror(errno));
+ goto out;
+ }
}
- */
io_nanny_start(ctx.qc_tko * ctx.qc_interval);
12 years, 7 months
cluster: RHEL6 - cman: improve cman/qdisk interactions
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: c79c32e88eb21219298bde15fb3e537cfb76f002
Parent: 9a3280e078bd9b9b4997b087eab4748ca79d4182
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Wed Sep 7 14:26:06 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Thu Sep 8 16:28:13 2011 +0200
cman: improve cman/qdisk interactions
- libcman/cman: add new quorum API call to update name and votes of a quorum device
- cman: simplify common code to free quorum_device infrastructure and handle quorum recalculation
- cman: do better logging/error reports of the quorum API usage
- cman: use strdup instead of malloc+strcpy (code is more readable)
- libcman: perform better error checking in register_quorum_device/update_quorum_device
- Allow qdisk to update device name in cman using a new libcman quorum API call
- Perform slight better error checking of some update opertaions
Resolves: rhbz#735917
Acked-by: Lon Hohberger <lhh(a)redhat.com>
Acked-by: Christine Caulfield <ccaulfie(a)redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/daemon/cnxman-socket.h | 1 +
cman/daemon/commands.c | 135 +++++++++++++++++++++++++++++++++----------
cman/lib/libcman.c | 19 +++++-
cman/lib/libcman.h | 4 +
cman/qdisk/main.c | 28 ++++++++-
5 files changed, 150 insertions(+), 37 deletions(-)
diff --git a/cman/daemon/cnxman-socket.h b/cman/daemon/cnxman-socket.h
index e8b7378..d243b40 100644
--- a/cman/daemon/cnxman-socket.h
+++ b/cman/daemon/cnxman-socket.h
@@ -32,6 +32,7 @@
#define CMAN_CMD_REG_QUORUMDEV 0x800000b5
#define CMAN_CMD_UNREG_QUORUMDEV 0x800000b6
#define CMAN_CMD_POLL_QUORUMDEV 0x800000b7
+#define CMAN_CMD_UPDATE_QUORUMDEV 0x800000b8
#define CMAN_CMD_TRY_SHUTDOWN 0x800000bb
#define CMAN_CMD_SHUTDOWN_REPLY 0x000000bc
#define CMAN_CMD_UPDATE_FENCE_INFO 0x800000bd
diff --git a/cman/daemon/commands.c b/cman/daemon/commands.c
index d4d9fd9..98dee3b 100644
--- a/cman/daemon/commands.c
+++ b/cman/daemon/commands.c
@@ -1080,27 +1080,66 @@ static int do_cmd_try_shutdown(struct connection *con, char *cmdbuf)
return 0;
}
+static void free_quorum_device(void)
+{
+ if (!quorum_device)
+ return;
+
+ if (quorum_device->name)
+ free(quorum_device->name);
+
+ free(quorum_device);
+
+ quorum_device = NULL;
+}
+
+static void quorum_device_update_votes(int votes)
+{
+ int oldvotes;
+
+ /* Update votes even if it existed before */
+ oldvotes = quorum_device->votes;
+ quorum_device->votes = votes;
+
+ /* If it is a member and votes changed, recalculate quorum */
+ if (quorum_device->state == NODESTATE_MEMBER &&
+ oldvotes != votes) {
+ recalculate_quorum(1, 0);
+ }
+}
+
static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
{
int votes;
- int oldvotes;
char *name = cmdbuf+sizeof(int);
- if (!ais_running)
+ if (!ais_running) {
+ log_printf(LOG_ERR, "unable to register quorum device: corosync is not running\n");
return -ENOTCONN;
+ }
- if (!we_are_a_cluster_member)
+ if (!we_are_a_cluster_member) {
+ log_printf(LOG_ERR, "unable to register quorum device: this node is not part of a cluster\n");
return -ENOENT;
+ }
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) {
+ log_printf(LOG_ERR, "unable to register quorum device: name is too long\n");
+ /* this should probably return -E2BIG? */
return -EINVAL;
+ }
/* Allow re-registering of a quorum device if the name is the same */
- if (quorum_device && strcmp(name, quorum_device->name))
- return -EBUSY;
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ log_printf(LOG_ERR, "unable to re-register quorum device: device names do not match\n");
+ log_printf(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
+ return -EBUSY;
+ }
- if (find_node_by_name(name))
- return -EALREADY;
+ if (find_node_by_name(name)) {
+ log_printf(LOG_ERR, "unable to register quorum device: a node with the same name (%s) already exists\n", name);
+ return -EALREADY;
+ }
memcpy(&votes, cmdbuf, sizeof(int));
@@ -1108,18 +1147,19 @@ static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
if (!quorum_device)
{
quorum_device = malloc(sizeof(struct cluster_node));
- if (!quorum_device)
+ if (!quorum_device) {
+ log_printf(LOG_ERR, "unable to register quorum device: not enough memory\n");
return -ENOMEM;
+ }
memset(quorum_device, 0, sizeof(struct cluster_node));
- quorum_device->name = malloc(strlen(name) + 1);
+ quorum_device->name = strdup(name);
if (!quorum_device->name) {
- free(quorum_device);
- quorum_device = NULL;
+ log_printf(LOG_ERR, "unable to register quorum device: not enough memory\n");
+ free_quorum_device();
return -ENOMEM;
}
- strcpy(quorum_device->name, name);
quorum_device->state = NODESTATE_DEAD;
gettimeofday(&quorum_device->join_time, NULL);
@@ -1132,34 +1172,63 @@ static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
log_printf(LOG_INFO, "quorum device re-registered\n");
}
- /* Update votes even if it existed before */
- oldvotes = quorum_device->votes;
- quorum_device->votes = votes;
+ quorum_device_update_votes(votes);
- /* If it is a member and votes decreased, recalculate quorum */
- if (quorum_device->state == NODESTATE_MEMBER &&
- oldvotes != votes) {
- recalculate_quorum(1, 0);
+ return 0;
+}
+
+static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
+{
+ if (!quorum_device) {
+ log_printf(LOG_DEBUG, "memb: failed to unregister a non existing quorum device\n");
+ return -EINVAL;
+ }
+
+ if (quorum_device->state == NODESTATE_MEMBER) {
+ log_printf(LOG_DEBUG, "memb: failed to unregister: quorum device still active.\n");
+ return -EBUSY;
}
- return 0;
+ free_quorum_device();
+
+ log_printf(LOG_INFO, "quorum device unregistered\n");
+ return 0;
}
-static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
+static int do_cmd_update_quorum_device(char *cmdbuf, int *retlen)
{
- if (!quorum_device)
- return -EINVAL;
+ int votes, ret = 0;
+ char *name = cmdbuf+sizeof(int);
- if (quorum_device->state == NODESTATE_MEMBER)
- return -EBUSY;
+ if (!quorum_device) {
+ log_printf(LOG_DEBUG, "memb: failed to update a non-existing quorum device\n");
+ return -EINVAL;
+ }
- free(quorum_device->name);
- free(quorum_device);
+ memcpy(&votes, cmdbuf, sizeof(int));
- quorum_device = NULL;
+ /* allow name change of the quorum device */
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ char *newname = NULL;
+ char *oldname = NULL;
- log_printf(LOG_INFO, "quorum device unregistered\n");
- return 0;
+ log_printf(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
+ newname = strdup(name);
+ if (!newname) {
+ log_printf(LOG_ERR, "memb: unable to update quorum device name: out of memory\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+ log_printf(LOG_INFO, "quorum device name changed to %s\n", name);
+ oldname = quorum_device->name;
+ quorum_device->name = newname;
+ free(oldname);
+ }
+
+out:
+ quorum_device_update_votes(votes);
+
+ return ret;
}
static int reload_config(int new_version, int should_broadcast)
@@ -1560,6 +1629,10 @@ int process_command(struct connection *con, int cmd, char *cmdbuf,
err = do_cmd_unregister_quorum_device(cmdbuf, retlen);
break;
+ case CMAN_CMD_UPDATE_QUORUMDEV:
+ err = do_cmd_update_quorum_device(cmdbuf, retlen);
+ break;
+
case CMAN_CMD_POLL_QUORUMDEV:
err = do_cmd_poll_quorum_device(cmdbuf, retlen);
break;
diff --git a/cman/lib/libcman.c b/cman/lib/libcman.c
index daaad07..a89c731 100644
--- a/cman/lib/libcman.c
+++ b/cman/lib/libcman.c
@@ -1002,14 +1002,15 @@ int cman_replyto_shutdown(cman_handle_t handle, int yesno)
return 0;
}
-
-int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+static int cman_set_quorum_device(cman_handle_t handle,
+ int ops,
+ char *name, int votes)
{
struct cman_handle *h = (struct cman_handle *)handle;
char buf[strlen(name)+1 + sizeof(int)];
VALIDATE_HANDLE(h);
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if ((!name) || (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) || (votes < 0))
{
errno = EINVAL;
return -1;
@@ -1017,7 +1018,12 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
memcpy(buf, &votes, sizeof(int));
strcpy(buf+sizeof(int), name);
- return info_call(h, CMAN_CMD_REG_QUORUMDEV, buf, strlen(name)+1+sizeof(int), NULL, 0);
+ return info_call(h, ops, buf, strlen(name)+1+sizeof(int), NULL, 0);
+}
+
+int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_REG_QUORUMDEV, name, votes);
}
int cman_unregister_quorum_device(cman_handle_t handle)
@@ -1053,6 +1059,11 @@ int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info)
return ret;
}
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_UPDATE_QUORUMDEV, name, votes);
+}
+
int cman_get_fenceinfo(cman_handle_t handle, int nodeid, uint64_t *time, int *fenced, char *agent)
{
struct cman_handle *h = (struct cman_handle *)handle;
diff --git a/cman/lib/libcman.h b/cman/lib/libcman.h
index feb10a2..9f97875 100644
--- a/cman/lib/libcman.h
+++ b/cman/lib/libcman.h
@@ -420,6 +420,9 @@ int cman_barrier_delete(cman_handle_t handle, const char *name);
/*
* Add your own quorum device here, needs an admin socket
*
+ * register_quorum and update_quorum arguments are mandatory.
+ * name has to be a valid null-terminated string and votes >= 0.
+ *
* After creating a quorum device you will need to call 'poll_quorum_device'
* at least once every (default) 10 seconds (this can be changed in CCS)
* otherwise it will time-out and the cluster will lose its vote.
@@ -428,6 +431,7 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes);
int cman_unregister_quorum_device(cman_handle_t handle);
int cman_poll_quorum_device(cman_handle_t handle, int isavailable);
int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info);
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes);
/*
* Sets the dirty bit inside cman. This indicates that the node has
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index 9262af2..a90e82c 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -690,6 +690,17 @@ register_device(qd_ctx *ctx)
ctx->qc_votes : 0);
}
+static int
+update_device(qd_ctx *ctx)
+{
+ return cman_update_quorum_device(
+ ctx->qc_cman_admin,
+ (ctx->qc_flags&RF_CMAN_LABEL) ?
+ ctx->qc_cman_label : ctx->qc_device,
+ (!(ctx->qc_flags & RF_MASTER_WINS) ||
+ ctx->qc_status == S_MASTER) ?
+ ctx->qc_votes : 0);
+}
static int
adjust_votes(qd_ctx *ctx)
@@ -2080,9 +2091,22 @@ main(int argc, char **argv)
if (!_running)
goto out;
-
+
/* This registers the quorum device */
- register_device(&ctx);
+ ret = register_device(&ctx);
+ if (ret) {
+ if (errno == EBUSY) {
+ logt_print(LOG_NOTICE, "quorum device is already registered, updating\n");
+ ret = update_device(&ctx);
+ if (ret) {
+ logt_print(LOG_ERR, "Unable to update quorum device info!\n");
+ goto out;
+ }
+ } else {
+ logt_print(LOG_ERR, "Unable to register quorum device!\n");
+ goto out;
+ }
+ }
io_nanny_start(ctx.qc_tko * ctx.qc_interval);
12 years, 7 months
cluster: RHEL6 - rgmanager: Fix segfault caused by unref race
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 9a3280e078bd9b9b4997b087eab4748ca79d4182
Parent: 4dbb6e5cca30acbcb8fb9d715c6008c8868c5fa7
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Wed Sep 7 11:09:10 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Thu Sep 8 10:16:33 2011 -0400
rgmanager: Fix segfault caused by unref race
Since we only ever open/close the connection in one
place, there is no need to call ref/unref in the
separate thread, since we wait for that thread to exit
before calling DBus *close() and *unref() functions.
It is possible for notification(s) to be sent during
shutdown after shutting down the DBus connection.
Since notifications are best-effort and having the
DBus thread shut down is a normal condition, we should
not log errors when this condition occurs.
The rgm_dbus_notify() function was not locking around
checks to the private db variable, which was incorrect.
Resolves: rhbz#697446
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
Tested-by: Lon Hohberger <lhh(a)redhat.com>
Reviewed-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
rgmanager/src/daemons/update-dbus.c | 16 +++++++++++-----
1 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/rgmanager/src/daemons/update-dbus.c b/rgmanager/src/daemons/update-dbus.c
index bff1644..b45113c 100644
--- a/rgmanager/src/daemons/update-dbus.c
+++ b/rgmanager/src/daemons/update-dbus.c
@@ -127,13 +127,11 @@ static void *
_dbus_auto_flush(void *arg)
{
/* DBus connection functions are thread safe */
- dbus_connection_ref(db);
while (dbus_connection_read_write(db, 500)) {
if (!th)
break;
}
- dbus_connection_unref(db);
th = 0;
return NULL;
}
@@ -147,7 +145,7 @@ _rgm_dbus_notify(const char *svcname,
const char *svclast)
{
DBusMessage *msg = NULL;
- int ret = -1;
+ int ret = 0;
pthread_mutex_lock(&mu);
@@ -155,6 +153,9 @@ _rgm_dbus_notify(const char *svcname,
goto out_unlock;
}
+ /* Notifications are enabled */
+ ret = -1;
+
/* Check to ensure the connection is still valid. If it
* isn't, clean up and shut down the dbus connection.
*
@@ -215,12 +216,17 @@ rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
if (!rgm_dbus_notify)
goto out_free;
- if (!db)
- goto out_free;
if (view == 1)
goto out_free;
if (size != (sizeof(*st)))
goto out_free;
+
+ pthread_mutex_lock(&mu);
+ if (!db) {
+ pthread_mutex_unlock(&mu);
+ goto out_free;
+ }
+ pthread_mutex_unlock(&mu);
st = (rg_state_t *)data;
swab_rg_state_t(st);
12 years, 7 months
cluster: RHEL6 - cman: default to 2 different mcast addresses in RRP mode and set rrp_problem_count_threshold
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 4dbb6e5cca30acbcb8fb9d715c6008c8868c5fa7
Parent: 3a113c9b3b60f2a18a3b653b83edac5c89074af7
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Thu Sep 8 11:40:17 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Thu Sep 8 14:44:57 2011 +0200
cman: default to 2 different mcast addresses in RRP mode and set rrp_problem_count_threshold
Resolves: rhbz#735912
Acked-by: Jan Friesse <jfriesse(a)redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/daemon/cman-preconfig.c | 16 ++++++++++++----
config/tools/xml/cluster.rng.in.head | 9 ++++++++-
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/cman/daemon/cman-preconfig.c b/cman/daemon/cman-preconfig.c
index 16d89e5..7d60226 100644
--- a/cman/daemon/cman-preconfig.c
+++ b/cman/daemon/cman-preconfig.c
@@ -408,13 +408,14 @@ static uint16_t generate_cluster_id(char *name)
return value & 0xFFFF;
}
-static char *default_mcast(char *node, uint16_t clusterid)
+static char *default_mcast(char *node, int altiface)
{
struct addrinfo *ainfo;
struct addrinfo ahints;
int ret;
int family;
static char addr[132];
+ uint16_t clusterid = cluster_id + altiface;
memset(&ahints, 0, sizeof(ahints));
@@ -709,7 +710,7 @@ static int get_nodename(struct objdb_iface_ver0 *objdb)
}
if (!mcast_name) {
- mcast_name = default_mcast(nodename, cluster_id);
+ mcast_name = default_mcast(nodename, PRIMARY_IFACE);
}
if (!mcast_name)
@@ -793,7 +794,7 @@ static int get_nodename(struct objdb_iface_ver0 *objdb)
objdb_get_int(objdb, alt_object, "ttl", &altttl, ttl);
if (objdb_get_string(objdb, alt_object, "mcast", &mcast)) {
- mcast = mcast_name;
+ mcast = default_mcast(nodename, ALT_IFACE);
}
if (add_ifaddr(objdb, mcast, node, portnum, altttl,
@@ -1007,6 +1008,13 @@ static void add_cman_overrides(struct objdb_iface_ver0 *objdb)
}
}
+ if (objdb_get_string(objdb, object_handle, "rrp_problem_count_threshold", &value)) {
+ if (num_interfaces > 1) {
+ objdb->object_key_create_typed(object_handle, "rrp_problem_count_threshold",
+ "3", 2, OBJDB_VALUETYPE_STRING);
+ }
+ }
+
if (objdb_get_string(objdb, object_handle, "secauth", &value)) {
sprintf(tmp, "%d", 1);
objdb->object_key_create_typed(object_handle, "secauth",
@@ -1152,7 +1160,7 @@ static int set_noccs_defaults(struct objdb_iface_ver0 *objdb)
num_nodenames = 1;
if (!mcast_name) {
- mcast_name = default_mcast(nodename, cluster_id);
+ mcast_name = default_mcast(nodename, PRIMARY_IFACE);
}
/* This will increase as nodes join the cluster */
diff --git a/config/tools/xml/cluster.rng.in.head b/config/tools/xml/cluster.rng.in.head
index 1afa9e8..e6e4633 100644
--- a/config/tools/xml/cluster.rng.in.head
+++ b/config/tools/xml/cluster.rng.in.head
@@ -257,7 +257,7 @@ To validate your cluster.conf against this schema, run:
rha:sample="5"/>
</optional>
<!-- FIXME: The following description was adapted from the man page.
- It may be tool long for the schema docuement. Consider cutting text
+ It may be tool long for the schema document. Consider cutting text
after the second sentence and referring the reader to the openais.conf
man page. -->
<optional>
@@ -275,6 +275,13 @@ To validate your cluster.conf against this schema, run:
chosen." rha:sample="active"/>
</optional>
<optional>
+ <attribute name="rrp_problem_count_threshold"
+ rha:description="This specifies the number of times a problem is detected
+ with a link before setting the link faulty. Once a link is set faulty, no
+ more data is transmitted upon it. Corosync default is 10, cman default is 3"
+ rha:default="3" rha:sample="5"/>
+ </optional>
+ <optional>
<attribute name="secauth" rha:description="This attribute specifies
that HMAC/SHA1 authentication should be used to authenticate all
messages. It further specifies that all data should be encrypted
12 years, 7 months
cluster: STABLE31 - cman: default to 2 different mcast addresses in RRP mode and set rrp_problem_count_threshold
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 2ead34f00923c3ff4049e3f6f13c1b8811b38c01
Parent: 65f694d6c69b37fd57da251a39e2fb491cd97e28
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Thu Sep 8 11:40:17 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Thu Sep 8 11:40:17 2011 +0200
cman: default to 2 different mcast addresses in RRP mode and set rrp_problem_count_threshold
Resolves: rhbz#735912
Acked-by: Jan Friesse <jfriesse(a)redhat.com>
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/daemon/cman-preconfig.c | 16 ++++++++++++----
config/tools/xml/cluster.rng.in.head | 9 ++++++++-
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/cman/daemon/cman-preconfig.c b/cman/daemon/cman-preconfig.c
index 64f505f..d5e7a92 100644
--- a/cman/daemon/cman-preconfig.c
+++ b/cman/daemon/cman-preconfig.c
@@ -393,13 +393,14 @@ static uint16_t generate_cluster_id(char *name)
return value & 0xFFFF;
}
-static char *default_mcast(char *node, uint16_t clusterid)
+static char *default_mcast(char *node, int altiface)
{
struct addrinfo *ainfo;
struct addrinfo ahints;
int ret;
int family;
static char addr[132];
+ uint16_t clusterid = cluster_id + altiface;
memset(&ahints, 0, sizeof(ahints));
@@ -691,7 +692,7 @@ static int get_nodename(struct objdb_iface_ver0 *objdb)
}
if (!mcast_name) {
- mcast_name = default_mcast(nodename, cluster_id);
+ mcast_name = default_mcast(nodename, PRIMARY_IFACE);
}
if (!mcast_name)
@@ -778,7 +779,7 @@ static int get_nodename(struct objdb_iface_ver0 *objdb)
objdb_get_int(objdb, alt_object, "ttl", &altttl, ttl);
if (objdb_get_string(objdb, alt_object, "mcast", &mcast)) {
- mcast = mcast_name;
+ mcast = default_mcast(nodename, ALT_IFACE);
}
if (add_ifaddr(objdb, mcast, node, portnum, altttl,
@@ -992,6 +993,13 @@ static void add_cman_overrides(struct objdb_iface_ver0 *objdb)
}
}
+ if (objdb_get_string(objdb, object_handle, "rrp_problem_count_threshold", &value)) {
+ if (num_interfaces > 1) {
+ objdb->object_key_create_typed(object_handle, "rrp_problem_count_threshold",
+ "3", 2, OBJDB_VALUETYPE_STRING);
+ }
+ }
+
if (objdb_get_string(objdb, object_handle, "secauth", &value)) {
sprintf(tmp, "%d", 1);
objdb->object_key_create_typed(object_handle, "secauth",
@@ -1136,7 +1144,7 @@ static int set_noccs_defaults(struct objdb_iface_ver0 *objdb)
num_nodenames = 1;
if (!mcast_name) {
- mcast_name = default_mcast(nodename, cluster_id);
+ mcast_name = default_mcast(nodename, PRIMARY_IFACE);
}
/* This will increase as nodes join the cluster */
diff --git a/config/tools/xml/cluster.rng.in.head b/config/tools/xml/cluster.rng.in.head
index 1afa9e8..e6e4633 100644
--- a/config/tools/xml/cluster.rng.in.head
+++ b/config/tools/xml/cluster.rng.in.head
@@ -257,7 +257,7 @@ To validate your cluster.conf against this schema, run:
rha:sample="5"/>
</optional>
<!-- FIXME: The following description was adapted from the man page.
- It may be tool long for the schema docuement. Consider cutting text
+ It may be tool long for the schema document. Consider cutting text
after the second sentence and referring the reader to the openais.conf
man page. -->
<optional>
@@ -275,6 +275,13 @@ To validate your cluster.conf against this schema, run:
chosen." rha:sample="active"/>
</optional>
<optional>
+ <attribute name="rrp_problem_count_threshold"
+ rha:description="This specifies the number of times a problem is detected
+ with a link before setting the link faulty. Once a link is set faulty, no
+ more data is transmitted upon it. Corosync default is 10, cman default is 3"
+ rha:default="3" rha:sample="5"/>
+ </optional>
+ <optional>
<attribute name="secauth" rha:description="This attribute specifies
that HMAC/SHA1 authentication should be used to authenticate all
messages. It further specifies that all data should be encrypted
12 years, 7 months
cluster: STABLE31 - cman: improve cman/qdisk interactions
by Fabio M. Di Nitto
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 65f694d6c69b37fd57da251a39e2fb491cd97e28
Parent: 7e4856e8b5f98d4b70a0c434b876f80c8aa43c5c
Author: Fabio M. Di Nitto <fdinitto(a)redhat.com>
AuthorDate: Wed Sep 7 14:26:06 2011 +0200
Committer: Fabio M. Di Nitto <fdinitto(a)redhat.com>
CommitterDate: Thu Sep 8 08:58:33 2011 +0200
cman: improve cman/qdisk interactions
- libcman/cman: add new quorum API call to update name and votes of a quorum device
- cman: simplify common code to free quorum_device infrastructure and handle quorum recalculation
- cman: do better logging/error reports of the quorum API usage
- cman: use strdup instead of malloc+strcpy (code is more readable)
- libcman: perform better error checking in register_quorum_device/update_quorum_device
- Allow qdisk to update device name in cman using a new libcman quorum API call
- Perform slight better error checking of some update opertaions
Resolves: rhbz#735917
Signed-off-by: Fabio M. Di Nitto <fdinitto(a)redhat.com>
---
cman/daemon/cnxman-socket.h | 1 +
cman/daemon/commands.c | 135 +++++++++++++++++++++++++++++++++----------
cman/lib/libcman.c | 19 +++++-
cman/lib/libcman.h | 4 +
cman/qdisk/main.c | 28 ++++++++-
5 files changed, 150 insertions(+), 37 deletions(-)
diff --git a/cman/daemon/cnxman-socket.h b/cman/daemon/cnxman-socket.h
index e8b7378..d243b40 100644
--- a/cman/daemon/cnxman-socket.h
+++ b/cman/daemon/cnxman-socket.h
@@ -32,6 +32,7 @@
#define CMAN_CMD_REG_QUORUMDEV 0x800000b5
#define CMAN_CMD_UNREG_QUORUMDEV 0x800000b6
#define CMAN_CMD_POLL_QUORUMDEV 0x800000b7
+#define CMAN_CMD_UPDATE_QUORUMDEV 0x800000b8
#define CMAN_CMD_TRY_SHUTDOWN 0x800000bb
#define CMAN_CMD_SHUTDOWN_REPLY 0x000000bc
#define CMAN_CMD_UPDATE_FENCE_INFO 0x800000bd
diff --git a/cman/daemon/commands.c b/cman/daemon/commands.c
index 2948952..02fe88d 100644
--- a/cman/daemon/commands.c
+++ b/cman/daemon/commands.c
@@ -1080,27 +1080,66 @@ static int do_cmd_try_shutdown(struct connection *con, char *cmdbuf)
return 0;
}
+static void free_quorum_device(void)
+{
+ if (!quorum_device)
+ return;
+
+ if (quorum_device->name)
+ free(quorum_device->name);
+
+ free(quorum_device);
+
+ quorum_device = NULL;
+}
+
+static void quorum_device_update_votes(int votes)
+{
+ int oldvotes;
+
+ /* Update votes even if it existed before */
+ oldvotes = quorum_device->votes;
+ quorum_device->votes = votes;
+
+ /* If it is a member and votes changed, recalculate quorum */
+ if (quorum_device->state == NODESTATE_MEMBER &&
+ oldvotes != votes) {
+ recalculate_quorum(1, 0);
+ }
+}
+
static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
{
int votes;
- int oldvotes;
char *name = cmdbuf+sizeof(int);
- if (!ais_running)
+ if (!ais_running) {
+ log_printf(LOG_ERR, "unable to register quorum device: corosync is not running\n");
return -ENOTCONN;
+ }
- if (!we_are_a_cluster_member)
+ if (!we_are_a_cluster_member) {
+ log_printf(LOG_ERR, "unable to register quorum device: this node is not part of a cluster\n");
return -ENOENT;
+ }
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) {
+ log_printf(LOG_ERR, "unable to register quorum device: name is too long\n");
+ /* this should probably return -E2BIG? */
return -EINVAL;
+ }
/* Allow re-registering of a quorum device if the name is the same */
- if (quorum_device && strcmp(name, quorum_device->name))
- return -EBUSY;
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ log_printf(LOG_ERR, "unable to re-register quorum device: device names do not match\n");
+ log_printf(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
+ return -EBUSY;
+ }
- if (find_node_by_name(name))
- return -EALREADY;
+ if (find_node_by_name(name)) {
+ log_printf(LOG_ERR, "unable to register quorum device: a node with the same name (%s) already exists\n", name);
+ return -EALREADY;
+ }
memcpy(&votes, cmdbuf, sizeof(int));
@@ -1108,18 +1147,19 @@ static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
if (!quorum_device)
{
quorum_device = malloc(sizeof(struct cluster_node));
- if (!quorum_device)
+ if (!quorum_device) {
+ log_printf(LOG_ERR, "unable to register quorum device: not enough memory\n");
return -ENOMEM;
+ }
memset(quorum_device, 0, sizeof(struct cluster_node));
- quorum_device->name = malloc(strlen(name) + 1);
+ quorum_device->name = strdup(name);
if (!quorum_device->name) {
- free(quorum_device);
- quorum_device = NULL;
+ log_printf(LOG_ERR, "unable to register quorum device: not enough memory\n");
+ free_quorum_device();
return -ENOMEM;
}
- strcpy(quorum_device->name, name);
quorum_device->state = NODESTATE_DEAD;
gettimeofday(&quorum_device->join_time, NULL);
@@ -1132,34 +1172,63 @@ static int do_cmd_register_quorum_device(char *cmdbuf, int *retlen)
log_printf(LOG_INFO, "quorum device re-registered\n");
}
- /* Update votes even if it existed before */
- oldvotes = quorum_device->votes;
- quorum_device->votes = votes;
+ quorum_device_update_votes(votes);
- /* If it is a member and votes decreased, recalculate quorum */
- if (quorum_device->state == NODESTATE_MEMBER &&
- oldvotes != votes) {
- recalculate_quorum(1, 0);
+ return 0;
+}
+
+static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
+{
+ if (!quorum_device) {
+ log_printf(LOG_DEBUG, "memb: failed to unregister a non existing quorum device\n");
+ return -EINVAL;
+ }
+
+ if (quorum_device->state == NODESTATE_MEMBER) {
+ log_printf(LOG_DEBUG, "memb: failed to unregister: quorum device still active.\n");
+ return -EBUSY;
}
- return 0;
+ free_quorum_device();
+
+ log_printf(LOG_INFO, "quorum device unregistered\n");
+ return 0;
}
-static int do_cmd_unregister_quorum_device(char *cmdbuf, int *retlen)
+static int do_cmd_update_quorum_device(char *cmdbuf, int *retlen)
{
- if (!quorum_device)
- return -EINVAL;
+ int votes, ret = 0;
+ char *name = cmdbuf+sizeof(int);
- if (quorum_device->state == NODESTATE_MEMBER)
- return -EBUSY;
+ if (!quorum_device) {
+ log_printf(LOG_DEBUG, "memb: failed to update a non-existing quorum device\n");
+ return -EINVAL;
+ }
- free(quorum_device->name);
- free(quorum_device);
+ memcpy(&votes, cmdbuf, sizeof(int));
- quorum_device = NULL;
+ /* allow name change of the quorum device */
+ if (quorum_device && strcmp(name, quorum_device->name)) {
+ char *newname = NULL;
+ char *oldname = NULL;
- log_printf(LOG_INFO, "quorum device unregistered\n");
- return 0;
+ log_printf(LOG_DEBUG, "memb: old name: %s new name: %s\n", quorum_device->name, name);
+ newname = strdup(name);
+ if (!newname) {
+ log_printf(LOG_ERR, "memb: unable to update quorum device name: out of memory\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+ log_printf(LOG_INFO, "quorum device name changed to %s\n", name);
+ oldname = quorum_device->name;
+ quorum_device->name = newname;
+ free(oldname);
+ }
+
+out:
+ quorum_device_update_votes(votes);
+
+ return ret;
}
static int reload_config(int new_version, int should_broadcast)
@@ -1560,6 +1629,10 @@ int process_command(struct connection *con, int cmd, char *cmdbuf,
err = do_cmd_unregister_quorum_device(cmdbuf, retlen);
break;
+ case CMAN_CMD_UPDATE_QUORUMDEV:
+ err = do_cmd_update_quorum_device(cmdbuf, retlen);
+ break;
+
case CMAN_CMD_POLL_QUORUMDEV:
err = do_cmd_poll_quorum_device(cmdbuf, retlen);
break;
diff --git a/cman/lib/libcman.c b/cman/lib/libcman.c
index daaad07..a89c731 100644
--- a/cman/lib/libcman.c
+++ b/cman/lib/libcman.c
@@ -1002,14 +1002,15 @@ int cman_replyto_shutdown(cman_handle_t handle, int yesno)
return 0;
}
-
-int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+static int cman_set_quorum_device(cman_handle_t handle,
+ int ops,
+ char *name, int votes)
{
struct cman_handle *h = (struct cman_handle *)handle;
char buf[strlen(name)+1 + sizeof(int)];
VALIDATE_HANDLE(h);
- if (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN)
+ if ((!name) || (strlen(name) > MAX_CLUSTER_MEMBER_NAME_LEN) || (votes < 0))
{
errno = EINVAL;
return -1;
@@ -1017,7 +1018,12 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
memcpy(buf, &votes, sizeof(int));
strcpy(buf+sizeof(int), name);
- return info_call(h, CMAN_CMD_REG_QUORUMDEV, buf, strlen(name)+1+sizeof(int), NULL, 0);
+ return info_call(h, ops, buf, strlen(name)+1+sizeof(int), NULL, 0);
+}
+
+int cman_register_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_REG_QUORUMDEV, name, votes);
}
int cman_unregister_quorum_device(cman_handle_t handle)
@@ -1053,6 +1059,11 @@ int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info)
return ret;
}
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes)
+{
+ return cman_set_quorum_device(handle, CMAN_CMD_UPDATE_QUORUMDEV, name, votes);
+}
+
int cman_get_fenceinfo(cman_handle_t handle, int nodeid, uint64_t *time, int *fenced, char *agent)
{
struct cman_handle *h = (struct cman_handle *)handle;
diff --git a/cman/lib/libcman.h b/cman/lib/libcman.h
index feb10a2..9f97875 100644
--- a/cman/lib/libcman.h
+++ b/cman/lib/libcman.h
@@ -420,6 +420,9 @@ int cman_barrier_delete(cman_handle_t handle, const char *name);
/*
* Add your own quorum device here, needs an admin socket
*
+ * register_quorum and update_quorum arguments are mandatory.
+ * name has to be a valid null-terminated string and votes >= 0.
+ *
* After creating a quorum device you will need to call 'poll_quorum_device'
* at least once every (default) 10 seconds (this can be changed in CCS)
* otherwise it will time-out and the cluster will lose its vote.
@@ -428,6 +431,7 @@ int cman_register_quorum_device(cman_handle_t handle, char *name, int votes);
int cman_unregister_quorum_device(cman_handle_t handle);
int cman_poll_quorum_device(cman_handle_t handle, int isavailable);
int cman_get_quorum_device(cman_handle_t handle, struct cman_qdev_info *info);
+int cman_update_quorum_device(cman_handle_t handle, char *name, int votes);
/*
* Sets the dirty bit inside cman. This indicates that the node has
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index c1598fa..d613d84 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -690,6 +690,17 @@ register_device(qd_ctx *ctx)
ctx->qc_votes : 0);
}
+static int
+update_device(qd_ctx *ctx)
+{
+ return cman_update_quorum_device(
+ ctx->qc_cman_admin,
+ (ctx->qc_flags&RF_CMAN_LABEL) ?
+ ctx->qc_cman_label : ctx->qc_device,
+ (!(ctx->qc_flags & RF_MASTER_WINS) ||
+ ctx->qc_status == S_MASTER) ?
+ ctx->qc_votes : 0);
+}
static int
adjust_votes(qd_ctx *ctx)
@@ -2119,9 +2130,22 @@ main(int argc, char **argv)
if (!_running)
goto out;
-
+
/* This registers the quorum device */
- register_device(&ctx);
+ ret = register_device(&ctx);
+ if (ret) {
+ if (errno == EBUSY) {
+ logt_print(LOG_NOTICE, "quorum device is already registered, updating\n");
+ ret = update_device(&ctx);
+ if (ret) {
+ logt_print(LOG_ERR, "Unable to update quorum device info!\n");
+ goto out;
+ }
+ } else {
+ logt_print(LOG_ERR, "Unable to register quorum device!\n");
+ goto out;
+ }
+ }
io_nanny_start(ch_user, ctx.qc_tko * ctx.qc_interval);
12 years, 7 months
gfs2-utils: master - libgfs2: Fix off-by-one error in rgrp searching
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 320251b01daf66d9324a32a1db9c00015c67c0e4
Parent: 3d4d902ad95128679c005373eda1e033e716d02f
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 7 13:53:13 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Sep 7 13:53:13 2011 -0500
libgfs2: Fix off-by-one error in rgrp searching
The patch fixes an off-by-one error that results in landing on the
wrong resource group when searching for an address exactly equal to
an rgrp's ri_addr.
This bug is mostly seen if you're walking the rgrps from gfs2_edit
and walk the bitmaps: The bitmap's block translation will be
calculated for the wrong rgrp. The code was checking to see if the
block is greater than ri->ri_data0 + ri->ri_data, but technically
ri->ri_data0 + ri->ri_data is the ri_addr of the next rgrp.
So the correct calculation should be block > ri_data0 + ri_data - 1
or for simplicity of coding, block >= ri_data0 + ri_data
---
gfs2/libgfs2/rgrp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index e7b5f72..3e852d2 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -106,7 +106,7 @@ struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
if (blk < ri->ri_addr)
node = node->osi_left;
- else if (blk > ri->ri_data0 + ri->ri_data)
+ else if (blk >= ri->ri_data0 + ri->ri_data)
node = node->osi_right;
else
return rgd;
12 years, 7 months
cluster: STABLE31 - rgmanager: Fix segfault caused by unref race
by Lon Hohberger
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 7e4856e8b5f98d4b70a0c434b876f80c8aa43c5c
Parent: cebf9e1fc3fb524223f49382c43ac2044d69c3be
Author: Lon Hohberger <lhh(a)redhat.com>
AuthorDate: Wed Sep 7 11:09:10 2011 -0400
Committer: Lon Hohberger <lhh(a)redhat.com>
CommitterDate: Wed Sep 7 15:20:56 2011 -0400
rgmanager: Fix segfault caused by unref race
Since we only ever open/close the connection in one
place, there is no need to call ref/unref in the
separate thread, since we wait for that thread to exit
before calling DBus *close() and *unref() functions.
It is possible for notification(s) to be sent during
shutdown after shutting down the DBus connection.
Since notifications are best-effort and having the
DBus thread shut down is a normal condition, we should
not log errors when this condition occurs.
The rgm_dbus_notify() function was not locking around
checks to the private db variable, which was incorrect.
Resolves: rhbz#697446
Signed-off-by: Lon Hohberger <lhh(a)redhat.com>
Tested-by: Lon Hohberger <lhh(a)redhat.com>
---
rgmanager/src/daemons/update-dbus.c | 16 +++++++++++-----
1 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/rgmanager/src/daemons/update-dbus.c b/rgmanager/src/daemons/update-dbus.c
index bff1644..b45113c 100644
--- a/rgmanager/src/daemons/update-dbus.c
+++ b/rgmanager/src/daemons/update-dbus.c
@@ -127,13 +127,11 @@ static void *
_dbus_auto_flush(void *arg)
{
/* DBus connection functions are thread safe */
- dbus_connection_ref(db);
while (dbus_connection_read_write(db, 500)) {
if (!th)
break;
}
- dbus_connection_unref(db);
th = 0;
return NULL;
}
@@ -147,7 +145,7 @@ _rgm_dbus_notify(const char *svcname,
const char *svclast)
{
DBusMessage *msg = NULL;
- int ret = -1;
+ int ret = 0;
pthread_mutex_lock(&mu);
@@ -155,6 +153,9 @@ _rgm_dbus_notify(const char *svcname,
goto out_unlock;
}
+ /* Notifications are enabled */
+ ret = -1;
+
/* Check to ensure the connection is still valid. If it
* isn't, clean up and shut down the dbus connection.
*
@@ -215,12 +216,17 @@ rgm_dbus_update(char *key, uint64_t view, void *data, uint32_t size)
if (!rgm_dbus_notify)
goto out_free;
- if (!db)
- goto out_free;
if (view == 1)
goto out_free;
if (size != (sizeof(*st)))
goto out_free;
+
+ pthread_mutex_lock(&mu);
+ if (!db) {
+ pthread_mutex_unlock(&mu);
+ goto out_free;
+ }
+ pthread_mutex_unlock(&mu);
st = (rg_state_t *)data;
swab_rg_state_t(st);
12 years, 7 months
gfs2-utils: master - gfs2_edit: Fix segfault jumping within rindex
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 3d4d902ad95128679c005373eda1e033e716d02f
Parent: 35a6232630c764fb1c33e0a28fdc8edf556aa9d8
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 7 13:07:31 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Wed Sep 7 13:11:46 2011 -0500
gfs2_edit: Fix segfault jumping within rindex
This patch fixes a segfault that occurs when you jump to an rindex
entry from the extended mode. The problem was that the jump code
was assuming jumps occurred only from structures that had an indirect
data structure. The rindex doesn't, so it tried to reference an
invalid entry in the indirect structure.
---
gfs2/edit/hexedit.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index dd0cf60..5864e2d 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -1920,7 +1920,7 @@ static void push_block(uint64_t blk)
blockstack[bhst].lines_per_row[i] = lines_per_row[i];
}
blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
- if (edit_row[dmode] >= 0)
+ if (edit_row[dmode] >= 0 && !block_is_rindex())
memcpy(&blockstack[bhst].mp,
&indirect->ii[edit_row[dmode]].mp,
sizeof(struct metapath));
@@ -2409,8 +2409,8 @@ static void jump(void)
int i;
offset = 0;
+ push_block(temp_blk);
block = temp_blk;
- push_block(block);
for (i = 0; i < DMODES; i++) {
start_row[i] = end_row[i] = edit_row[i] = 0;
edit_col[i] = 0;
12 years, 7 months