Patchwork [BUG:1303,2/2] client changes for 'gluster volume migration' to work

login
register
Submitter Amar Tumballi
Date 2010-08-12 10:19:50
Message ID <20100812101950.GA6161@gluster.com>
Download mbox | patch
Permalink /patch/4090/
State Accepted
Headers show

Comments

Amar Tumballi - 2010-08-12 10:19:50
Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Pavan Vilas Sondur <pavan@gluster.com>
---
 extras/volgen/CreateVolfile.py       |   17 ++-
 xlators/protocol/client/src/client.c |  259 +++++++++++++++++++++++++++++-----
 xlators/protocol/client/src/client.h |    4 +
 3 files changed, 246 insertions(+), 34 deletions(-)

Patch

diff --git a/extras/volgen/CreateVolfile.py b/extras/volgen/CreateVolfile.py
index f243f7e..df38a99 100644
--- a/extras/volgen/CreateVolfile.py
+++ b/extras/volgen/CreateVolfile.py
@@ -309,6 +309,21 @@  class CreateVolfile:
                 exp_fd.write ("    subvolumes posix\n")
             exp_fd.write ("end-volume\n\n")
 
+            exp_fd.write ("volume replace-brick\n")
+            exp_fd.write ("    type protocol/client\n")
+            if self.transport:
+                exp_fd.write ("    option transport-type %s\n" % self.transport)
+
+            if self.gfs_port:
+                exp_fd.write ("    option transport.remote-port %d\n" % self.gfs_port)
+            exp_fd.write ("    option ping-timeout 42\n")
+            exp_fd.write ("end-volume\n\n")
+
+            exp_fd.write ("volume pump\n")
+            exp_fd.write ("    type cluster/pump\n")
+            exp_fd.write ("    subvolumes locks replace-brick\n")
+            exp_fd.write ("end-volume\n\n")
+
             exp_fd.write ("volume %s\n" % export)
             exp_fd.write ("    type performance/io-threads\n")
             exp_fd.write ("    option thread-count 8\n")
@@ -316,7 +331,7 @@  class CreateVolfile:
             exp_fd.write ("#   option min-threads 2 # min count for thread pool\n")
             exp_fd.write ("#   option max-threads 64 # max count for thread pool\n")
 
-            exp_fd.write ("    subvolumes locks\n")
+            exp_fd.write ("    subvolumes pump\n")
             exp_fd.write ("end-volume\n\n")
 
             for transport in self.transports:
diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c
index c8bbd46..c481ae9 100644
--- a/xlators/protocol/client/src/client.c
+++ b/xlators/protocol/client/src/client.c
@@ -35,11 +35,10 @@ 
 extern rpc_clnt_prog_t clnt_handshake_prog;
 extern rpc_clnt_prog_t clnt_dump_prog;
 
-int
-client_handshake (xlator_t *this, struct rpc_clnt *rpc);
-
-void
-client_start_ping (void *data);
+int client_handshake (xlator_t *this, struct rpc_clnt *rpc);
+void client_start_ping (void *data);
+int client_init_rpc (xlator_t *this);
+int client_destroy_rpc (xlator_t *this);
 
 int
 client_submit_request (xlator_t *this, void *req, call_frame_t *frame,
@@ -836,16 +835,145 @@  out:
 	return 0;
 }
 
+static gf_boolean_t
+is_client_rpc_init_command (dict_t *dict, xlator_t *this,
+                            char **value)
+{
+        gf_boolean_t ret      = _gf_false;
+        int          dict_ret = -1;
+
+        if (strncmp (this->name, "replace-brick", 13))
+                goto out;
+
+        dict_ret = dict_get_str (dict, CLIENT_CMD_CONNECT, value);
+        if (dict_ret)
+                goto out;
+
+        ret = _gf_true;
+
+out:
+        return ret;
+
+}
+
+static gf_boolean_t
+is_client_rpc_destroy_command (dict_t *dict, xlator_t *this)
+{
+        gf_boolean_t ret      = _gf_false;
+        int          dict_ret = -1;
+        char        *dummy    = NULL;
+
+        if (strncmp (this->name, "replace-brick", 13))
+                goto out;
+
+        dict_ret = dict_get_str (dict, CLIENT_CMD_DISCONNECT, &dummy);
+        if (dict_ret)
+                goto out;
+
+        ret = _gf_true;
+
+out:
+        return ret;
+
+}
+
+static gf_boolean_t
+client_set_remote_options (char *value, xlator_t *this)
+{
+        clnt_conf_t  *conf          = NULL;
+        char         *dup_value     = NULL;
+        char         *host          = NULL;
+        char         *subvol        = NULL;
+        char         *host_dup      = NULL;
+        char         *subvol_dup    = NULL;
+        char         *tmp           = NULL;
+        gf_boolean_t  ret           = _gf_false;
+
+        conf = this->private;
+
+        dup_value = gf_strdup (value);
+        host = strtok_r (dup_value, ":", &tmp);
+        subvol = strtok_r (NULL, ":", &tmp);
+        if (!subvol) {
+                gf_log (this->name, GF_LOG_WARNING,
+                        "proper value not passed as subvolume");
+                goto out;
+        }
+
+        host_dup = gf_strdup (host);
+        if (!host_dup) {
+                gf_log (this->name, GF_LOG_ERROR,
+                        "Out of memory");
+                goto out;
+        }
+
+        ret = dict_set_dynstr (this->options, "remote-host", host_dup);
+        if (ret) {
+                gf_log (this->name, GF_LOG_WARNING,
+                        "failed to set remote-host with %s", host);
+                goto out;
+        }
+
+        subvol_dup = gf_strdup (subvol);
+        if (!subvol_dup) {
+                gf_log (this->name, GF_LOG_ERROR,
+                        "Out of memory");
+                goto out;
+        }
+
+        ret = dict_set_dynstr (this->options, "remote-subvolume", subvol_dup);
+        if (ret) {
+                gf_log (this->name, GF_LOG_WARNING,
+                        "failed to set remote-host with %s", host);
+                goto out;
+        }
+
+        ret = _gf_true;
+out:
+        if (dup_value)
+                GF_FREE (dup_value);
+
+        return ret;
+}
 
 
 int32_t
 client_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
                  int32_t flags)
 {
-        int          ret  = -1;
-        clnt_conf_t *conf = NULL;
-        rpc_clnt_procedure_t *proc = NULL;
-        clnt_args_t  args = {0,};
+        int                   ret         = -1;
+        int                   op_ret      = -1;
+        int                   op_errno    = ENOTCONN;
+        int                   need_unwind = 0;
+        clnt_conf_t          *conf        = NULL;
+        rpc_clnt_procedure_t *proc        = NULL;
+        clnt_args_t           args        = {0,};
+        char                 *value       = NULL;
+
+
+        if (is_client_rpc_init_command (dict, this, &value) == _gf_true) {
+                GF_ASSERT (value);
+                ret = client_set_remote_options (value, this);
+                if (ret)
+                        ret = client_init_rpc (this);
+
+                if (!ret) {
+                        op_ret      = 0;
+                        op_errno    = 0;
+                }
+                need_unwind = 1;
+                goto out;
+        }
+
+        if (is_client_rpc_destroy_command (dict, this) == _gf_true) {
+                ret = client_destroy_rpc (this);
+                if (ret) {
+                        op_ret      = 0;
+                        op_errno    = 0;
+                }
+                need_unwind = 1;
+                goto out;
+        }
 
         conf = this->private;
         if (!conf->fops)
@@ -856,11 +984,17 @@  client_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
         args.flags = flags;
 
         proc = &conf->fops->proctable[GF_FOP_SETXATTR];
-        if (proc->fn)
+        if (proc->fn) {
                 ret = proc->fn (frame, this, &args);
+                if (ret) {
+                        op_ret = -1;
+                        op_errno = ENOTCONN;
+                        need_unwind = 1;
+                }
+        }
 out:
-        if (ret)
-                STACK_UNWIND_STRICT (setxattr, frame, -1, ENOTCONN);
+        if (need_unwind)
+                STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno);
 
 	return 0;
 }
@@ -1476,14 +1610,6 @@  build_client_config (xlator_t *this, clnt_conf_t *conf)
 {
         int ret = 0;
 
-        ret = dict_get_str (this->options, "remote-subvolume",
-                            &conf->opt.remote_subvolume);
-        if (ret) {
-                gf_log (this->name, GF_LOG_ERROR,
-                        "option 'remote-subvolume' not given");
-                goto out;
-        }
-
         ret = dict_get_int32 (this->options, "frame-timeout",
                               &conf->rpc_conf.rpc_timeout);
         if (ret >= 0) {
@@ -1517,6 +1643,16 @@  build_client_config (xlator_t *this, clnt_conf_t *conf)
                 conf->opt.ping_timeout = GF_UNIVERSAL_ANSWER;
         }
 
+        ret = dict_get_str (this->options, "remote-subvolume",
+                            &conf->opt.remote_subvolume);
+        if (ret) {
+                /* This is valid only if 'cluster/pump' is the parent */
+                gf_log (this->name, GF_LOG_NORMAL,
+                        "option 'remote-subvolume' not given");
+                ret = 1;
+                goto out;
+        }
+
         ret = 0;
 out:
         return ret;
@@ -1542,6 +1678,63 @@  mem_acct_init (xlator_t *this)
         return ret;
 }
 
+int
+client_destroy_rpc (xlator_t *this)
+{
+        int          ret  = -1;
+        clnt_conf_t *conf = NULL;
+
+        conf = this->private;
+
+        if (conf->rpc) {
+                rpc_clnt_destroy (conf->rpc);
+                ret = 0;
+                gf_log (this->name, GF_LOG_DEBUG,
+                        "Client rpc conn destroyed");
+                goto out;
+        }
+
+        gf_log (this->name, GF_LOG_DEBUG,
+                "RPC destory called on already destroyed "
+                "connection");
+
+out:
+        return ret;
+}
+
+int
+client_init_rpc (xlator_t *this)
+{
+        int          ret  = -1;
+        clnt_conf_t *conf = NULL;
+
+        conf = this->private;
+
+        if (conf->rpc) {
+                gf_log (this->name, GF_LOG_DEBUG,
+                        "client rpc already init'ed");
+                ret = -1;
+                goto out;
+        }
+
+        conf->rpc = rpc_clnt_init (&conf->rpc_conf, this->options, this->ctx,
+                                   this->name);
+        if (!conf->rpc)
+                goto out;
+
+        ret = rpc_clnt_register_notify (conf->rpc, client_rpc_notify, this);
+        if (ret)
+                goto out;
+
+        conf->handshake = &clnt_handshake_prog;
+        conf->dump      = &clnt_dump_prog;
+
+        ret = 0;
+
+        gf_log (this->name, GF_LOG_DEBUG, "client init successful");
+out:
+        return ret;
+}
 
 int
 init (xlator_t *this)
@@ -1569,24 +1762,24 @@  init (xlator_t *this)
         pthread_mutex_init (&conf->lock, NULL);
         INIT_LIST_HEAD (&conf->saved_fds);
 
+        this->private = conf;
+
+        /* If it returns -1, then its a failure, if it returns +1 we need
+           have to understand that 'this' is subvolume of a xlator which,
+           will set the remote host and remote subvolume in a setxattr
+           call.
+        */
+
         ret = build_client_config (this, conf);
-        if (ret)
+        if (ret == -1)
                 goto out;
 
-        conf->rpc = rpc_clnt_init (&conf->rpc_conf, this->options, this->ctx,
-                                   this->name);
-        if (!conf->rpc)
-                goto out;
-        conf->rpc->xid = 42; /* It should be enough random everytime :O */
-        ret = rpc_clnt_register_notify (conf->rpc, client_rpc_notify, this);
-        if (ret)
+        if (ret) {
+                ret = 0;
                 goto out;
+        }
 
-        conf->handshake = &clnt_handshake_prog;
-        conf->dump      = &clnt_dump_prog;
-        this->private = conf;
-
-        ret = 0;
+        ret = client_init_rpc (this);
 out:
         if (ret)
                 this->fini (this);
diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h
index 234df4e..473ae2a 100644
--- a/xlators/protocol/client/src/client.h
+++ b/xlators/protocol/client/src/client.h
@@ -30,6 +30,10 @@ 
 #include "protocol-common.h"
 #include "glusterfs3-xdr.h"
 
+/* FIXME: Needs to be defined in a common file */
+#define CLIENT_CMD_CONNECT "trusted.glusterfs.client-connect"
+#define CLIENT_CMD_DISCONNECT "trusted.glusterfs.client-disconnect"
+
 struct clnt_options {
         char *remote_subvolume;
         int   ping_timeout;