[Ocfs2-tools-devel] [PATCH 32/39] libo2cb: Add the API to open and
close the ocfs2_control device.
Joel Becker
joel.becker at oracle.com
Fri Mar 14 16:52:55 PDT 2008
This API is used by ocfs2_controld to connect to the filesystem module.
It performs a handshake with the kernel driver, after which filesystems
can be mounted.
Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
include/o2cb/o2cb.h | 3 +
libo2cb/o2cb_abi.c | 167 ++++++++++++++++++++++++++++++++++++++++++------
ocfs2_controld/main.c | 12 +++-
3 files changed, 160 insertions(+), 22 deletions(-)
diff --git a/include/o2cb/o2cb.h b/include/o2cb/o2cb.h
index 35e2d1d..9373f0c 100644
--- a/include/o2cb/o2cb.h
+++ b/include/o2cb/o2cb.h
@@ -113,6 +113,9 @@ errcode_t o2cb_get_node_num(const char *cluster_name,
const char *node_name,
uint16_t *node_num);
+errcode_t o2cb_control_open(unsigned int this_node);
+void o2cb_control_close(void);
+
errcode_t o2cb_get_hb_ctl_path(char *buf, int count);
#endif /* _O2CB_H */
diff --git a/libo2cb/o2cb_abi.c b/libo2cb/o2cb_abi.c
index 7d26da3..65383db 100644
--- a/libo2cb/o2cb_abi.c
+++ b/libo2cb/o2cb_abi.c
@@ -44,6 +44,7 @@
#define CLUSTER_STACK_FILE "/sys/fs/ocfs2/cluster_stack"
#define OCFS2_STACK_LABEL_LEN 4
+#define CONTROL_DEVICE "/dev/misc/ocfs2_control"
struct o2cb_stack_ops {
@@ -100,7 +101,8 @@ static struct o2cb_stack user_stack = {
};
static struct o2cb_stack *current_stack;
-static int controld_fd = -1;
+static int control_daemon_fd = -1;
+static int control_device_fd = -1;
static char *configfs_path;
@@ -1241,7 +1243,7 @@ static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
char *argv[OCFS2_CONTROLD_MAXARGS + 1];
char buf[OCFS2_CONTROLD_MAXLINE];
- if (controld_fd != -1) {
+ if (control_daemon_fd != -1) {
/* fprintf(stderr, "Join already in progress!\n"); */
err = O2CB_ET_INTERNAL_FAILURE;
goto out;
@@ -1263,9 +1265,9 @@ static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
}
goto out;
}
- controld_fd = rc;
+ control_daemon_fd = rc;
- rc = send_message(controld_fd, CM_MOUNT, OCFS2_FS_NAME,
+ rc = send_message(control_daemon_fd, CM_MOUNT, OCFS2_FS_NAME,
region->r_name, cluster->c_cluster,
region->r_device_name, region->r_service);
if (rc) {
@@ -1275,7 +1277,7 @@ static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
goto out;
}
- rc = receive_message(controld_fd, buf, &message, argv);
+ rc = receive_message(control_daemon_fd, buf, &message, argv);
if (rc < 0) {
/* fprintf(stderr, "Error reading from daemon: %s\n",
strerror(-rc)); */
@@ -1312,9 +1314,9 @@ static errcode_t user_begin_group_join(struct o2cb_cluster_desc *cluster,
err = 0;
out:
- if (err && (controld_fd != -1)) {
- close(controld_fd);
- controld_fd = -1;
+ if (err && (control_daemon_fd != -1)) {
+ close(control_daemon_fd);
+ control_daemon_fd = -1;
}
return err;
@@ -1332,13 +1334,13 @@ static errcode_t user_complete_group_join(struct o2cb_cluster_desc *cluster,
char *argv[OCFS2_CONTROLD_MAXARGS + 1];
char buf[OCFS2_CONTROLD_MAXLINE];
- if (controld_fd == -1) {
+ if (control_daemon_fd == -1) {
/* fprintf(stderr, "Join not started!\n"); */
err = O2CB_ET_SERVICE_UNAVAILABLE;
goto out;
}
- rc = send_message(controld_fd, CM_MRESULT, OCFS2_FS_NAME,
+ rc = send_message(control_daemon_fd, CM_MRESULT, OCFS2_FS_NAME,
region->r_name, result, region->r_service);
if (rc) {
/* fprintf(stderr, "Unable to send MRESULT message: %s\n",
@@ -1347,7 +1349,7 @@ static errcode_t user_complete_group_join(struct o2cb_cluster_desc *cluster,
goto out;
}
- rc = receive_message(controld_fd, buf, &message, argv);
+ rc = receive_message(control_daemon_fd, buf, &message, argv);
if (rc < 0) {
/* fprintf(stderr, "Error reading from daemon: %s\n",
strerror(-rc)); */
@@ -1383,9 +1385,9 @@ static errcode_t user_complete_group_join(struct o2cb_cluster_desc *cluster,
err = 0;
out:
- if (controld_fd != -1) {
- close(controld_fd);
- controld_fd = -1;
+ if (control_daemon_fd != -1) {
+ close(control_daemon_fd);
+ control_daemon_fd = -1;
}
return err;
@@ -1402,7 +1404,7 @@ static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
char *argv[OCFS2_CONTROLD_MAXARGS + 1];
char buf[OCFS2_CONTROLD_MAXLINE];
- if (controld_fd != -1) {
+ if (control_daemon_fd != -1) {
/* fprintf(stderr, "Join in progress!\n"); */
err = O2CB_ET_INTERNAL_FAILURE;
goto out;
@@ -1424,9 +1426,9 @@ static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
}
goto out;
}
- controld_fd = rc;
+ control_daemon_fd = rc;
- rc = send_message(controld_fd, CM_UNMOUNT, OCFS2_FS_NAME,
+ rc = send_message(control_daemon_fd, CM_UNMOUNT, OCFS2_FS_NAME,
region->r_name, region->r_service);
if (rc) {
/* fprintf(stderr, "Unable to send UNMOUNT message: %s\n",
@@ -1435,7 +1437,7 @@ static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
goto out;
}
- rc = receive_message(controld_fd, buf, &message, argv);
+ rc = receive_message(control_daemon_fd, buf, &message, argv);
if (rc < 0) {
/* fprintf(stderr, "Error reading from daemon: %s\n",
strerror(-rc)); */
@@ -1472,9 +1474,9 @@ static errcode_t user_group_leave(struct o2cb_cluster_desc *cluster,
err = 0;
out:
- if (controld_fd != -1) {
- close(controld_fd);
- controld_fd = -1;
+ if (control_daemon_fd != -1) {
+ close(control_daemon_fd);
+ control_daemon_fd = -1;
}
return err;
@@ -1858,6 +1860,129 @@ errcode_t o2cb_get_node_num(const char *cluster_name, const char *node_name,
return 0;
}
+/*
+ * The handshake is pretty simple. We need to read all supported control
+ * device protocols from the kernel. Once we've read them, we can write
+ * the protocol we want to use. After that, we're good to go.
+ *
+ * Right now, we will just allow the T01 protocol and not write any
+ * code to handle multiples. We'll add that later if and when it is
+ * necessary.
+ *
+ * The versions read from the kernel are all 4 characers including the
+ * newline.
+ */
+#define OCFS2_CONTROL_PROTO "T01\n"
+#define OCFS2_CONTROL_PROTO_LEN 4
+#define OCFS2_CONTROL_MESSAGE_SETNODE_OP "SETN"
+#define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN 14
+#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN 8
+static errcode_t o2cb_control_handshake(unsigned int this_node)
+{
+ errcode_t err = 0;
+ int found = 0;
+ size_t ret;
+ char buf[OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN + 1];
+
+ if (control_device_fd == -1) {
+ err = O2CB_ET_INTERNAL_FAILURE;
+ goto out;
+ }
+
+ buf[OCFS2_CONTROL_PROTO_LEN] = '\0';
+ while (1)
+ {
+ ret = read(control_device_fd, buf, OCFS2_CONTROL_PROTO_LEN);
+ if (ret == OCFS2_CONTROL_PROTO_LEN) {
+ if (!found && !strcmp(buf,
+ OCFS2_CONTROL_PROTO))
+ found = 1;
+ continue;
+ }
+
+ if (ret != 0)
+ err = O2CB_ET_IO;
+ else if (!found)
+ err = O2CB_ET_SERVICE_UNAVAILABLE; /* no match */
+ break;
+ }
+
+ if (err)
+ goto out;
+
+ ret = write(control_device_fd, OCFS2_CONTROL_PROTO,
+ OCFS2_CONTROL_PROTO_LEN);
+ if (ret != OCFS2_CONTROL_PROTO_LEN) {
+ err = O2CB_ET_IO;
+ goto out;
+ }
+
+ snprintf(buf, OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN + 1,
+ "SETN %08X\n", this_node);
+ ret = write(control_device_fd, buf,
+ OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN);
+ if (ret != OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN)
+ err = O2CB_ET_IO;
+
+out:
+ return err;
+}
+
+errcode_t o2cb_control_open(unsigned int this_node)
+{
+ errcode_t err = 0;
+ int rc;
+
+ if (!current_stack) {
+ err = O2CB_ET_SERVICE_UNAVAILABLE;
+ goto out;
+ }
+
+ if (control_device_fd != -1)
+ goto out;
+
+ rc = open(CONTROL_DEVICE, O_RDWR);
+ if (rc < 0) {
+ switch (errno) {
+ default:
+ err = O2CB_ET_INTERNAL_FAILURE;
+ break;
+
+ case ENOTDIR:
+ case ENOENT:
+ case EISDIR:
+ err = O2CB_ET_SERVICE_UNAVAILABLE;
+ break;
+
+ case EACCES:
+ case EPERM:
+ case EROFS:
+ err = O2CB_ET_PERMISSION_DENIED;
+ break;
+ }
+ goto out;
+ }
+
+ control_device_fd = rc;
+
+ err = o2cb_control_handshake(this_node);
+ if (err) {
+ close(control_device_fd);
+ control_device_fd = -1;
+ }
+
+out:
+ return err;
+}
+
+void o2cb_control_close(void)
+{
+ if (control_device_fd != -1) {
+ close(control_device_fd);
+ control_device_fd = -1;
+ }
+}
+
errcode_t o2cb_get_hb_ctl_path(char *buf, int count)
{
int fd;
diff --git a/ocfs2_controld/main.c b/ocfs2_controld/main.c
index 246af07..770a137 100644
--- a/ocfs2_controld/main.c
+++ b/ocfs2_controld/main.c
@@ -571,9 +571,18 @@ static int setup_listener(void)
static void cpg_joined(void)
{
int rv;
+ errcode_t err;
- log_debug("CPG is live, starting to listen for mounters");
+ log_debug("CPG is live, opening control device");
+ err = o2cb_control_open(our_nodeid);
+ if (err) {
+ log_error("Error opening control device: %s",
+ error_message(err));
+ shutdown_daemon();
+ return;
+ }
+ log_debug("Starting to listen for mounters");
rv = setup_listener();
if (rv < 0) {
shutdown_daemon();
@@ -633,6 +642,7 @@ stop:
bail_on_mounts();
+ o2cb_control_close();
exit_cpg();
exit_cman();
--
1.5.3.8
More information about the Ocfs2-tools-devel
mailing list