diff options
| author | Amar Tumballi <amar@gluster.com> | 2010-06-21 07:00:04 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2010-06-21 20:21:10 -0700 | 
| commit | fdd20492638fe98a62b5e6d5e82f18cf4799fd1a (patch) | |
| tree | 98082d7bfdc66157f40666f2070d3a45b582327a /xlators/protocol/client/src | |
| parent | b9b8734a9496ccf5f8ed5527dc7714930a59948b (diff) | |
rpc protocol
Signed-off-by: Amar Tumballi <amar@gluster.com>
Signed-off-by: Raghavendra G <raghavendra@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 875 (Implement a new protocol to provide proper backward/forward compatibility)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=875
Diffstat (limited to 'xlators/protocol/client/src')
| -rw-r--r-- | xlators/protocol/client/src/Makefile.am | 16 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client-handshake.c | 738 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client-helpers.c | 109 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client-mem-types.h | 32 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client.c | 1791 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client.h | 125 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client3_1-fops.c | 4662 | 
7 files changed, 7473 insertions, 0 deletions
diff --git a/xlators/protocol/client/src/Makefile.am b/xlators/protocol/client/src/Makefile.am new file mode 100644 index 00000000000..40281467e17 --- /dev/null +++ b/xlators/protocol/client/src/Makefile.am @@ -0,0 +1,16 @@ + +xlator_LTLIBRARIES = client.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/alpha/protocol + +client_la_LDFLAGS = -module -avoidversion + +client_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ +	$(top_builddir)/xlators/protocol/rpc/rpc-lib/src/libgfrpc.la \ +	$(top_builddir)/xlators/protocol/lib/src/libgfproto1.la + +client_la_SOURCES = client.c client-helpers.c client3_1-fops.c client-handshake.c +noinst_HEADERS = client.h client-mem-types.h + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \ +	-I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)  \ +	-I$(top_srcdir)/xlators/protocol/lib/src -I$(top_srcdir)/xlators/protocol/rpc/rpc-lib/src/ diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c new file mode 100644 index 00000000000..79cabd106b2 --- /dev/null +++ b/xlators/protocol/client/src/client-handshake.c @@ -0,0 +1,738 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "xlator.h" +#include "defaults.h" +#include "glusterfs.h" +#include "msg-xdr.h" +#include "statedump.h" +#include "compat-errno.h" + +extern rpc_clnt_prog_t clnt3_1_fop_prog; +extern rpc_clnt_prog_t clnt3_1_mgmt_prog; + +/* Handshake */ + +void +rpc_client_ping_timer_expired (void *data) +{ +        rpc_transport_t         *trans              = NULL; +        rpc_clnt_connection_t   *conn               = NULL; +        int                      disconnect         = 0; +        int                      transport_activity = 0; +        struct timeval           timeout            = {0, }; +        struct timeval           current            = {0, }; +        struct rpc_clnt         *clnt               = NULL; +        xlator_t                *this               = NULL; +        clnt_conf_t             *conf               = NULL; + +        if (!data) { +                goto out; +        } + +        this = data; +        conf = this->private; + +        conn = &conf->rpc->conn; +        trans = conn->trans; + +        if (!clnt || !trans) { +                goto out; +        } + +        pthread_mutex_lock (&conn->lock); +        { +                if (conn->ping_timer) +                        gf_timer_call_cancel (this->ctx, +                                              conn->ping_timer); +                gettimeofday (¤t, NULL); + +                if (((current.tv_sec - conn->last_received.tv_sec) < +                     conf->opt.ping_timeout) +                    || ((current.tv_sec - conn->last_sent.tv_sec) < +                        conf->opt.ping_timeout)) { +                        transport_activity = 1; +                } + +                if (transport_activity) { +                        gf_log (trans->name, GF_LOG_TRACE, +                                "ping timer expired but transport activity " +                                "detected - not bailing transport"); +                        timeout.tv_sec = conf->opt.ping_timeout; +                        timeout.tv_usec = 0; + +                        conn->ping_timer = +                                gf_timer_call_after (this->ctx, timeout, +                                                     rpc_client_ping_timer_expired, +                                                     (void *) this); +                        if (conn->ping_timer == NULL) +                                gf_log (trans->name, GF_LOG_DEBUG, +                                        "unable to setup timer"); + +                } else { +                        conn->ping_started = 0; +                        conn->ping_timer = NULL; +                        disconnect = 1; +                } +        } +        pthread_mutex_unlock (&conn->lock); + +        if (disconnect) { +                gf_log (trans->name, GF_LOG_ERROR, +                        "Server %s has not responded in the last %d " +                        "seconds, disconnecting.", +                        conn->trans->peerinfo.identifier, +                        conf->opt.ping_timeout); + +                rpc_transport_disconnect (conn->trans); +        } + +out: +        return; +} + + +void +client_start_ping (void *data) +{ +        xlator_t                *this        = NULL; +        clnt_conf_t             *conf        = NULL; +        rpc_clnt_connection_t   *conn        = NULL; +        int32_t                  ret         = -1; +        struct timeval           timeout     = {0, }; +        call_frame_t            *frame       = NULL; +        int                      frame_count = 0; +        rpc_transport_t         *trans       = NULL; + +        this = data; +        conf  = this->private; + +        conn = &conf->rpc->conn; +        trans = conn->trans; + +        if (conf->opt.ping_timeout == 0) +                return; + +        pthread_mutex_lock (&conn->lock); +        { +                if (conn->ping_timer) +                        gf_timer_call_cancel (this->ctx, conn->ping_timer); + +                conn->ping_timer = NULL; +                conn->ping_started = 0; + +                if (conn->saved_frames) +                        /* treat the case where conn->saved_frames is NULL +                           as no pending frames */ +                        frame_count = conn->saved_frames->count; + +                if ((frame_count == 0) || !conn->connected) { +                        /* using goto looked ugly here, +                         * hence getting out this way */ +                        /* unlock */ +                        pthread_mutex_unlock (&conn->lock); +                        return; +                } + +                if (frame_count < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "saved_frames->count is %"PRId64, +                                conn->saved_frames->count); +                        conn->saved_frames->count = 0; +                } + +                timeout.tv_sec = conf->opt.ping_timeout; +                timeout.tv_usec = 0; + +                conn->ping_timer = +                        gf_timer_call_after (this->ctx, timeout, +                                             rpc_client_ping_timer_expired, +                                             (void *) this); + +                if (conn->ping_timer == NULL) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "unable to setup timer"); +                } else { +                        conn->ping_started = 1; +                } +        } +        pthread_mutex_unlock (&conn->lock); + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) +                goto fail; + +        ret = client_submit_request (this, NULL, frame, conf->handshake, +                                     GF_HNDSK_PING, NULL, NULL); + +        return; +fail: + +        if (frame) { +                STACK_DESTROY (frame->root); +        } + +        return; +} + + +int +client_ping_cbk (struct rpc_req *req, struct iovec *iov, int count, +                 void *myframe) +{ +        xlator_t              *this    = NULL; +        rpc_clnt_connection_t *conn    = NULL; +        struct timeval         timeout = {0, }; +        call_frame_t          *frame   = NULL; +        clnt_conf_t           *conf    = NULL; + +        frame = myframe; + +        this = frame->this; +        conf = this->private; +        conn = &conf->rpc->conn; + +        if (req->rpc_status == -1) { +                /* timer expired and transport bailed out */ +                gf_log (this->name, GF_LOG_DEBUG, "timer must have expired"); +                goto out; +        } + +        pthread_mutex_lock (&conn->lock); +        { +                timeout.tv_sec  = conf->opt.ping_timeout; +                timeout.tv_usec = 0; + +                gf_timer_call_cancel (this->ctx, +                                      conn->ping_timer); + +                conn->ping_timer = +                        gf_timer_call_after (this->ctx, timeout, +                                             client_start_ping, (void *)this); + +                if (conn->ping_timer == NULL) +                        gf_log (this->name, GF_LOG_DEBUG, +                                "gf_timer_call_after() returned NULL"); +        } +        pthread_mutex_unlock (&conn->lock); +out: +        STACK_DESTROY (frame->root); +        return 0; +} + + +int +client_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ +        gf_getspec_rsp           rsp   = {0,}; +        call_frame_t            *frame = NULL; +        clnt_conf_t             *conf = NULL; +        int                      ret   = 0; +        char                     spec[(32*1024)] = {0,}; + +        frame = myframe; +        conf  = frame->this->private; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        rsp.spec = spec; +        ret = xdr_to_dump_version_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 == rsp.op_ret) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "failed to get the 'volume file' from server"); +                goto out; +        } + +out: +        /* no _STRICT for mops */ +        STACK_UNWIND_STRICT (getspec, frame, rsp.op_ret, rsp.op_errno, rsp.spec); +        return 0; +} + + +int +client_post_handshake (call_frame_t *frame, xlator_t *this) +{ +        clnt_conf_t            *conf = NULL; +        clnt_fd_ctx_t          *tmp = NULL; +        clnt_fd_ctx_t          *fdctx = NULL; +        xlator_list_t          *parent = NULL; +        struct list_head        reopen_head; + +        if (!this || !this->private) +                goto out; + +        conf = this->private; +        INIT_LIST_HEAD (&reopen_head); + +        pthread_mutex_lock (&conf->lock); +        { +                list_for_each_entry_safe (fdctx, tmp, &conf->saved_fds, +                                          sfd_pos) { +                        if (fdctx->remote_fd != -1) +                                continue; + +                        list_del_init (&fdctx->sfd_pos); +                        list_add_tail (&fdctx->sfd_pos, &reopen_head); +                } +        } +        pthread_mutex_unlock (&conf->lock); + +        list_for_each_entry_safe (fdctx, tmp, &reopen_head, sfd_pos) { +                list_del_init (&fdctx->sfd_pos); + +                if (fdctx->is_dir) +                        protocol_client_reopendir (this, fdctx); +                else +                        protocol_client_reopen (this, fdctx); +        } + +        parent = this->parents; + +        while (parent) { +                xlator_notify (parent->xlator, GF_EVENT_CHILD_UP, +                               this); +                parent = parent->next; +        } + +out: +        return 0; +} + +int +client_setvolume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ +        call_frame_t         *frame         = NULL; +        clnt_conf_t          *conf          = NULL; +        xlator_t             *this          = NULL; +        dict_t               *reply         = NULL; +        xlator_list_t        *parent        = NULL; +        char                 *process_uuid  = NULL; +        char                 *remote_error  = NULL; +        char                 *remote_subvol = NULL; +        rpc_transport_t      *peer_trans    = NULL; +        gf_setvolume_rsp      rsp           = {0,}; +        uint64_t              peertrans_int = 0; +        int                   ret           = 0; +        int                   op_ret        = 0; +        int                   op_errno      = 0; + +        frame = myframe; +        this  = frame->this; +        conf  = this->private; + +        if (-1 == req->rpc_status) { +                op_ret = -1; +                op_errno = EINVAL; +                goto out; +        } + +        ret = xdr_to_setvolume_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                op_errno = EINVAL; +                op_ret = -1; +                goto out; +        } +        op_ret   = rsp.op_ret; +        op_errno = gf_error_to_errno (rsp.op_errno); +        if (-1 == rsp.op_ret) { +                gf_log (frame->this->name, GF_LOG_WARNING, +                        "failed to set the volume"); +        } + +        reply = dict_new (); +        if (!reply) +                goto out; + +        if (rsp.dict.dict_len) { +                ret = dict_unserialize (rsp.dict.dict_val, +                                        rsp.dict.dict_len, &reply); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_DEBUG, +                                "failed to unserialize buffer to dict"); +                        goto out; +                } +        } + +        ret = dict_get_str (reply, "ERROR", &remote_error); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "failed to get ERROR string from reply dict"); +        } + +        ret = dict_get_str (reply, "process-uuid", &process_uuid); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "failed to get 'process-uuid' from reply dict"); +        } + +        if (op_ret < 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "SETVOLUME on remote-host failed: %s", +                        remote_error ? remote_error : strerror (op_errno)); +                errno = op_errno; +                if (op_errno == ESTALE) { +                        parent = this->parents; +                        while (parent) { +                                xlator_notify (parent->xlator, +                                               GF_EVENT_VOLFILE_MODIFIED, +                                               this); +                                parent = parent->next; +                        } +                } +                goto out; +        } +        ret = dict_get_str (this->options, "remote-subvolume", +                            &remote_subvol); +        if (!remote_subvol) +                goto out; + +        if (process_uuid && +            !strcmp (this->ctx->process_uuid, process_uuid)) { +                ret = dict_get_uint64 (reply, "transport-ptr", +                                       &peertrans_int); + +                peer_trans = (void *) (long) (peertrans_int); + +                gf_log (this->name, GF_LOG_WARNING, +                        "attaching to the local volume '%s'", +                        remote_subvol); + +                if (req->conn) { +                        /* TODO: Some issues with this logic at present */ +                        //rpc_transport_setpeer (req->conn->trans, peer_trans); +                } +        } + +        gf_log (this->name, GF_LOG_NORMAL, +                "Connected to %s, attached to remote volume '%s'.", +                conf->rpc->conn.trans->peerinfo.identifier, +                remote_subvol); + +        rpc_clnt_set_connected (&conf->rpc->conn); + +        op_ret = 0; +        conf->connecting = 0; + +        /* TODO: more to test */ +        client_post_handshake (frame, frame->this); + +out: + +        if (-1 == op_ret) { +                /* Let the connection/re-connection happen in +                 * background, for now, don't hang here, +                 * tell the parents that i am all ok.. +                 */ +                parent = this->parents; +                while (parent) { +                        xlator_notify (parent->xlator, +                                       GF_EVENT_CHILD_CONNECTING, this); +                        parent = parent->next; +                } + +                conf->connecting= 1; +        } + +        if (rsp.dict.dict_val) +                free (rsp.dict.dict_val); + +        STACK_DESTROY (frame->root); + +        if (reply) +                dict_unref (reply); + +        return 0; +} + +int +client_setvolume (xlator_t *this, struct rpc_clnt *rpc) +{ +        int               ret             = 0; +        gf_setvolume_req  req             = {0,}; +        call_frame_t     *fr              = NULL; +        char             *process_uuid_xl = NULL; +        clnt_conf_t      *conf            = NULL; +        dict_t           *options         = NULL; + +        options = this->options; +        conf    = this->private; + +        if (conf->fops || !dict_get (options, "fops-version")) { +                ret = dict_set_int32 (options, "fops-version", +                                      conf->fops->prognum); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "failed to set version-fops(%d) in handshake msg", +                                conf->fops->prognum); +                        goto fail; +                } +        } + +        if (conf->mgmt) { +                ret = dict_set_int32 (options, "mgmt-version", conf->mgmt->prognum); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "failed to set version-mgmt(%d) in handshake msg", +                                conf->mgmt->prognum); +                        goto fail; +                } +        } + +        ret = gf_asprintf (&process_uuid_xl, "%s-%s", this->ctx->process_uuid, +                           this->name); +        if (-1 == ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "asprintf failed while setting process_uuid"); +                goto fail; +        } +        ret = dict_set_dynstr (options, "process-uuid", process_uuid_xl); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "failed to set process-uuid(%s) in handshake msg", +                        process_uuid_xl); +                goto fail; +        } + +        if (this->ctx->cmd_args.volfile_server) { +                if (this->ctx->cmd_args.volfile_id) +                        ret = dict_set_str (options, "volfile-key", +                                            this->ctx->cmd_args.volfile_id); +                ret = dict_set_uint32 (options, "volfile-checksum", +                                       this->graph->volfile_checksum); +        } + +        req.dict.dict_len = dict_serialized_length (options); +        if (req.dict.dict_len < 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "failed to get serialized length of dict"); +                ret = -1; +                goto fail; +        } +        req.dict.dict_val = GF_CALLOC (1, req.dict.dict_len, 0); +        ret = dict_serialize (options, req.dict.dict_val); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "failed to serialize dictionary"); +                goto fail; +        } + +        fr  = create_frame (this, this->ctx->pool); +        if (!fr) +                goto fail; + +        ret = client_submit_request (this, &req, fr, conf->handshake, +                                     GF_HNDSK_SETVOLUME, NULL, xdr_from_setvolume_req); + +fail: +        if (req.dict.dict_val) +                GF_FREE (req.dict.dict_val); + +        return ret; +} + +int +select_server_supported_programs (xlator_t *this, char *msg) +{ +        clnt_conf_t *conf        = NULL; +        char        *tmp_str     = NULL; +        char        *prog_str    = NULL; +        char        *dup_str     = NULL; +        char        *tmp_str1    = NULL; +        char        *tmp_msg     = NULL; +        char        *progname    = NULL; +        char        *progver_str = NULL; +        char        *prognum_str = NULL; +        int          ret         = -1; +        int          progver     = 0; +        int          prognum     = 0; + +        if (!this || !msg) +                goto out; + +        conf = this->private; + +        /* Reply in "Name:Program-Number:Program-Version,..." format */ +        tmp_msg = gf_strdup (msg); +        prog_str = strtok_r (tmp_msg, ",", &tmp_str); +        while (prog_str) { +                dup_str = gf_strdup (prog_str); + +                progname = strtok_r (dup_str, ":", &tmp_str1); +                prognum_str = strtok_r (NULL, ":", &tmp_str1); +                if (!prognum_str) { +                        gf_log (this->name, GF_LOG_WARNING, +                                "Supported versions not formatted"); +                        goto out; +                } +                sscanf (prognum_str, "%d", &prognum); +                progver_str = strtok_r (NULL, ":", &tmp_str1); +                if (!progver_str) { +                        gf_log (this->name, GF_LOG_WARNING, +                                "Supported versions not formatted"); +                        goto out; +                } +                sscanf (progver_str, "%d", &progver); + +                /* Select 'programs' */ +                if ((clnt3_1_fop_prog.prognum == prognum) && +                    (clnt3_1_fop_prog.progver == progver)) { +                        conf->fops = &clnt3_1_fop_prog; +                        gf_log (this->name, GF_LOG_INFO, +                                "Using Program %s, Num (%s), Version (%s)", +                                progname, prognum_str, progver_str); +                        ret = 0; +                } +                if ((clnt3_1_mgmt_prog.prognum == prognum) && +                    (clnt3_1_mgmt_prog.progver == progver)) { +                        conf->mgmt = &clnt3_1_mgmt_prog; +                        gf_log (this->name, GF_LOG_INFO, +                                "Using Program %s, Num (%s), Version (%s)", +                                progname, prognum_str, progver_str); +                        ret = 0; +                } + +                prog_str = strtok_r (NULL, ",", &tmp_str); +                GF_FREE (dup_str); +        } + +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "none of the server versions are supported by client"); +        } +        ret = 0; +out: +        if (tmp_msg) +                GF_FREE (tmp_msg); +        return ret; +} + +int +client_dump_version_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) +{ +        gf_dump_version_rsp  rsp   = {0,}; +        call_frame_t            *frame = NULL; +        clnt_conf_t             *conf = NULL; +        int                      ret   = 0; + +        frame = myframe; +        conf  = frame->this->private; + +        if (-1 == req->rpc_status) { +                gf_log ("", 1, "some error, retry again later"); +                goto out; +        } + +        ret = xdr_to_dump_version_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                goto out; +        } +        if (-1 == rsp.op_ret) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "failed to get the 'versions' from server"); +                goto out; +        } + +        /* Check for the proper version string */ +        /* Reply in "Name:Program-Number:Program-Version,..." format */ +        ret = select_server_supported_programs (frame->this, +                                                rsp.msg.msg_val); +        if (ret) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "Server versions are not present in this " +                        "release (%s)", rsp.msg.msg_val); +                goto out; +        } + +        client_setvolume (frame->this, conf->rpc); + +out: +        /* don't use GF_FREE, buffer was allocated by libc */ +        if (rsp.msg.msg_val) { +                free (rsp.msg.msg_val); +        } + +        STACK_DESTROY (frame->root); +        return ret; +} + +int +client_handshake (xlator_t *this, struct rpc_clnt *rpc) +{ +        call_frame_t        *frame = NULL; +        clnt_conf_t         *conf  = NULL; +        gf_dump_version_req  req   = {0,}; +        int                  ret   = 0; + +        conf = this->private; +        if (!conf->handshake) +                goto out; + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) +                goto out; + +        req.key = "fop-handshake"; +        req.gfs_id = 123456; +        ret = client_submit_request (this, &req, frame, conf->handshake, +                                     GF_HNDSK_DUMP_VERSION, +                                     NULL, xdr_from_dump_version_req); + +out: +        return ret; +} + + +/* */ +/* This table should ideally remain same irrespective of versions */ +static rpc_clnt_procedure_t clnt_handshake_actors[] = { +        [GF_HNDSK_NULL]         = { "NULL", NULL, NULL}, +        [GF_HNDSK_DUMP_VERSION] = { "VERSION", NULL, client_dump_version_cbk}, +        [GF_HNDSK_SETVOLUME]    = { "SETVOLUME", NULL,  client_setvolume_cbk}, +        [GF_HNDSK_GETSPEC]      = { "GETSPEC", NULL, client_getspec_cbk }, +        [GF_HNDSK_PING]         = { "PING", NULL, client_ping_cbk }, +}; + +rpc_clnt_prog_t clnt_handshake_prog = { +        .progname = "GlusterFS Handshake", +        .prognum  = GLUSTER_HNDSK_PROGRAM, +        .progver  = GLUSTER_HNDSK_VERSION, +        .actor    = clnt_handshake_actors, +        .numproc  = (sizeof (*clnt_handshake_actors) / +                     sizeof (rpc_clnt_procedure_t)), +}; diff --git a/xlators/protocol/client/src/client-helpers.c b/xlators/protocol/client/src/client-helpers.c new file mode 100644 index 00000000000..ae091ed1d8d --- /dev/null +++ b/xlators/protocol/client/src/client-helpers.c @@ -0,0 +1,109 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "fd.h" + + +clnt_fd_ctx_t * +this_fd_del_ctx (fd_t *file, xlator_t *this) +{ +        int         dict_ret = -1; +        uint64_t    ctxaddr  = 0; + +        GF_VALIDATE_OR_GOTO ("client", this, out); +        GF_VALIDATE_OR_GOTO (this->name, file, out); + +        dict_ret = fd_ctx_del (file, this, &ctxaddr); + +        if (dict_ret < 0) { +                ctxaddr = 0; +        } + +out: +        return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; +} + + +clnt_fd_ctx_t * +this_fd_get_ctx (fd_t *file, xlator_t *this) +{ +        int         dict_ret = -1; +        uint64_t    ctxaddr = 0; + +        GF_VALIDATE_OR_GOTO ("client", this, out); +        GF_VALIDATE_OR_GOTO (this->name, file, out); + +        dict_ret = fd_ctx_get (file, this, &ctxaddr); + +        if (dict_ret < 0) { +                ctxaddr = 0; +        } + +out: +        return (clnt_fd_ctx_t *)(unsigned long)ctxaddr; +} + + +void +this_fd_set_ctx (fd_t *file, xlator_t *this, loc_t *loc, clnt_fd_ctx_t *ctx) +{ +        uint64_t oldaddr = 0; +        int32_t  ret = -1; + +        GF_VALIDATE_OR_GOTO ("client", this, out); +        GF_VALIDATE_OR_GOTO (this->name, file, out); + +        ret = fd_ctx_get (file, this, &oldaddr); +        if (ret >= 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "%s (%"PRId64"): trying duplicate remote fd set. ", +                        loc->path, loc->inode->ino); +        } + +        ret = fd_ctx_set (file, this, (uint64_t)(unsigned long)ctx); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "%s (%"PRId64"): failed to set remote fd", +                        loc->path, loc->inode->ino); +        } +out: +        return; +} + + +int +client_local_wipe (clnt_local_t *local) +{ +        if (local) { +                loc_wipe (&local->loc); + +                if (local->fd) +                        fd_unref (local->fd); + +                 GF_FREE (local); +        } + +        return 0; +} diff --git a/xlators/protocol/client/src/client-mem-types.h b/xlators/protocol/client/src/client-mem-types.h new file mode 100644 index 00000000000..5fadfafc9e1 --- /dev/null +++ b/xlators/protocol/client/src/client-mem-types.h @@ -0,0 +1,32 @@ +/* +   Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +   This file is part of GlusterFS. + +   GlusterFS is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published +   by the Free Software Foundation; either version 3 of the License, +   or (at your option) any later version. + +   GlusterFS is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see +   <http://www.gnu.org/licenses/>. +*/ + + +#ifndef __CLIENT_MEM_TYPES_H__ +#define __CLIENT_MEM_TYPES_H__ + +#include "mem-types.h" + +enum gf_client_mem_types_ { +        gf_client_mt_clnt_conf_t = gf_common_mt_end + 1, +        gf_client_mt_clnt_local_t, +        gf_client_mt_clnt_fdctx_t, +        gf_client_mt_end, +}; +#endif /* __CLIENT_MEM_TYPES_H__ */ diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c new file mode 100644 index 00000000000..49e88bfdea3 --- /dev/null +++ b/xlators/protocol/client/src/client.c @@ -0,0 +1,1791 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "xlator.h" +#include "defaults.h" +#include "glusterfs.h" +#include "msg-xdr.h" +#include "statedump.h" +#include "compat-errno.h" + +extern rpc_clnt_prog_t clnt_handshake_prog; +int +client_handshake (xlator_t *this, struct rpc_clnt *rpc); + +void +client_start_ping (void *data); + +int +client_submit_request (xlator_t *this, void *req, +                       call_frame_t *frame, rpc_clnt_prog_t *prog, int procnum, +                       struct iobref *iobref, gfs_serialize_t sfunc) +{ +        int          ret         = -1; +        clnt_conf_t *conf        = NULL; +        struct iovec iov         = {0, }; +        struct iobuf *iobuf      = NULL; +        int           count      = 0; +        char          new_iobref = 0, start_ping = 0; + +        conf = this->private; + +        iobuf = iobuf_get (this->ctx->iobuf_pool); +        if (!iobuf) { +                goto out; +        }; + +        if (!iobref) { +                iobref = iobref_new (); +                if (!iobref) { +                        goto out; +                } + +                new_iobref = 1; +        } + +        iobref_add (iobref, iobuf); + +        iov.iov_base = iobuf->ptr; +        iov.iov_len  = 128 * GF_UNIT_KB; + +        /* Create the xdr payload */ +        if (req && sfunc) { +                ret = sfunc (iov, req); +                if (ret == -1) { +                        goto out; +                } +                iov.iov_len = ret; +                count = 1; +        } +        /* Send the msg */ +        ret = rpc_clnt_submit (conf->rpc, prog, procnum, &iov, count, NULL, 0, +                               iobref, frame); + +        if (ret == 0) { +                pthread_mutex_lock (&conf->rpc->conn.lock); +                { +                        if (!conf->rpc->conn.ping_started) { +                                start_ping = 1; +                        } +                } +                pthread_mutex_unlock (&conf->rpc->conn.lock); +        } + +        if (start_ping) +                client_start_ping ((void *) this); + +        ret = 0; +out: +        if (new_iobref) { +                iobref_unref (iobref); +        } + +        iobuf_unref (iobuf); + +        return ret; +} + + +int32_t +client_forget (xlator_t *this, inode_t *inode) +{ +        /* Nothing here */ +	return 0; +} + +int32_t +client_releasedir (xlator_t *this, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; +        call_frame_t *frame = NULL; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; + +        proc = &conf->fops->actor[GF_FOP_RELEASEDIR]; +        if (proc->fn) { +                frame = create_frame (this, this->ctx->pool); +                if (!frame) { +                        goto out; +                } +                ret = proc->fn (frame, this, conf->fops, &args); +        } +out: +	return 0; +} + +int32_t +client_release (xlator_t *this, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; +        call_frame_t *frame = NULL; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        proc = &conf->fops->actor[GF_FOP_RELEASE]; +        if (proc->fn) { +                frame = create_frame (this, this->ctx->pool); +                if (!frame) { +                        goto out; +                } +                ret = proc->fn (frame, this, conf->fops, &args); +        } +out: +	return 0; +} + + +int32_t +client_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, +               dict_t *xattr_req) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.dict = xattr_req; + +        proc = &conf->fops->actor[GF_FOP_LOOKUP]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        /* think of avoiding a missing frame */ +        if (ret) +                STACK_UNWIND_STRICT (lookup, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL); + +	return 0; +} + + +int32_t +client_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; + +        proc = &conf->fops->actor[GF_FOP_STAT]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (stat, frame, -1, ENOTCONN, NULL); + + +	return 0; +} + + +int32_t +client_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc    = loc; +        args.offset = offset; + +        proc = &conf->fops->actor[GF_FOP_TRUNCATE]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (truncate, frame, -1, ENOTCONN, NULL, NULL); + + +	return 0; +} + + +int32_t +client_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd     = fd; +        args.offset = offset; + +        proc = &conf->fops->actor[GF_FOP_FTRUNCATE]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + + + +int32_t +client_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc  = loc; +        args.mask = mask; + +        proc = &conf->fops->actor[GF_FOP_ACCESS]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (access, frame, -1, ENOTCONN); + +	return 0; +} + + + + +int32_t +client_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc  = loc; +        args.size = size; + +        proc = &conf->fops->actor[GF_FOP_READLINK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (readlink, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + + + +int32_t +client_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, +              dev_t rdev) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc  = loc; +        args.mode = mode; +        args.rdev = rdev; + +        proc = &conf->fops->actor[GF_FOP_MKNOD]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (mknod, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, +              mode_t mode) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.mode = mode; + +        proc = &conf->fops->actor[GF_FOP_MKDIR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (mkdir, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; + +        proc = &conf->fops->actor[GF_FOP_UNLINK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (unlink, frame, -1, ENOTCONN, +                                     NULL, NULL); + +	return 0; +} + +int32_t +client_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; + +        proc = &conf->fops->actor[GF_FOP_RMDIR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        /* think of avoiding a missing frame */ +        if (ret) +                STACK_UNWIND_STRICT (rmdir, frame, -1, ENOTCONN, +                                     NULL, NULL); + +	return 0; +} + + + +int32_t +client_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, +                loc_t *loc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.linkname = linkpath; +        args.loc      = loc; + +        proc = &conf->fops->actor[GF_FOP_SYMLINK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (symlink, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, +               loc_t *newloc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.oldloc = oldloc; +        args.newloc = newloc; +        proc = &conf->fops->actor[GF_FOP_RENAME]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (rename, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, +             loc_t *newloc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.oldloc = oldloc; +        args.newloc = newloc; + +        proc = &conf->fops->actor[GF_FOP_LINK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (link, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_create (call_frame_t *frame, xlator_t *this, loc_t *loc, +               int32_t flags, mode_t mode, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.flags = flags; +        args.mode = mode; +        args.fd = fd; + +        proc = &conf->fops->actor[GF_FOP_CREATE]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (create, frame, -1, ENOTCONN, +                                     NULL, NULL, NULL, NULL, NULL); + +	return 0; +} + + + +int32_t +client_open (call_frame_t *frame, xlator_t *this, loc_t *loc, +             int32_t flags, fd_t *fd, int32_t wbflags) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.flags = flags; +        args.fd = fd; +        args.wbflags = wbflags; + +        proc = &conf->fops->actor[GF_FOP_OPEN]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); + +out: +        if (ret) +                STACK_UNWIND_STRICT (open, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, +              off_t offset) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd     = fd; +        args.size   = size; +        args.offset = offset; + +        proc = &conf->fops->actor[GF_FOP_READ]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); + +out: +        if (ret) +                STACK_UNWIND_STRICT (readv, frame, -1, ENOTCONN, +                                     NULL, 0, NULL, NULL); + +	return 0; +} + + + + +int32_t +client_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, +               struct iovec *vector, int32_t count, off_t off, +               struct iobref *iobref) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd     = fd; +        args.vector = vector; +        args.count  = count; +        args.offset = off; +        args.iobref = iobref; + +        proc = &conf->fops->actor[GF_FOP_WRITE]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (writev, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + + + +int32_t +client_flush (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; + +        proc = &conf->fops->actor[GF_FOP_FLUSH]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (flush, frame, -1, ENOTCONN); + +	return 0; +} + + + +int32_t +client_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, +              int32_t flags) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd    = fd; +        args.flags = flags; + +        proc = &conf->fops->actor[GF_FOP_FSYNC]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fsync, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + + + +int32_t +client_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; + +        proc = &conf->fops->actor[GF_FOP_FSTAT]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fstat, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.fd  = fd; + +        proc = &conf->fops->actor[GF_FOP_OPENDIR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (opendir, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd    = fd; +        args.flags = flags; + +        proc = &conf->fops->actor[GF_FOP_FSYNCDIR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fsyncdir, frame, -1, ENOTCONN); + +	return 0; +} + + + +int32_t +client_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; + +        proc = &conf->fops->actor[GF_FOP_STATFS]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (statfs, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +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,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc   = loc; +        args.dict  = dict; +        args.flags = flags; + +        proc = &conf->fops->actor[GF_FOP_SETXATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (setxattr, frame, -1, ENOTCONN); + +	return 0; +} + + + +int32_t +client_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                  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,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.dict = dict; +        args.flags = flags; + +        proc = &conf->fops->actor[GF_FOP_FSETXATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOTCONN); + +	return 0; +} + + + + +int32_t +client_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                  const char *name) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.name = name; + +        proc = &conf->fops->actor[GF_FOP_FGETXATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fgetxattr, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                 const char *name) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.name = name; +        args.loc  = loc; + +        proc = &conf->fops->actor[GF_FOP_GETXATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (getxattr, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, +                gf_xattrop_flags_t flags, dict_t *dict) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.flags = flags; +        args.dict = dict; + +        proc = &conf->fops->actor[GF_FOP_XATTROP]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (xattrop, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, +                 gf_xattrop_flags_t flags, dict_t *dict) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.flags = flags; +        args.dict = dict; + +        proc = &conf->fops->actor[GF_FOP_FXATTROP]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fxattrop, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + + +int32_t +client_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                    const char *name) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.name = name; +        args.loc  = loc; + +        proc = &conf->fops->actor[GF_FOP_REMOVEXATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (removexattr, frame, -1, ENOTCONN); + +	return 0; +} + + +int32_t +client_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, +           struct flock *lock) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd    = fd; +        args.cmd   = cmd; +        args.flock = lock; + +        proc = &conf->fops->actor[GF_FOP_LK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (lk, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + +int32_t +client_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, +                loc_t *loc, int32_t cmd, struct flock *lock) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc    = loc; +        args.cmd    = cmd; +        args.flock  = lock; +        args.volume = volume; + +        proc = &conf->fops->actor[GF_FOP_INODELK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (inodelk, frame, -1, ENOTCONN); + +	return 0; +} + + + +int32_t +client_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, +                 fd_t *fd, int32_t cmd, struct flock *lock) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd     = fd; +        args.cmd    = cmd; +        args.flock  = lock; +        args.volume = volume; + +        proc = &conf->fops->actor[GF_FOP_FINODELK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (finodelk, frame, -1, ENOTCONN); + +	return 0; +} + + +int32_t +client_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, +                loc_t *loc, const char *basename, entrylk_cmd cmd, +                entrylk_type type) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc          = loc; +        args.basename     = basename; +        args.type         = type; +        args.volume       = volume; +        args.cmd_entrylk  = cmd; + +        proc = &conf->fops->actor[GF_FOP_ENTRYLK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (entrylk, frame, -1, ENOTCONN); + +	return 0; +} + + + +int32_t +client_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, +                 fd_t *fd, const char *basename, entrylk_cmd cmd, +                 entrylk_type type) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd           = fd; +        args.basename     = basename; +        args.type         = type; +        args.volume       = volume; +        args.cmd_entrylk  = cmd; + +        proc = &conf->fops->actor[GF_FOP_FENTRYLK]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fentrylk, frame, -1, ENOTCONN); + +	return 0; +} + + +int32_t +client_checksum (call_frame_t *frame, xlator_t *this, loc_t *loc, +                 int32_t flag) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.flags = flag; + +        proc = &conf->fops->actor[GF_FOP_CHECKSUM]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (checksum, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + + + +int32_t +client_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, +                  int32_t len) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.offset = offset; +        args.len = len; + +        proc = &conf->fops->actor[GF_FOP_RCHECKSUM]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (rchecksum, frame, -1, ENOTCONN, 0, NULL); + +	return 0; +} + +int32_t +client_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, +                size_t size, off_t off) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.size = size; +        args.offset = off; + +        proc = &conf->fops->actor[GF_FOP_READDIR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (readdir, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + +int32_t +client_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, +                 size_t size, off_t off) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.size = size; +        args.offset = off; + +        proc = &conf->fops->actor[GF_FOP_READDIRP]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (readdirp, frame, -1, ENOTCONN, NULL); + +	return 0; +} + + +int32_t +client_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                struct iatt *stbuf, int32_t valid) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.loc = loc; +        args.stbuf = stbuf; +        args.valid = valid; + +        proc = &conf->fops->actor[GF_FOP_SETATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (setattr, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + +int32_t +client_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                 struct iatt *stbuf, int32_t valid) +{ +        int          ret  = -1; +        clnt_conf_t *conf = NULL; +        rpc_clnt_procedure_t *proc = NULL; +        clnt_args_t  args = {0,}; + +        conf = this->private; +        if (!conf->fops) +                goto out; + +        args.fd = fd; +        args.stbuf = stbuf; +        args.valid = valid; + +        proc = &conf->fops->actor[GF_FOP_FSETATTR]; +        if (proc->fn) +                ret = proc->fn (frame, this, conf->fops, &args); +out: +        if (ret) +                STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOTCONN, NULL, NULL); + +	return 0; +} + +///////////////// +int32_t +client_getspec (call_frame_t *frame, xlator_t *this, const char *key, +                int32_t flags) +{ +        int                 ret  = -1; +        clnt_conf_t        *conf = NULL; +        gf_getspec_req      req  = {0,}; + +        conf = this->private; +        if (!conf->handshake) +                goto out; + +        req.key   = (char *)key; +        req.flags = flags; + +        client_submit_request (this, &req, frame, conf->handshake, +                               GF_HNDSK_GETSPEC, NULL, xdr_from_getspec_req); +        ret = 0; +out: +        if (ret) +                STACK_UNWIND_STRICT (getspec, frame, -1, EINVAL, NULL); + +	return 0; +} + + + int +client_mark_fd_bad (xlator_t *this) +{ +        clnt_conf_t            *conf = NULL; +        clnt_fd_ctx_t          *tmp = NULL, *fdctx = NULL; + +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                list_for_each_entry_safe (fdctx, tmp, &conf->saved_fds, +                                          sfd_pos) { +                        fdctx->remote_fd = -1; +                } +        } +        pthread_mutex_unlock (&conf->lock); + +        return 0; +} + + +int +client_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, +                   void *data) +{ +        xlator_t *this = NULL; +        char *handshake = NULL; +        clnt_conf_t  *conf = NULL; +        int ret = 0; + +        this = mydata; +        conf = this->private; + +        switch (event) { +        case RPC_CLNT_CONNECT: +        { +                // connect happened, send 'get_supported_versions' mop +                ret = dict_get_str (this->options, "disable-handshake", +                                    &handshake); + +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); + +                if ((ret < 0) || (strcasecmp (handshake, "on"))) { +                        ret = client_handshake (this, conf->rpc); + +                } else { +                        //conf->rpc->connected = 1; +                        ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); +                } +                break; +        } +        case RPC_CLNT_DISCONNECT: + +                client_mark_fd_bad (this); + +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); + +                default_notify (this, GF_EVENT_CHILD_DOWN, NULL); +                break; + +        default: +                gf_log (this->name, GF_LOG_TRACE, +                        "got some other RPC event %d", event); + +                break; +        } + +        return 0; +} + + +int +notify (xlator_t *this, int32_t event, void *data, ...) +{ +        clnt_conf_t *conf  = NULL; +        void        *trans = NULL; + +        conf = this->private; + +        switch (event) { +        case GF_EVENT_PARENT_UP: +        { +                if (conf->rpc) +                        trans = conf->rpc->conn.trans; + +                if (!trans) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "transport init failed"); +                        return 0; +                } + +                gf_log (this->name, GF_LOG_DEBUG, +                        "got GF_EVENT_PARENT_UP, attempting connect " +                        "on transport"); + +                rpc_clnt_reconnect (trans); +        } +        break; + +        default: +                gf_log (this->name, GF_LOG_DEBUG, +                        "got %d, calling default_notify ()", event); + +                default_notify (this, event, data); +                break; +        } + +        return 0; +} + +int +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) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "setting frame-timeout to %d", +                        conf->rpc_conf.rpc_timeout); +        } else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "defaulting frame-timeout to 30mins"); +                conf->rpc_conf.rpc_timeout = 1800; +        } + +        ret = dict_get_int32 (this->options, "remote-port", +                              &conf->rpc_conf.remote_port); +        if (ret >= 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "remote-port is %d", conf->rpc_conf.remote_port); +        } else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "defaulting remote-port to %d", +                        GF_PROTOCOL_DEFAULT_PORT); +                conf->rpc_conf.remote_port = GF_PROTOCOL_DEFAULT_PORT; +        } + +        ret = dict_get_int32 (this->options, "ping-timeout", +                              &conf->opt.ping_timeout); +        if (ret >= 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "setting ping-timeout to %d", conf->opt.ping_timeout); +        } else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "defaulting ping-timeout to 42"); +                conf->opt.ping_timeout = GF_UNIVERSAL_ANSWER; +        } + +        ret = 0; +out: +        return ret;} + + +static int32_t +mem_acct_init (xlator_t *this) +{ +        int     ret = -1; + +        if (!this) +                return ret; + +        ret = xlator_mem_acct_init (this, gf_client_mt_end + 1); + +        if (ret != 0) { +                gf_log (this->name, GF_LOG_ERROR, "Memory accounting init" +                                "failed"); +                return ret; +        } + +        return ret; +} + + +int +init (xlator_t *this) +{ +        int          ret = -1; +        clnt_conf_t *conf = NULL; + +        /* */ +        if (this->children) { +                gf_log (this->name, GF_LOG_ERROR, +                        "FATAL: client protocol translator cannot have any " +                        "subvolumes"); +                goto out; +        } + +        if (!this->parents) { +                gf_log (this->name, GF_LOG_WARNING, +                        "Volume is dangling. "); +        } + +        ret = mem_acct_init (this); +        if (ret) +                goto out; + +        conf = GF_CALLOC (1, sizeof (*conf), gf_client_mt_clnt_conf_t); +        if (!conf) +                goto out; + +        pthread_mutex_init (&conf->lock, NULL); +        INIT_LIST_HEAD (&conf->saved_fds); + +        ret = build_client_config (this, conf); +        if (ret) +                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) +                goto out; + +        conf->handshake = &clnt_handshake_prog; +        this->private = conf; + +        ret = 0; +out: +        if (ret) +                this->fini (this); + +        return ret; +} + +void +fini (xlator_t *this) +{ +        clnt_conf_t *conf = NULL; + +        conf = this->private; +        this->private = NULL; + +        if (conf) { +                if (conf->rpc) +                        rpc_clnt_destroy (conf->rpc); + +                /* Saved Fds */ +                /* TODO: */ + +                pthread_mutex_destroy (&conf->lock); + +                GF_FREE (conf); +        } +        return; +} + +int +client_priv_dump (xlator_t *this) +{ +        clnt_conf_t    *conf = NULL; +        int             ret   = -1; +        clnt_fd_ctx_t  *tmp = NULL; +        int             i = 0; +        char            key[GF_DUMP_MAX_BUF_LEN]; +        char            key_prefix[GF_DUMP_MAX_BUF_LEN]; + +        if (!this) +                return -1; + +        conf = this->private; +        if (!conf) { +                gf_log (this->name, GF_LOG_WARNING, +                        "conf null in xlator"); +                return -1; +        } + +        ret = pthread_mutex_trylock(&conf->lock); +        if (ret) { +                gf_log("", GF_LOG_WARNING, "Unable to lock client %s" +                       " errno: %d", this->name, errno); +                return -1; +        } + +        gf_proc_dump_build_key(key_prefix, "xlator.protocol.client", +                               "%s.priv", this->name); + +        gf_proc_dump_add_section(key_prefix); + +        list_for_each_entry(tmp, &conf->saved_fds, sfd_pos) { +                gf_proc_dump_build_key(key, key_prefix, +                                       "fd.%d.remote_fd", ++i); +                gf_proc_dump_write(key, "%d", tmp->remote_fd); +        } + +        gf_proc_dump_build_key(key, key_prefix, "connecting"); +        gf_proc_dump_write(key, "%d", conf->connecting); +        gf_proc_dump_build_key(key, key_prefix, "last_sent"); +        gf_proc_dump_write(key, "%s", ctime(&conf->last_sent.tv_sec)); +        gf_proc_dump_build_key(key, key_prefix, "last_received"); +        gf_proc_dump_write(key, "%s", ctime(&conf->last_received.tv_sec)); + +        pthread_mutex_unlock(&conf->lock); + +        return 0; + +} + +int32_t +client_inodectx_dump (xlator_t *this, inode_t *inode) +{ +        ino_t    par = 0; +        uint64_t gen = 0; +        int      ret = -1; +        char     key[GF_DUMP_MAX_BUF_LEN]; + +        if (!inode) +                return -1; + +        if (!this) +                return -1; + +        ret = inode_ctx_get2 (inode, this, &par, &gen); + +        if (ret != 0) +                return ret; + +        gf_proc_dump_build_key(key, "xlator.protocol.client", +                               "%s.inode.%ld.par", +                               this->name,inode->ino); +        gf_proc_dump_write(key, "%ld, %ld", par, gen); + +        return 0; +} + + + + +struct xlator_cbks cbks = { +        .forget     = client_forget, +        .release    = client_release, +        .releasedir = client_releasedir +}; + +struct xlator_fops fops = { +        .stat        = client_stat, +        .readlink    = client_readlink, +        .mknod       = client_mknod, +        .mkdir       = client_mkdir, +        .unlink      = client_unlink, +        .rmdir       = client_rmdir, +        .symlink     = client_symlink, +        .rename      = client_rename, +        .link        = client_link, +        .truncate    = client_truncate, +        .open        = client_open, +        .readv       = client_readv, +        .writev      = client_writev, +        .statfs      = client_statfs, +        .flush       = client_flush, +        .fsync       = client_fsync, +        .setxattr    = client_setxattr, +        .getxattr    = client_getxattr, +        .fsetxattr   = client_fsetxattr, +        .fgetxattr   = client_fgetxattr, +        .removexattr = client_removexattr, +        .opendir     = client_opendir, +        .readdir     = client_readdir, +        .readdirp    = client_readdirp, +        .fsyncdir    = client_fsyncdir, +        .access      = client_access, +        .ftruncate   = client_ftruncate, +        .fstat       = client_fstat, +        .create      = client_create, +        .lk          = client_lk, +        .inodelk     = client_inodelk, +        .finodelk    = client_finodelk, +        .entrylk     = client_entrylk, +        .fentrylk    = client_fentrylk, +        .lookup      = client_lookup, +        .checksum    = client_checksum, +        .rchecksum   = client_rchecksum, +        .xattrop     = client_xattrop, +        .fxattrop    = client_fxattrop, +        .setattr     = client_setattr, +        .fsetattr    = client_fsetattr, +        .getspec     = client_getspec, +}; + + +struct xlator_dumpops dumpops = { +        .priv      =  client_priv_dump, +        .inodectx  =  client_inodectx_dump, +}; + + +struct volume_options options[] = { +        { .key   = {"username"}, +          .type  = GF_OPTION_TYPE_ANY +        }, +        { .key   = {"password"}, +          .type  = GF_OPTION_TYPE_ANY +        }, +        { .key   = {"transport-type"}, +          .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp", +                    "tcp/client", "ib-verbs/client"}, +          .type  = GF_OPTION_TYPE_STR +        }, +        { .key   = {"remote-host"}, +          .type  = GF_OPTION_TYPE_INTERNET_ADDRESS +        }, +        { .key   = {"remote-subvolume"}, +          .type  = GF_OPTION_TYPE_ANY +        }, +        { .key   = {"frame-timeout", +                    "rpc-timeout" }, +          .type  = GF_OPTION_TYPE_TIME, +          .min   = 0, +          .max   = 86400, +        }, +        { .key   = {"ping-timeout"}, +          .type  = GF_OPTION_TYPE_TIME, +          .min   = 1, +          .max   = 1013, +        }, +        { .key   = {NULL} }, +}; diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h new file mode 100644 index 00000000000..9d713bed204 --- /dev/null +++ b/xlators/protocol/client/src/client.h @@ -0,0 +1,125 @@ +/* +   Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +   This file is part of GlusterFS. + +   GlusterFS is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published +   by the Free Software Foundation; either version 3 of the License, +   or (at your option) any later version. + +   GlusterFS is distributed in the hope that it will be useful, but +   WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see +   <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CLIENT_H +#define _CLIENT_H + +#include <pthread.h> +#include <stdint.h> + +#include "rpc-clnt.h" +#include "list.h" +#include "inode.h" +#include "client-mem-types.h" +#include "protocol-common.h" + +struct clnt_options { +        char *remote_subvolume; +        int   ping_timeout; +}; + +typedef struct clnt_conf { +        struct rpc_clnt       *rpc; +        struct clnt_options    opt; +        struct rpc_clnt_config rpc_conf; +	struct list_head       saved_fds; +        pthread_mutex_t        lock; +        int                    connecting; +	struct timeval         last_sent; +	struct timeval         last_received; + +        rpc_clnt_prog_t       *fops; +        rpc_clnt_prog_t       *mgmt; +        rpc_clnt_prog_t       *handshake; +} clnt_conf_t; + +typedef struct _client_fd_ctx { +        struct list_head  sfd_pos;      /*  Stores the reference to this +                                            fd's position in the saved_fds list. +                                        */ +        int64_t           remote_fd; +        inode_t          *inode; +        uint64_t          ino; +        uint64_t          gen; +        char              is_dir; +        char              released; +        int32_t           flags; +        int32_t           wbflags; +} clnt_fd_ctx_t; + +typedef struct client_local { +        loc_t              loc; +        loc_t              loc2; +        fd_t              *fd; +        clnt_fd_ctx_t     *fdctx; +        uint32_t           flags; +        uint32_t           wbflags; +        fop_cbk_fn_t       op; +} clnt_local_t; + +typedef struct client_args { +        loc_t              *loc; +        fd_t               *fd; +        dict_t             *xattr_req; +        const char         *linkname; +        struct iobref      *iobref; +        struct iovec       *vector; +        dict_t             *xattr; +        struct iatt        *stbuf; +        dict_t             *dict; +        loc_t              *oldloc; +        loc_t              *newloc; +        const char         *name; +        struct flock       *flock; +        const char         *volume; +        const char         *basename; +        off_t               offset; +        int32_t             mask; +        int32_t             cmd; +        size_t              size; +        mode_t              mode; +        dev_t               rdev; +        int32_t             flags; +        int32_t             wbflags; +        int32_t             count; +        int32_t             datasync; +        entrylk_cmd         cmd_entrylk; +        entrylk_type        type; +        gf_xattrop_flags_t  optype; +        int32_t             valid; +        int32_t             len; +} clnt_args_t; + +typedef ssize_t (*gfs_serialize_t) (struct iovec outmsg, void *args); + +clnt_fd_ctx_t *this_fd_get_ctx (fd_t *file, xlator_t *this); +clnt_fd_ctx_t *this_fd_del_ctx (fd_t *file, xlator_t *this); +void this_fd_set_ctx (fd_t *file, xlator_t *this, loc_t *loc, +                      clnt_fd_ctx_t *ctx); + +int client_local_wipe (clnt_local_t *local); +int client_submit_request (xlator_t *this, void *req, +                           call_frame_t *frame, rpc_clnt_prog_t *prog, +                           int procnum, struct iobref *iobref, +                           gfs_serialize_t sfunc); + +int protocol_client_reopendir (xlator_t *this, clnt_fd_ctx_t *fdctx); +int protocol_client_reopen (xlator_t *this, clnt_fd_ctx_t *fdctx); + +#endif /* !_CLIENT_H */ diff --git a/xlators/protocol/client/src/client3_1-fops.c b/xlators/protocol/client/src/client3_1-fops.c new file mode 100644 index 00000000000..01b78436c6c --- /dev/null +++ b/xlators/protocol/client/src/client3_1-fops.c @@ -0,0 +1,4662 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "client.h" +#include "glusterfs-xdr.h" +#include "msg-xdr.h" +#include "compat-errno.h" + +void client_start_ping (void *data); +rpc_clnt_prog_t clnt3_1_fop_prog; + +int +client_submit_vec_request (xlator_t      *this, void *req, +                           call_frame_t  *frame, rpc_clnt_prog_t *prog, int procnum, +                           struct iovec  *payload, int payloadcnt, +                           struct iobref *iobref, gfs_serialize_t sfunc) +{ +        int           ret        = 0; +        clnt_conf_t  *conf       = NULL; +        struct iovec  iov        = {0, }; +        struct iobuf *iobuf      = NULL; +        int           count      = 0; +        char          new_iobref = 0; +        int           start_ping = 0; + +        start_ping = 0; + +        conf = this->private; + +        iobuf = iobuf_get (this->ctx->iobuf_pool); +        if (!iobuf) { +                goto out; +        }; + +        if (!iobref) { +                iobref = iobref_new (); +                if (!iobref) { +                        goto out; +                } + +                new_iobref = 1; +        } + +        iobref_add (iobref, iobuf); + +        iov.iov_base = iobuf->ptr; +        iov.iov_len  = 128 * GF_UNIT_KB; + +        /* Create the xdr payload */ +        if (req && sfunc) { +                ret = sfunc (iov, req); +                if (ret == -1) { +                        goto out; +                } +                iov.iov_len = ret; +                count = 1; +        } +        /* Send the msg */ +        ret = rpc_clnt_submit (conf->rpc, prog, procnum, &iov, count, +                               payload, payloadcnt, iobref, frame); + +        if (ret == 0) { +                pthread_mutex_lock (&conf->rpc->conn.lock); +                { +                        if (!conf->rpc->conn.ping_started) { +                                start_ping = 1; +                        } +                } +                pthread_mutex_unlock (&conf->rpc->conn.lock); +        } + +        if (start_ping) +                client_start_ping ((void *) this); + +out: +        if (new_iobref) { +                iobref_unref (iobref); +        } + +        iobuf_unref (iobuf); + +        return 0; +} + +int +client_fdctx_destroy (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ +        call_frame_t *fr = NULL; +        int32_t       ret = -1; + +        if (!fdctx) +                goto out; + +        if (fdctx->remote_fd == -1) +                goto out; + +        fr = create_frame (this, this->ctx->pool); + +        if (fdctx->is_dir) { +                gfs3_releasedir_req  req = {0,}; +                req.fd = fdctx->remote_fd; +                client_submit_request (this, &req, fr, &clnt3_1_fop_prog, +                                       GFS3_OP_RELEASEDIR, NULL, +                                       xdr_from_releasedir_req); +        } else { +                gfs3_release_req  req = {0,}; +                req.fd = fdctx->remote_fd; +                client_submit_request (this, &req, fr, &clnt3_1_fop_prog, +                                       GFS3_OP_RELEASE, NULL, +                                       xdr_from_release_req); +        } + +out: +        fdctx->remote_fd = -1; +        inode_unref (fdctx->inode); +        GF_FREE (fdctx); + +        return ret; +} + +int +client3_1_reopen_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void           *myframe) +{ +        int32_t        ret = -1; +        gfs3_open_rsp  rsp = {0,}; +        clnt_local_t  *local = NULL; +        clnt_conf_t   *conf = NULL; +        clnt_fd_ctx_t *fdctx = NULL; +        call_frame_t  *frame = NULL; + +        frame = myframe; + +        local = frame->local; +        conf  = frame->this->private; +        fdctx = local->fdctx; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_open_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        gf_log (frame->this->name, GF_LOG_DEBUG, +                "reopen on %s returned %d (%"PRId64")", +                local->loc.path, rsp.op_ret, rsp.fd); + +        if (-1 != rsp.op_ret) { +                pthread_mutex_lock (&conf->lock); +                { +                        fdctx->remote_fd = rsp.fd; + +                        if (!fdctx->released) { +                                list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); +                                fdctx = NULL; +                        } +                } +                pthread_mutex_unlock (&conf->lock); +        } + +out: +        if (fdctx) +                client_fdctx_destroy (frame->this, fdctx); + +        frame->local = NULL; +        STACK_DESTROY (frame->root); + +        client_local_wipe (local); + +        return 0; +} + +int +client3_1_reopendir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                         void           *myframe) +{ +        int32_t        ret   = -1; +        gfs3_open_rsp  rsp   = {0,}; +        clnt_local_t  *local = NULL; +        clnt_conf_t   *conf  = NULL; +        clnt_fd_ctx_t *fdctx = NULL; +        call_frame_t  *frame = NULL; + +        frame = myframe; +        if (!frame || !frame->this) +                goto out; + +        local        = frame->local; +        frame->local = NULL; +        conf         = frame->this->private; +        fdctx        = local->fdctx; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_opendir_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        gf_log (frame->this->name, GF_LOG_DEBUG, +                "reopendir on %s returned %d (%"PRId64")", +                local->loc.path, rsp.op_ret, rsp.fd); + +        if (fdctx) { +                pthread_mutex_lock (&conf->lock); +                { +                        fdctx->remote_fd = rsp.fd; + +                        if (!fdctx->released) { +                                list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); +                                fdctx = NULL; +                        } +                } +                pthread_mutex_unlock (&conf->lock); +        } + +out: +        if (fdctx) +                client_fdctx_destroy (frame->this, fdctx); + +        frame->local = NULL; +        STACK_DESTROY (frame->root); + +        client_local_wipe (local); + +        return 0; +} + +int +protocol_client_reopendir (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ +        int               ret   = -1; +        gfs3_opendir_req  req   = {0,}; +        clnt_local_t     *local = NULL; +        inode_t          *inode = NULL; +        char             *path  = NULL; +        call_frame_t     *frame = NULL; +        clnt_conf_t      *conf  = NULL; + +        if (!this || !fdctx) +                goto out; + +        inode = fdctx->inode; +        conf = this->private; + +        ret = inode_path (inode, NULL, &path); +        if (ret < 0) { +                goto out; +        } + +        local = GF_CALLOC (1, sizeof (*local), 0); +        if (!local) { +                goto out; +        } + +        local->fdctx    = fdctx; +        local->op       = client3_1_reopendir_cbk; +        local->loc.path = path; +        path            = NULL; + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) { +                goto out; +        } + +        req.ino   = fdctx->ino; +        req.gen   = fdctx->gen; +        req.path  = (char *)local->loc.path; + +        gf_log (frame->this->name, GF_LOG_DEBUG, +                "attempting reopen on %s", local->loc.path); + +        frame->local = local; local = NULL; + +        client_submit_request (this, &req, frame, conf->fops, +                               GFS3_OP_OPENDIR, NULL, xdr_from_opendir_req); + +        return ret; + +out: +        if (frame) { +                frame->local = NULL; +                STACK_DESTROY (frame->root); +        } + +        if (local) +                client_local_wipe (local); + +        if (path) +                GF_FREE (path); + +        return 0; + +} + +int +protocol_client_reopen (xlator_t *this, clnt_fd_ctx_t *fdctx) +{ +        int            ret   = -1; +        gfs3_open_req  req   = {0,}; +        clnt_local_t  *local = NULL; +        inode_t       *inode = NULL; +        char          *path  = NULL; +        call_frame_t  *frame = NULL; +        clnt_conf_t   *conf  = NULL; + +        if (!this || !fdctx) +                goto out; + +        inode = fdctx->inode; +        conf  = this->private; + +        ret = inode_path (inode, NULL, &path); +        if (ret < 0) { +                goto out; +        } + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) { +                goto out; +        } + +        local = GF_CALLOC (1, sizeof (*local), 0); +        if (!local) { +                goto out; +        } + +        local->fdctx    = fdctx; +        local->op       = client3_1_reopen_cbk; +        local->loc.path = path; +        path            = NULL; +        frame->local    = local; + +        req.ino      = fdctx->ino; +        req.gen      = fdctx->gen; +        req.flags    = gf_flags_from_flags (fdctx->flags); +        req.wbflags  = fdctx->wbflags; +        req.path     = (char *)local->loc.path; + +        gf_log (frame->this->name, GF_LOG_DEBUG, +                "attempting reopen on %s", local->loc.path); + +        local = NULL; +        client_submit_request (this, &req, frame, conf->fops, +                               GFS3_OP_OPEN, NULL, xdr_from_open_req); + +        return ret; + +out: +        if (frame) { +                frame->local = NULL; +                STACK_DESTROY (frame->root); +        } + +        if (local) +                client_local_wipe (local); + +        if (path) +                GF_FREE (path); + +        return 0; + +} + + + +int32_t +client3_1_releasedir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                      void *data) +{ +        clnt_conf_t         *conf = NULL; +        clnt_fd_ctx_t       *fdctx = NULL; +        clnt_args_t         *args = NULL; +        gfs3_releasedir_req  req = {0,}; +        int64_t              remote_fd = -1; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_del_ctx (args->fd, this); +                if (fdctx != NULL) { +                        remote_fd = fdctx->remote_fd; + +                        /* fdctx->remote_fd == -1 indicates a reopen attempt +                           in progress. Just mark ->released = 1 and let +                           reopen_cbk handle releasing +                        */ + +                        if (remote_fd != -1) +                                list_del_init (&fdctx->sfd_pos); + +                        fdctx->released = 1; +                } +        } +        pthread_mutex_unlock (&conf->lock); + +        if (remote_fd != -1) { +                req.fd = remote_fd; +                client_submit_request (this, &req, frame, prog, +                                       GFS3_OP_RELEASEDIR, +                                       NULL, xdr_from_releasedir_req); +                inode_unref (fdctx->inode); +                GF_FREE (fdctx); +        } + +        return 0; +unwind: +        return 0; +} + +int32_t +client3_1_release (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        int64_t           remote_fd = -1; +        clnt_conf_t      *conf      = NULL; +        clnt_fd_ctx_t    *fdctx     = NULL; +        clnt_args_t      *args      = NULL; +        gfs3_release_req  req       = {0,}; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_del_ctx (args->fd, this); +                if (fdctx != NULL) { +                        remote_fd = fdctx->remote_fd; + +                        /* fdctx->remote_fd == -1 indicates a reopen attempt +                           in progress. Just mark ->released = 1 and let +                           reopen_cbk handle releasing +                        */ + +                        if (remote_fd != -1) +                                list_del_init (&fdctx->sfd_pos); + +                        fdctx->released = 1; +                } +        } +        pthread_mutex_unlock (&conf->lock); + +        if (remote_fd != -1) { +                req.fd = remote_fd; +                client_submit_request (this, &req, frame, prog, +                                       GFS3_OP_RELEASE, NULL, +                                       xdr_from_release_req); +                inode_unref (fdctx->inode); +                GF_FREE (fdctx); +        } +        return 0; +unwind: +        return 0; +} + + +int32_t +client3_1_lookup (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_local_t    *local    = NULL; +        clnt_args_t     *args     = NULL; +        gfs3_lookup_req  req      = {0,}; +        int              ret      = 0; +        size_t           dict_len = 0; +        int              op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } + +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        if (args->loc->ino != 1 && args->loc->parent) { +                ret = inode_ctx_get2 (args->loc->parent, this, +                                      &req.par, &req.gen); +                if (args->loc->parent->ino && ret < 0) { +                        gf_log (this->name, GF_LOG_TRACE, +                                "LOOKUP %"PRId64"/%s (%s): failed to get " +                                "remote inode number for parent", +                                args->loc->parent->ino, args->loc->name, +                                args->loc->path); +                        goto unwind; +                } +                GF_VALIDATE_OR_GOTO (this->name, args->loc->name, unwind); +        } else { +                req.ino = 1; +        } + +        if (args->dict) { +                ret = dict_allocate_and_serialize (args->dict, +                                                   &req.dict.dict_val, +                                                   &dict_len); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "failed to get serialized length of dict"); +                        op_errno = EINVAL; +                        goto unwind; +                } +        } + +        req.path          = (char *)args->loc->path; +        req.bname         = (char *)args->loc->name; +        req.dict.dict_len = dict_len; + +        client_submit_request (this, &req, frame,prog, +                               GFS3_OP_LOOKUP, NULL, xdr_from_lookup_req); + +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } + +        return 0; + +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); + +        if (local) +                client_local_wipe (local); + +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } + +        return 0; +} + + + +int32_t +client3_1_stat (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                void *data) +{ +        clnt_args_t   *args     = NULL; +        gfs3_stat_req  req      = {0,}; +        int            ret      = 0; +        int            op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_STAT, +                               NULL, xdr_from_stat_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (stat, frame, -1, op_errno, NULL); +        return 0; +} + + +int32_t +client3_1_truncate (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_truncate_req  req      = {0,}; +        int                ret      = 0; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.offset = args->offset; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_TRUNCATE, +                               NULL, xdr_from_truncate_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (truncate, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + +int32_t +client3_1_ftruncate (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                     void *data) +{ +        clnt_args_t        *args     = NULL; +        clnt_fd_ctx_t      *fdctx    = NULL; +        clnt_conf_t        *conf     = NULL; +        gfs3_ftruncate_req  req      = {0,}; +        int                 op_errno = EINVAL; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.offset = args->offset; +        req.fd     = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FTRUNCATE, +                               NULL, xdr_from_ftruncate_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (ftruncate, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_access (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_args_t     *args     = NULL; +        gfs3_access_req  req      = {0,}; +        int              ret      = 0; +        int              op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.mask = args->mask; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_ACCESS, +                               NULL, xdr_from_access_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (access, frame, -1, op_errno); +        return 0; +} + +int32_t +client3_1_readlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_readlink_req  req      = {0,}; +        int                ret      = 0; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.size = args->size; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_READLINK, +                               NULL, xdr_from_readlink_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (readlink, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + + +int32_t +client3_1_unlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_args_t     *args     = NULL; +        gfs3_unlink_req  req      = {0,}; +        int              ret      = 0; +        int              op_errno = 0; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64"/%s (%s): " +                        "failed to get remote inode number for parent", +                        args->loc->parent->ino, args->loc->name, args->loc->path); +                        goto unwind; +        } +        req.path  = (char *)args->loc->path; +        req.bname = (char *)args->loc->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_UNLINK, +                               NULL, xdr_from_unlink_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (unlink, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_rmdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_args_t    *args     = NULL; +        gfs3_rmdir_req  req      = {0,}; +        int             ret      = 0; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64"/%s (%s): " +                        "failed to get remote inode number for parent", +                        args->loc->parent->ino, args->loc->name, args->loc->path); +                        goto unwind; +        } +        req.path  = (char *)args->loc->path; +        req.bname = (char *)args->loc->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_RMDIR, +                               NULL, xdr_from_rmdir_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (rmdir, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_symlink (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_local_t     *local    = NULL; +        clnt_args_t      *args     = NULL; +        gfs3_symlink_req  req      = {0,}; +        int               ret      = 0; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } + +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" +                        " number parent", +                        args->loc->parent->ino, args->loc->name, +                        args->loc->path); +                        goto unwind; +        } + +        req.path     = (char *)args->loc->path; +        req.linkname = (char *)args->linkname; +        req.bname    = (char *)args->loc->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_SYMLINK, +                               NULL, xdr_from_symlink_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (symlink, frame, -1, op_errno, NULL, NULL, NULL, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + + +int32_t +client3_1_rename (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_args_t     *args     = NULL; +        gfs3_rename_req  req      = {0,}; +        int              ret      = 0; +        int              op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->oldloc->parent, this, +                              &req.oldpar, &req.oldgen); +        if (args->oldloc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "RENAME %"PRId64"/%s (%s): failed to get remote inode " +                        "number for source parent", args->oldloc->parent->ino, +                        args->oldloc->name, args->oldloc->path); +                        goto unwind; +        } + +        ret = inode_ctx_get2 (args->newloc->parent, this, &req.newpar, +                              &req.newgen); +        if (args->newloc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "CREATE %"PRId64"/%s (%s): failed to get remote inode " +                        "number for destination parent", +                        args->newloc->parent->ino, args->newloc->name, +                        args->newloc->path); +                        goto unwind; +        } + +        req.oldpath = (char *)args->oldloc->path; +        req.oldbname =  (char *)args->oldloc->name; +        req.newpath = (char *)args->newloc->path; +        req.newbname = (char *)args->newloc->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_RENAME, +                               NULL, xdr_from_rename_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_link (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                void *data) +{ +        clnt_local_t  *local    = NULL; +        clnt_args_t   *args     = NULL; +        gfs3_link_req  req      = {0,}; +        int            ret      = 0; +        int            op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } + +        loc_copy (&local->loc, args->oldloc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->oldloc->inode, this, +                              &req.oldino, &req.oldgen); +        if (args->oldloc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "RENAME %"PRId64"/%s (%s): failed to get remote inode " +                        "number for source parent", args->oldloc->parent->ino, +                        args->oldloc->name, args->oldloc->path); +                        goto unwind; +        } + +        ret = inode_ctx_get2 (args->newloc->parent, this, &req.newpar, +                              &req.newgen); +        if (args->newloc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "CREATE %"PRId64"/%s (%s): failed to get remote inode " +                        "number for destination parent", +                        args->newloc->parent->ino, args->newloc->name, +                        args->newloc->path); +                        goto unwind; +        } + +        req.oldpath = (char *)args->oldloc->path; +        req.newpath = (char *)args->newloc->path; +        req.newbname = (char *)args->newloc->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_LINK, +                               NULL, xdr_from_link_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (link, frame, -1, op_errno, NULL, NULL, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_mknod (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_local_t   *local    = NULL; +        clnt_args_t    *args     = NULL; +        gfs3_mknod_req  req      = {0,}; +        int             ret      = 0; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } + +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" +                        " number parent", +                        args->loc->parent->ino, args->loc->name, +                        args->loc->path); +                        goto unwind; +        } + +        req.path   = (char *)args->loc->path; +        req.bname  = (char *)args->loc->name; +        req.mode   = args->mode; +        req.dev    = args->rdev; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_MKNOD, +                               NULL, xdr_from_mknod_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + + +int32_t +client3_1_mkdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_local_t   *local    = NULL; +        clnt_args_t    *args     = NULL; +        gfs3_mkdir_req  req      = {0,}; +        int             ret      = 0; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } + +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" +                        " number parent", +                        args->loc->parent->ino, args->loc->name, +                        args->loc->path); +                        goto unwind; +        } + +        req.path  = (char *)args->loc->path; +        req.bname = (char *)args->loc->name; +        req.mode  = args->mode; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_MKDIR, +                               NULL, xdr_from_mkdir_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (mkdir, frame, -1, op_errno, NULL, NULL, NULL, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + +int32_t +client3_1_create (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_local_t    *local    = NULL; +        clnt_args_t     *args     = NULL; +        gfs3_create_req  req      = {0,}; +        int              ret      = 0; +        int              op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } +        local->fd = fd_ref (args->fd); +        local->flags = args->flags; +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->parent, this, &req.par, &req.gen); +        if (args->loc->parent->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SYMLINK %"PRId64"/%s (%s): failed to get remote inode" +                        " number parent", +                        args->loc->parent->ino, args->loc->name, +                        args->loc->path); +                        goto unwind; +        } + +        req.path  = (char *)args->loc->path; +        req.bname = (char *)args->loc->name; +        req.mode  = args->mode; +        req.flags = gf_flags_from_flags (args->flags); + +        client_submit_request (this, &req, frame,prog, GFS3_OP_CREATE, +                               NULL, xdr_from_create_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (create, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + + +int32_t +client3_1_open (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                void *data) +{ +        clnt_local_t  *local    = NULL; +        clnt_args_t   *args     = NULL; +        gfs3_open_req  req      = {0,}; +        int            ret      = 0; +        int            op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } +        local->fd = fd_ref (args->fd); +        local->flags = args->flags; +        local->wbflags = args->wbflags; +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "OPEN %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.flags = gf_flags_from_flags (args->flags); +        req.wbflags = args->wbflags; +        req.path = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_OPEN, +                               NULL, xdr_from_open_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (open, frame, -1, op_errno, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + + +int32_t +client3_1_readv (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_args_t   *args     = NULL; +        clnt_fd_ctx_t *fdctx    = NULL; +        clnt_conf_t   *conf     = NULL; +        int            op_errno = ESTALE; +        gfs3_read_req  req      = {0,}; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.size   = args->size; +        req.offset = args->offset; +        req.fd     = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_READ, +                               NULL, xdr_from_readv_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (readv, frame, -1, op_errno, NULL, 0, NULL, NULL); +        return 0; +} + + +int32_t +client3_1_writev (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_args_t    *args     = NULL; +        clnt_fd_ctx_t  *fdctx    = NULL; +        clnt_conf_t    *conf     = NULL; +        gfs3_write_req  req      = {0,}; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.size   = args->size; +        req.offset = args->offset; +        req.fd     = fdctx->remote_fd; + +        /* TODO: Buffer */ + +        client_submit_vec_request (this, &req, frame,prog, GFS3_OP_WRITE, +                                   args->vector, args->count, +                                   args->iobref, xdr_from_writev_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (writev, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_flush (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_args_t    *args     = NULL; +        gfs3_flush_req  req      = {0,}; +        clnt_fd_ctx_t  *fdctx    = NULL; +        clnt_conf_t    *conf     = NULL; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FLUSH, +                               NULL, xdr_from_flush_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (flush, frame, -1, op_errno); +        return 0; +} + + + +int32_t +client3_1_fsync (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_args_t    *args     = NULL; +        gfs3_fsync_req  req      = {0,}; +        clnt_fd_ctx_t  *fdctx    = NULL; +        clnt_conf_t    *conf     = NULL; +        int             op_errno = 0; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd   = fdctx->remote_fd; +        req.data = args->flags; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FSYNC, +                               NULL, xdr_from_fsync_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fsync, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_fstat (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                 void *data) +{ +        clnt_args_t    *args     = NULL; +        gfs3_fstat_req  req      = {0,}; +        clnt_fd_ctx_t  *fdctx    = NULL; +        clnt_conf_t    *conf     = NULL; +        int             op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FSTAT, +                               NULL, xdr_from_fstat_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fstat, frame, -1, op_errno, NULL); +        return 0; +} + + + +int32_t +client3_1_opendir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_local_t     *local = NULL; +        clnt_args_t      *args = NULL; +        gfs3_opendir_req  req = {0,}; +        int               ret       = 0; +        int               op_errno  = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        local = GF_CALLOC (1, sizeof (*local), gf_client_mt_clnt_local_t); +        if (!local) { +                op_errno = ENOMEM; +                goto unwind; +        } +        local->fd = fd_ref (args->fd); +        loc_copy (&local->loc, args->loc); +        frame->local = local; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "OPEN %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_OPENDIR, +                               NULL, xdr_from_opendir_req); + +        return 0; +unwind: +        frame->local = NULL; +        STACK_UNWIND_STRICT (opendir, frame, -1, op_errno, NULL); +        if (local) +                client_local_wipe (local); +        return 0; +} + + + +int32_t +client3_1_fsyncdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) + +{ +        clnt_args_t       *args     = NULL; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        int                op_errno = ESTALE; +        gfs3_fsyncdir_req  req      = {0,}; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd   = fdctx->remote_fd; +        req.data = args->flags; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FSYNCDIR, +                               NULL, xdr_from_fsyncdir_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fsyncdir, frame, -1, op_errno); +        return 0; +} + + + +int32_t +client3_1_statfs (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                  void *data) +{ +        clnt_args_t     *args     = NULL; +        gfs3_statfs_req  req      = {0,}; +        int              ret      = 0; +        int              op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        if (args->loc->inode) { +                ret = inode_ctx_get2 (args->loc->inode, this, +                                      &req.ino, &req.gen); +                if (args->loc->inode->ino && ret < 0) { +                        gf_log (this->name, GF_LOG_TRACE, +                                "STATFS %"PRId64" (%s): " +                                "failed to get remote inode number", +                                args->loc->inode->ino, args->loc->path); +                        goto unwind; +                } +        } +        req.path = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_STATFS, +                               NULL, xdr_from_statfs_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (statfs, frame, -1, op_errno, NULL); +        return 0; +} + + + +int32_t +client3_1_setxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_setxattr_req  req      = {0,}; +        int                ret      = 0; +        size_t             dict_len = 0; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SETXATTR %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        if (args->dict) { +                ret = dict_allocate_and_serialize (args->dict, +                                                   &req.dict.dict_val, +                                                   &dict_len); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "failed to get serialized dict"); +                        op_errno = EINVAL; +                        goto unwind; +                } +                req.dict.dict_len = dict_len; +        } +        req.flags = args->flags; +        req.path  = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_SETXATTR, +                               NULL, xdr_from_setxattr_req); + +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } + +        return 0; +unwind: +        STACK_UNWIND_STRICT (setxattr, frame, -1, op_errno); +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } +        return 0; +} + + + +int32_t +client3_1_fsetxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                     void *data) +{ +        clnt_args_t        *args     = NULL; +        clnt_fd_ctx_t      *fdctx    = NULL; +        clnt_conf_t        *conf     = NULL; +        gfs3_fsetxattr_req  req      = {0,}; +        int                 op_errno = ESTALE; +        int                 ret      = 0; +        size_t              dict_len = 0; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd    = fdctx->remote_fd; +        req.flags = args->flags; +        req.ino   = args->fd->inode->ino; + +        if (args->dict) { +                ret = dict_allocate_and_serialize (args->dict, +                                                   &req.dict.dict_val, +                                                   &dict_len); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "failed to get serialized dict"); +                        goto unwind; +                } +                req.dict.dict_len = dict_len; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FSETXATTR, +                               NULL, xdr_from_fsetxattr_req); + +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fsetxattr, frame, -1, op_errno); +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } +        return 0; +} + + + + +int32_t +client3_1_fgetxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                     void *data) +{ +        clnt_args_t        *args     = NULL; +        clnt_fd_ctx_t      *fdctx    = NULL; +        clnt_conf_t        *conf     = NULL; +        gfs3_fgetxattr_req  req      = {0,}; +        int                 op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.namelen = 1; /* Use it as a flag */ +        req.fd   = fdctx->remote_fd; +        req.name = (char *)args->name; +        if (!req.name) { +                req.name = ""; +                req.namelen = 0; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FGETXATTR, +                               NULL, xdr_from_fgetxattr_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fgetxattr, frame, -1, op_errno, NULL); +        return 0; +} + + + +int32_t +client3_1_getxattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_getxattr_req  req      = {0,}; +        int                ret      = 0; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } + +        req.namelen = 1; /* Use it as a flag */ +        req.path = (char *)args->loc->path; +        req.name = (char *)args->name; +        if (!req.name) { +                req.name = ""; +                req.namelen = 0; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_GETXATTR, +                               NULL, xdr_from_getxattr_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (getxattr, frame, -1, op_errno, NULL); +        return 0; +} + + + +int32_t +client3_1_xattrop (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_args_t      *args     = NULL; +        gfs3_xattrop_req  req      = {0,}; +        int               ret      = 0; +        size_t            dict_len = 0; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "SETXATTR %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        if (args->dict) { +                ret = dict_allocate_and_serialize (args->dict, +                                                   &req.dict.dict_val, +                                                   &dict_len); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "failed to get serialized dict"); +                        op_errno = EINVAL; +                        goto unwind; +                } +                req.dict.dict_len = dict_len; +        } +        req.flags = args->flags; +        req.path  = (char *)args->loc->path; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_XATTROP, +                               NULL, xdr_from_xattrop_req); + +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } +        return 0; +unwind: +        STACK_UNWIND_STRICT (xattrop, frame, -1, op_errno, NULL); +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } +        return 0; +} + + + +int32_t +client3_1_fxattrop (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        gfs3_fxattrop_req  req      = {0,}; +        int                op_errno = ESTALE; +        int                ret      = 0; +        size_t             dict_len = 0; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd    = fdctx->remote_fd; +        req.flags = args->flags; +        req.ino   = args->fd->inode->ino; + +        if (args->dict) { +                ret = dict_allocate_and_serialize (args->dict, +                                                   &req.dict.dict_val, +                                                   &dict_len); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "failed to get serialized dict"); +                        goto unwind; +                } +                req.dict.dict_len = dict_len; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FXATTROP, +                               NULL, xdr_from_fxattrop_req); +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fxattrop, frame, -1, op_errno, NULL); +        if (req.dict.dict_val) { +                GF_FREE (req.dict.dict_val); +        } +        return 0; +} + + + +int32_t +client3_1_removexattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                       void *data) +{ +        clnt_args_t          *args     = NULL; +        gfs3_removexattr_req  req      = {0,}; +        int                   ret      = 0; +        int                   op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "REMOVEXATTR %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.name = (char *)args->name; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_REMOVEXATTR, +                               NULL, xdr_from_removexattr_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (removexattr, frame, -1, op_errno); +        return 0; +} + + +int32_t +client3_1_lk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +              void *data) +{ +        clnt_args_t   *args     = NULL; +        gfs3_lk_req    req      = {0,}; +        int32_t        gf_cmd   = 0; +        int32_t        gf_type  = 0; +        clnt_fd_ctx_t *fdctx    = NULL; +        clnt_conf_t   *conf     = NULL; +        int            op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (args->cmd == F_GETLK || args->cmd == F_GETLK64) +                gf_cmd = GF_LK_GETLK; +        else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) +                gf_cmd = GF_LK_SETLK; +        else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) +                gf_cmd = GF_LK_SETLKW; +        else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "Unknown cmd (%d)!", gf_cmd); +                goto unwind; +        } + +        switch (args->flock->l_type) { +        case F_RDLCK: +                gf_type = GF_LK_F_RDLCK; +                break; +        case F_WRLCK: +                gf_type = GF_LK_F_WRLCK; +                break; +        case F_UNLCK: +                gf_type = GF_LK_F_UNLCK; +                break; +        } + +        req.fd    = fdctx->remote_fd; +        req.cmd   = gf_cmd; +        req.type  = gf_type; +        gf_flock_from_flock (&req.flock, args->flock); + +        client_submit_request (this, &req, frame,prog, GFS3_OP_LK, +                               NULL, xdr_from_lk_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (lk, frame, -1, op_errno, NULL); +        return 0; +} + + +int32_t +client3_1_inodelk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_args_t      *args    = NULL; +        gfs3_inodelk_req  req     = {0,}; +        int               ret     = 0; +        int32_t           gf_cmd  = 0; +        int32_t           gf_type = 0; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "INODELK %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } + +        if (args->cmd == F_GETLK || args->cmd == F_GETLK64) +                gf_cmd = GF_LK_GETLK; +        else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) +                gf_cmd = GF_LK_SETLK; +        else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) +                gf_cmd = GF_LK_SETLKW; +        else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "Unknown cmd (%d)!", gf_cmd); +                op_errno = EINVAL; +                goto unwind; +        } + +        switch (args->flock->l_type) { +        case F_RDLCK: +                gf_type = GF_LK_F_RDLCK; +                break; +        case F_WRLCK: +                gf_type = GF_LK_F_WRLCK; +                break; +        case F_UNLCK: +                gf_type = GF_LK_F_UNLCK; +                break; +        } + +        req.path   = (char *)args->loc->path; +        req.volume = (char *)args->volume; +        req.cmd    = gf_cmd; +        req.type   = gf_type; +        gf_flock_from_flock (&req.flock, args->flock); + +        client_submit_request (this, &req, frame, prog, GFS3_OP_INODELK, +                               NULL, xdr_from_inodelk_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (inodelk, frame, -1, op_errno); +        return 0; +} + + + +int32_t +client3_1_finodelk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_finodelk_req  req      = {0,}; +        int32_t            gf_cmd   = 0; +        int32_t            gf_type  = 0; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (args->cmd == F_GETLK || args->cmd == F_GETLK64) +                gf_cmd = GF_LK_GETLK; +        else if (args->cmd == F_SETLK || args->cmd == F_SETLK64) +                gf_cmd = GF_LK_SETLK; +        else if (args->cmd == F_SETLKW || args->cmd == F_SETLKW64) +                gf_cmd = GF_LK_SETLKW; +        else { +                gf_log (this->name, GF_LOG_DEBUG, +                        "Unknown cmd (%d)!", gf_cmd); +                goto unwind; +        } + +        switch (args->flock->l_type) { +        case F_RDLCK: +                gf_type = GF_LK_F_RDLCK; +                break; +        case F_WRLCK: +                gf_type = GF_LK_F_WRLCK; +                break; +        case F_UNLCK: +                gf_type = GF_LK_F_UNLCK; +                break; +        } + +        req.volume = (char *)args->volume; +        req.fd    = fdctx->remote_fd; +        req.cmd   = gf_cmd; +        req.type  = gf_type; +        gf_flock_from_flock (&req.flock, args->flock); + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FINODELK, +                               NULL, xdr_from_finodelk_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (finodelk, frame, -1, op_errno); +        return 0; +} + + +int32_t +client3_1_entrylk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_args_t      *args     = NULL; +        gfs3_entrylk_req  req      = {0,}; +        int               ret      = 0; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.cmd = args->cmd_entrylk; +        req.type = args->type; +        req.volume = (char *)args->volume; +        req.name = ""; +        if (args->basename) { +                req.name = (char *)args->basename; +                req.namelen = 1; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_ENTRYLK, +                               NULL, xdr_from_entrylk_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (entrylk, frame, -1, op_errno); +        return 0; +} + + + +int32_t +client3_1_fentrylk (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_fentrylk_req  req      = {0,}; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd  = fdctx->remote_fd; +        req.cmd = args->cmd_entrylk; +        req.type = args->type; +        req.volume = (char *)args->volume; +        req.name = ""; +        if (args->basename) { +                req.name = (char *)args->basename; +                req.namelen = 1; +        } + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FENTRYLK, +                               NULL, xdr_from_fentrylk_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fentrylk, frame, -1, op_errno); +        return 0; +} + + + + +int32_t +client3_1_checksum (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_checksum_req  req      = {0,}; +        int                ret      = 0; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.flag = args->flags; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_CHECKSUM, +                               NULL, xdr_from_checksum_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (checksum, frame, -1, op_errno, NULL, NULL); +        return 0; +} + + + +int32_t +client3_1_rchecksum (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                     void *data) +{ +        clnt_args_t        *args     = NULL; +        clnt_fd_ctx_t      *fdctx    = NULL; +        clnt_conf_t        *conf     = NULL; +        gfs3_rchecksum_req  req      = {0,}; +        int                 op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.len    = args->len; +        req.offset = args->offset; +        req.fd     = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_RCHECKSUM, +                               NULL, xdr_from_rchecksum_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (rchecksum, frame, -1, op_errno, 0, NULL); +        return 0; +} + + + +int32_t +client3_1_readdir (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_args_t      *args     = NULL; +        clnt_fd_ctx_t    *fdctx    = NULL; +        clnt_conf_t      *conf     = NULL; +        gfs3_readdir_req  req      = {0,}; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.size = args->size; +        req.offset = args->offset; +        req.fd = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_READDIR, +                               NULL, xdr_from_readdir_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (readdir, frame, -1, op_errno, NULL); +        return 0; +} + + +int32_t +client3_1_readdirp (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        gfs3_readdirp_req  req      = {0,}; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.size = args->size; +        req.offset = args->offset; +        req.fd = fdctx->remote_fd; + +        client_submit_request (this, &req, frame,prog, GFS3_OP_READDIRP, +                               NULL, xdr_from_readdirp_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (readdirp, frame, -1, op_errno, NULL); +        return 0; +} + + +int32_t +client3_1_setattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                   void *data) +{ +        clnt_args_t      *args     = NULL; +        gfs3_setattr_req  req      = {0,}; +        int               ret      = 0; +        int               op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; + +        ret = inode_ctx_get2 (args->loc->inode, this, &req.ino, &req.gen); +        if (args->loc->inode->ino && ret < 0) { +                gf_log (this->name, GF_LOG_TRACE, +                        "STAT %"PRId64" (%s): " +                        "failed to get remote inode number", +                        args->loc->inode->ino, args->loc->path); +                        goto unwind; +        } +        req.path = (char *)args->loc->path; +        req.valid = args->valid; +        gf_stat_from_iatt (&req.stbuf, args->stbuf); + +        client_submit_request (this, &req, frame,prog, GFS3_OP_SETATTR, +                               NULL, xdr_from_setattr_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (setattr, frame, -1, op_errno, NULL, NULL); +        return 0; +} + +int32_t +client3_1_fsetattr (call_frame_t *frame, xlator_t *this, rpc_clnt_prog_t *prog, +                    void *data) +{ +        clnt_args_t       *args     = NULL; +        clnt_fd_ctx_t     *fdctx    = NULL; +        clnt_conf_t       *conf     = NULL; +        gfs3_fsetattr_req  req      = {0,}; +        int                op_errno = ESTALE; + +        if (!frame || !this || !prog || !data) +                goto unwind; + +        args = data; +        conf = this->private; + +        pthread_mutex_lock (&conf->lock); +        { +                fdctx = this_fd_get_ctx (args->fd, this); +        } +        pthread_mutex_unlock (&conf->lock); + +        if (fdctx == NULL) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get fd ctx. EBADFD", +                        args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        if (fdctx->remote_fd == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "(%"PRId64"): failed to get" +                        " fd ctx. EBADFD", args->fd->inode->ino); +                op_errno = EBADFD; +                goto unwind; +        } + +        req.fd = fdctx->remote_fd; +        req.valid = args->valid; +        gf_stat_from_iatt (&req.stbuf, args->stbuf); + +        client_submit_request (this, &req, frame,prog, GFS3_OP_FSETATTR, +                               NULL, xdr_from_fsetattr_req); + +        return 0; +unwind: +        STACK_UNWIND_STRICT (fsetattr, frame, -1, op_errno, NULL, NULL); +        return 0; +} + +/* CBK */ +int +client3_1_release_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t   *frame = NULL; + +        frame = myframe; +        STACK_DESTROY (frame->root); +        return 0; +} +int +client3_1_releasedir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                          void *myframe) +{ +        call_frame_t   *frame = NULL; + +        frame = myframe; +        STACK_DESTROY (frame->root); +        return 0; +} + + +int +client3_1_symlink_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t     *frame      = NULL; +        gfs3_symlink_rsp  rsp        = {0,}; +        struct iatt       stbuf      = {0,}; +        struct iatt       preparent  = {0,}; +        struct iatt       postparent = {0,}; +        int               ret        = 0; +        clnt_local_t     *local      = NULL; +        inode_t          *inode      = NULL; + +        frame = myframe; + +        local = frame->local; +        frame->local = NULL; +        inode = local->loc.inode; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_symlink_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                ret = inode_ctx_put2 (inode, frame->this, +                                      stbuf.ia_ino, stbuf.ia_gen); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_DEBUG, +                                "SYMLINK %"PRId64"/%s (%s): failed to set " +                                "remote inode number to inode ctx", +                                local->loc.parent->ino, local->loc.name, +                                local->loc.path); +                } + +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (symlink, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), inode, &stbuf, +                             &preparent, &postparent); + +        if (local) +                client_local_wipe (local); + +        return 0; +} + + +int +client3_1_mknod_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        call_frame_t     *frame      = NULL; +        gfs3_mknod_rsp  rsp        = {0,}; +        struct iatt       stbuf      = {0,}; +        struct iatt       preparent  = {0,}; +        struct iatt       postparent = {0,}; +        int               ret        = 0; +        clnt_local_t     *local      = NULL; +        inode_t          *inode      = NULL; + +        frame = myframe; + +        local = frame->local; +        frame->local = NULL; +        inode = local->loc.inode; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_mknod_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                ret = inode_ctx_put2 (inode, frame->this, +                                      stbuf.ia_ino, stbuf.ia_gen); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_DEBUG, +                                "MKNOD %"PRId64"/%s (%s): failed to set " +                                "remote inode number to inode ctx", +                                local->loc.parent->ino, local->loc.name, +                                local->loc.path); +                } + +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (mknod, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), inode, +                             &stbuf, &preparent, &postparent); + +        if (local) +                client_local_wipe (local); + +        return 0; +} + +int +client3_1_mkdir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        call_frame_t     *frame      = NULL; +        gfs3_mkdir_rsp  rsp        = {0,}; +        struct iatt       stbuf      = {0,}; +        struct iatt       preparent  = {0,}; +        struct iatt       postparent = {0,}; +        int               ret        = 0; +        clnt_local_t     *local      = NULL; +        inode_t          *inode      = NULL; + +        frame = myframe; + +        local = frame->local; +        frame->local = NULL; +        inode = local->loc.inode; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_mkdir_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                ret = inode_ctx_put2 (inode, frame->this, +                                      stbuf.ia_ino, stbuf.ia_gen); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_DEBUG, +                                "MKDIR %"PRId64"/%s (%s): failed to set " +                                "remote inode number to inode ctx", +                                local->loc.parent->ino, local->loc.name, +                                local->loc.path); +                } + +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (mkdir, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), inode, +                             &stbuf, &preparent, &postparent); + +        if (local) +                client_local_wipe (local); + +        return 0; +} + +int +client3_1_open_cbk (struct rpc_req *req, struct iovec *iov, int count, +                    void *myframe) +{ +        clnt_local_t  *local = NULL; +        clnt_conf_t   *conf  = NULL; +        clnt_fd_ctx_t *fdctx = NULL; +        call_frame_t  *frame = NULL; +        fd_t          *fd    = NULL; +        ino_t          ino   = 0; +        uint64_t       gen   = 0; +        int            ret   = 0; +        gfs3_open_rsp  rsp   = {0,}; + +        frame = myframe; +        local = frame->local; + +        if (local->op) { +                local->op (req, iov, 1, myframe); +                return 0; +        } + +        frame->local = NULL; +        conf  = frame->this->private; +        fd    = local->fd; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_open_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                fdctx = GF_CALLOC (1, sizeof (*fdctx), +                                   gf_client_mt_clnt_fdctx_t); +                if (!fdctx) { +                        rsp.op_ret = -1; +                        rsp.op_errno = ENOMEM; +                        goto out; +                } + +                inode_ctx_get2 (fd->inode, frame->this, &ino, &gen); + +                fdctx->remote_fd = rsp.fd; +                fdctx->inode     = inode_ref (fd->inode); +                fdctx->ino       = ino; +                fdctx->gen       = gen; +                fdctx->flags     = local->flags; +                fdctx->wbflags   = local->wbflags; + +                INIT_LIST_HEAD (&fdctx->sfd_pos); + +                this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + +                pthread_mutex_lock (&conf->lock); +                { +                        list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); +                } +                pthread_mutex_unlock (&conf->lock); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (open, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), fd); + +        client_local_wipe (local); + +        return 0; +} + + +int +client3_1_stat_cbk (struct rpc_req *req, struct iovec *iov, int count, +                    void *myframe) +{ +        gfs3_stat_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  iatt = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_stat_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &iatt); +        } + +out: +        STACK_UNWIND_STRICT (stat, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &iatt); + +        return 0; +} + +int +client3_1_readlink_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        gfs3_readlink_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  iatt = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_readlink_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.buf, &iatt); +        } + +out: +        STACK_UNWIND_STRICT (readlink, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), rsp.path, &iatt); + +        /* This is allocated by the libc while decoding RPC msg */ +        /* Hence no 'GF_FREE', but just 'free' */ +        if (rsp.path) +                free (rsp.path); + +        return 0; +} + +int +client3_1_unlink_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gfs3_unlink_rsp  rsp        = {0,}; +        struct iatt      preparent  = {0,}; +        struct iatt      postparent = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_unlink_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        STACK_UNWIND_STRICT (unlink, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &preparent, +                             &postparent); + +        return 0; +} + +int +client3_1_rmdir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        gfs3_rmdir_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  preparent  = {0,}; +        struct iatt  postparent = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_rmdir_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        STACK_UNWIND_STRICT (rmdir, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &preparent, +                             &postparent); + +        return 0; +} + + +int +client3_1_truncate_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        gfs3_truncate_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  prestat  = {0,}; +        struct iatt  poststat = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_truncate_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.prestat, &prestat); +                gf_stat_to_iatt (&rsp.poststat, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (truncate, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + + +int +client3_1_statfs_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        gfs3_statfs_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct statvfs  statfs = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_statfs_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_statfs_to_statfs (&rsp.statfs, &statfs); +        } + +out: +        STACK_UNWIND_STRICT (statfs, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &statfs); + +        return 0; +} + + +int +client3_1_writev_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        gfs3_write_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  prestat  = {0,}; +        struct iatt  poststat = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_truncate_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.prestat, &prestat); +                gf_stat_to_iatt (&rsp.poststat, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (writev, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + +int +client3_1_flush_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (flush, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_fsync_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        gfs3_fsync_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  prestat  = {0,}; +        struct iatt  poststat = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_truncate_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.prestat, &prestat); +                gf_stat_to_iatt (&rsp.poststat, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (fsync, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + +int +client3_1_setxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (setxattr, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_getxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t      *frame    = NULL; +        dict_t            *dict     = NULL; +        char              *buf      = NULL; +        int                dict_len = 0; +        int                op_ret   = 0; +        int                op_errno = 0; +        gfs3_getxattr_rsp  rsp      = {0,}; +        int                ret      = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                op_ret   = -1; +                op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_getxattr_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                op_ret   = -1; +                op_errno = EINVAL; +                goto out; +        } + +        op_errno = gf_error_to_errno (rsp.op_errno); +        op_ret = rsp.op_ret; +        if (-1 != op_ret) { +                op_ret = -1; +                dict_len = rsp.dict.dict_len; + +                if (dict_len > 0) { +                        dict = dict_new(); +                        buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); + +                        GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); +                        GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + +                        ret = dict_unserialize (buf, dict_len, &dict); +                        if (ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "failed to unserialize xattr dict"); +                                op_errno = EINVAL; +                                goto out; +                        } +                        dict->extra_free = buf; +                        buf = NULL; +                } +                op_ret = 0; +        } + +out: +        STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + +        if (rsp.dict.dict_val) { +                /* don't use GF_FREE, this memory was allocated by libc +                 */ +                free (rsp.dict.dict_val); +                rsp.dict.dict_val = NULL; +        } + +        if (buf) +                GF_FREE (buf); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + +int +client3_1_fgetxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                         void *myframe) +{ +        call_frame_t       *frame    = NULL; +        char               *buf      = NULL; +        dict_t             *dict     = NULL; +        gfs3_fgetxattr_rsp  rsp      = {0,}; +        int                 ret      = 0; +        int                 dict_len = 0; +        int                 op_ret   = 0; +        int                 op_errno = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                op_ret   = -1; +                op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_fgetxattr_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                op_ret   = -1; +                op_errno = EINVAL; +                goto out; +        } + +        op_errno = gf_error_to_errno (rsp.op_errno); +        op_ret = rsp.op_ret; +        if (-1 != op_ret) { +                op_ret = -1; +                dict_len = rsp.dict.dict_len; + +                if (dict_len > 0) { +                        dict = dict_new(); +                        GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); +                        buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); +                        GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + +                        ret = dict_unserialize (buf, dict_len, &dict); +                        if (ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "failed to unserialize xattr dict"); +                                op_errno = EINVAL; +                                goto out; +                        } +                        dict->extra_free = buf; +                        buf = NULL; +                } +                op_ret = 0; +        } +out: +        STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict); +        if (rsp.dict.dict_val) { +                /* don't use GF_FREE, this memory was allocated by libc +                 */ +                free (rsp.dict.dict_val); +                rsp.dict.dict_val = NULL; +        } + +        if (buf) +                GF_FREE (buf); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + +int +client3_1_removexattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                           void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (removexattr, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_fsyncdir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (fsyncdir, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_access_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (access, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + + +int +client3_1_ftruncate_cbk (struct rpc_req *req, struct iovec *iov, int count, +                         void *myframe) +{ +        gfs3_ftruncate_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  prestat  = {0,}; +        struct iatt  poststat = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_ftruncate_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.prestat, &prestat); +                gf_stat_to_iatt (&rsp.poststat, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (ftruncate, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + +int +client3_1_fstat_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        gfs3_fstat_rsp rsp = {0,}; +        call_frame_t   *frame = NULL; +        struct iatt  stat  = {0,}; +        int ret = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_fstat_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stat); +        } + +out: +        STACK_UNWIND_STRICT (fstat, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &stat); + +        return 0; +} + + +int +client3_1_inodelk_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (inodelk, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_finodelk_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (finodelk, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_entrylk_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: + +        STACK_UNWIND_STRICT (entrylk, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_fentrylk_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (fentrylk, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_xattrop_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t     *frame    = NULL; +        dict_t           *dict     = NULL; +        char             *buf      = NULL; +        gfs3_xattrop_rsp  rsp      = {0,}; +        int               ret      = 0; +        int               op_ret   = 0; +        int               dict_len = 0; +        int               op_errno = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                op_ret   = -1; +                op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_xattrop_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                op_ret   = -1; +                op_errno = EINVAL; +                goto out; +        } + +        op_ret = rsp.op_ret; +        if (-1 != op_ret) { +                op_ret = -1; +                dict_len = rsp.dict.dict_len; + +                if (dict_len > 0) { +                        dict = dict_new(); +                        GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + +                        buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); +                        GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); +                        op_ret = dict_unserialize (buf, dict_len, &dict); +                        if (op_ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "failed to unserialize xattr dict"); +                                op_errno = EINVAL; +                                goto out; +                        } +                        dict->extra_free = buf; +                        buf = NULL; +                } +                op_ret = 0; +        } + +out: + +        STACK_UNWIND_STRICT (xattrop, frame, op_ret, +                             gf_error_to_errno (rsp.op_errno), dict); + +        if (rsp.dict.dict_val) { +                /* don't use GF_FREE, this memory was allocated by libc +                 */ +                free (rsp.dict.dict_val); +                rsp.dict.dict_val = NULL; +        } + +        if (buf) +                GF_FREE (buf); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + +int +client3_1_fxattrop_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t      *frame    = NULL; +        dict_t            *dict     = NULL; +        char              *buf      = NULL; +        gfs3_fxattrop_rsp  rsp      = {0,}; +        int                ret      = 0; +        int                op_ret   = 0; +        int                dict_len = 0; +        int                op_errno = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                op_ret   = -1; +                op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_fxattrop_rsp (*iov, &rsp); +        if (ret < 0) { +                op_ret = -1; +                op_errno = EINVAL; +                gf_log ("", GF_LOG_ERROR, "error"); +                goto out; +        } + +        op_ret = rsp.op_ret; +        if (-1 != op_ret) { +                op_ret = -1; +                dict_len = rsp.dict.dict_len; + +                if (dict_len > 0) { +                        dict = dict_new(); +                        GF_VALIDATE_OR_GOTO (frame->this->name, dict, out); + +                        buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); +                        GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); +                        op_ret = dict_unserialize (buf, dict_len, &dict); +                        if (op_ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "failed to unserialize xattr dict"); +                                op_errno = EINVAL; +                                goto out; +                        } +                        dict->extra_free = buf; +                        buf = NULL; +                } +                op_ret = 0; +        } + +out: + +        STACK_UNWIND_STRICT (fxattrop, frame, op_ret, +                             gf_error_to_errno (rsp.op_errno), dict); + +        if (rsp.dict.dict_val) { +                /* don't use GF_FREE, this memory was allocated by libc +                 */ +                free (rsp.dict.dict_val); +                rsp.dict.dict_val = NULL; +        } + +        if (buf) +                GF_FREE (buf); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + +int +client3_1_fsetxattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                         void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gf_common_rsp    rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_common_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (fsetxattr, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno)); + +        return 0; +} + +int +client3_1_fsetattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gfs3_fsetattr_rsp rsp        = {0,}; +        struct iatt      prestat    = {0,}; +        struct iatt      poststat   = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } +        ret = xdr_to_fsetattr_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.statpre, &prestat); +                gf_stat_to_iatt (&rsp.statpost, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (fsetattr, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + + +int +client3_1_setattr_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t    *frame      = NULL; +        gfs3_setattr_rsp rsp        = {0,}; +        struct iatt      prestat    = {0,}; +        struct iatt      poststat   = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_setattr_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.statpre, &prestat); +                gf_stat_to_iatt (&rsp.statpost, &poststat); +        } + +out: +        STACK_UNWIND_STRICT (setattr, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &prestat, +                             &poststat); + +        return 0; +} + +int +client3_1_create_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        call_frame_t    *frame      = NULL; +        fd_t            *fd         = NULL; +        inode_t         *inode      = NULL; +        struct iatt      stbuf      = {0, }; +        struct iatt      preparent  = {0, }; +        struct iatt      postparent = {0, }; +        int32_t          ret        = -1; +        clnt_local_t    *local      = NULL; +        clnt_conf_t     *conf       = NULL; +        clnt_fd_ctx_t   *fdctx      = NULL; +        gfs3_create_rsp  rsp        = {0,}; + +        frame = myframe; +        local = frame->local; frame->local = NULL; +        conf  = frame->this->private; +        fd    = local->fd; +        inode = local->loc.inode; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_create_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                ret = inode_ctx_put2 (inode, frame->this, +                                      stbuf.ia_ino, stbuf.ia_gen); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_DEBUG, +                                "CREATE %"PRId64"/%s (%s): failed to set " +                                "remote inode number to inode ctx", +                                local->loc.parent->ino, local->loc.name, +                                local->loc.path); +                } + +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); + +                fdctx = GF_CALLOC (1, sizeof (*fdctx), +                                   gf_client_mt_clnt_fdctx_t); +                if (!fdctx) { +                        rsp.op_ret = -1; +                        rsp.op_errno = ENOMEM; +                        goto out; +                } + +                fdctx->remote_fd = rsp.fd; +                fdctx->inode     = inode_ref (inode); +                fdctx->ino       = stbuf.ia_ino; +                fdctx->gen       = stbuf.ia_gen; +                fdctx->flags     = local->flags; + +                INIT_LIST_HEAD (&fdctx->sfd_pos); + +                this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + +                pthread_mutex_lock (&conf->lock); +                { +                        list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); +                } +                pthread_mutex_unlock (&conf->lock); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (create, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), fd, inode, +                             &stbuf, &preparent, &postparent); + +        client_local_wipe (local); +        return 0; +} + + +int +client3_1_rchecksum_cbk (struct rpc_req *req, struct iovec *iov, int count, +                         void *myframe) +{ +        call_frame_t *frame = NULL; +        gfs3_rchecksum_rsp rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_rchecksum_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (rchecksum, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), +                             rsp.weak_checksum, +                             (uint8_t *)rsp.strong_checksum.strong_checksum_val); + +        if (rsp.strong_checksum.strong_checksum_val) { +                /* This is allocated by the libc while decoding RPC msg */ +                /* Hence no 'GF_FREE', but just 'free' */ +                free (rsp.strong_checksum.strong_checksum_val); +        } + +        return 0; +} + +int +client3_1_checksum_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t *frame = NULL; +        gfs3_checksum_rsp rsp        = {0,}; +        int              ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_checksum_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +out: +        STACK_UNWIND_STRICT (checksum, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), +                             (uint8_t *)rsp.fchecksum.fchecksum_val, +                             (uint8_t *)rsp.dchecksum.dchecksum_val); + +        /* This is allocated by the libc while decoding RPC msg */ +        /* Hence no 'GF_FREE', but just 'free' */ +        if (rsp.fchecksum.fchecksum_val) { +                free (rsp.fchecksum.fchecksum_val); +        } +        if (rsp.dchecksum.dchecksum_val) { +                free (rsp.dchecksum.dchecksum_val); +        } +        return 0; +} + +int +client3_1_lk_cbk (struct rpc_req *req, struct iovec *iov, int count, +                  void *myframe) +{ +        call_frame_t  *frame = NULL; +        struct flock   lock = {0,}; +        gfs3_lk_rsp    rsp        = {0,}; +        int            ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_lk_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (rsp.op_ret >= 0) { +                gf_flock_to_flock (&rsp.flock, &lock); +        } + +out: +        STACK_UNWIND_STRICT (lk, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &lock); + +        return 0; +} + +int +client3_1_readdir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        call_frame_t           *frame = NULL; +        gfs3_readdir_rsp        rsp = {0,}; +        int32_t                 ret = 0; +        gf_dirent_t             entries; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_readdir_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        INIT_LIST_HEAD (&entries.list); +        if (rsp.op_ret > 0) { +                gf_dirent_unserialize (&entries, rsp.buf.buf_val, +                                       rsp.buf.buf_len); +        } + +out: +        STACK_UNWIND_STRICT (readdir, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &entries); + +        if (rsp.op_ret != -1) { +                gf_dirent_free (&entries); +        } + +        /* This is allocated by the libc while decoding RPC msg */ +        /* Hence no 'GF_FREE', but just 'free' */ +        if (rsp.buf.buf_val) +                free (rsp.buf.buf_val); + +        return 0; +} + + +int +client3_1_readdirp_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        call_frame_t           *frame = NULL; +        gfs3_readdirp_rsp       rsp = {0,}; +        int32_t                 ret = 0; +        gf_dirent_t             entries; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_readdirp_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        INIT_LIST_HEAD (&entries.list); +        if (rsp.op_ret > 0) { +                gf_dirent_unserialize (&entries, rsp.buf.buf_val, +                                       rsp.buf.buf_len); +        } + +out: +        STACK_UNWIND_STRICT (readdirp, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &entries); + +        if (rsp.op_ret != -1) { +                gf_dirent_free (&entries); +        } + +        if (rsp.buf.buf_val) { +                /* don't use GF_FREE as this memory was allocated by libc */ +                free (rsp.buf.buf_val); +        } + +        return 0; +} + + +int +client3_1_rename_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        call_frame_t     *frame      = NULL; +        gfs3_rename_rsp   rsp        = {0,}; +        struct iatt       stbuf      = {0,}; +        struct iatt       preoldparent  = {0,}; +        struct iatt       postoldparent = {0,}; +        struct iatt       prenewparent  = {0,}; +        struct iatt       postnewparent = {0,}; +        int               ret        = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_rename_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                gf_stat_to_iatt (&rsp.preoldparent, &preoldparent); +                gf_stat_to_iatt (&rsp.postoldparent, &postoldparent); + +                gf_stat_to_iatt (&rsp.prenewparent, &prenewparent); +                gf_stat_to_iatt (&rsp.postnewparent, &postnewparent); +        } + +out: +        STACK_UNWIND_STRICT (rename, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), +                             &stbuf, &preoldparent, &postoldparent, +                             &preoldparent, &postoldparent); + +        return 0; +} + +int +client3_1_link_cbk (struct rpc_req *req, struct iovec *iov, int count, +                    void *myframe) +{ +        call_frame_t     *frame      = NULL; +        gfs3_link_rsp     rsp        = {0,}; +        struct iatt       stbuf      = {0,}; +        struct iatt       preparent  = {0,}; +        struct iatt       postparent = {0,}; +        int               ret        = 0; +        clnt_local_t     *local      = NULL; +        inode_t          *inode      = NULL; + +        frame = myframe; + +        local = frame->local; +        frame->local = NULL; +        inode = local->loc.inode; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_link_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                gf_stat_to_iatt (&rsp.preparent, &preparent); +                gf_stat_to_iatt (&rsp.postparent, &postparent); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (link, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), inode, +                             &stbuf, &preparent, &postparent); + +        client_local_wipe (local); +        return 0; +} + + +int +client3_1_opendir_cbk (struct rpc_req *req, struct iovec *iov, int count, +                       void *myframe) +{ +        clnt_local_t      *local = NULL; +        clnt_conf_t       *conf = NULL; +        clnt_fd_ctx_t     *fdctx = NULL; +        ino_t                ino = 0; +        uint64_t             gen = 0; +        call_frame_t   *frame = NULL; +        fd_t             *fd = NULL; +        int ret = 0; +        gfs3_opendir_rsp  rsp = {0,}; + +        frame = myframe; +        local = frame->local; + +        if (local->op) { +                local->op (req, iov, 1, myframe); +                return 0; +        } + +        frame->local = NULL; +        conf  = frame->this->private; +        fd    = local->fd; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_opendir_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (-1 != rsp.op_ret) { +                fdctx = GF_CALLOC (1, sizeof (*fdctx), +                                   gf_client_mt_clnt_fdctx_t); +                if (!fdctx) { +                        rsp.op_ret = -1; +                        rsp.op_errno = ENOMEM; +                        goto out; +                } + +                inode_ctx_get2 (fd->inode, frame->this, &ino, &gen); + +                fdctx->remote_fd = rsp.fd; +                fdctx->inode     = inode_ref (fd->inode); +                fdctx->ino       = ino; +                fdctx->gen       = gen; + +                fdctx->is_dir    = 1; + +                INIT_LIST_HEAD (&fdctx->sfd_pos); + +                this_fd_set_ctx (fd, frame->this, &local->loc, fdctx); + +                pthread_mutex_lock (&conf->lock); +                { +                        list_add_tail (&fdctx->sfd_pos, &conf->saved_fds); +                } +                pthread_mutex_unlock (&conf->lock); +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (opendir, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), fd); + +        client_local_wipe (local); + +        return 0; +} + + +int +client3_1_lookup_cbk (struct rpc_req *req, struct iovec *iov, int count, +                      void *myframe) +{ +        clnt_local_t    *local      = NULL; +        call_frame_t    *frame      = NULL; +        int              ret        = 0; +        gfs3_lookup_rsp  rsp        = {0,}; +        struct iatt      stbuf      = {0,}; +        struct iatt      postparent = {0,}; +        int              op_errno   = 0; +        ino_t            oldino     = 0; +        uint64_t         oldgen     = 0; +        dict_t          *xattr      = NULL; +        inode_t         *inode      = NULL; +        char            *buf        = NULL; + +        frame = myframe; +        local = frame->local; +        inode = local->loc.inode; +        frame->local = NULL; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_lookup_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        op_errno = gf_error_to_errno (rsp.op_errno); +        gf_stat_to_iatt (&rsp.postparent, &postparent); + +        if (rsp.op_ret == 0) { +                rsp.op_ret = -1; +                gf_stat_to_iatt (&rsp.stat, &stbuf); + +                ret = inode_ctx_get2 (inode, frame->this, &oldino, &oldgen); +                if (oldino != stbuf.ia_ino || oldgen != stbuf.ia_gen) { +                        if (oldino) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "LOOKUP %"PRId64"/%s (%s): " +                                        "inode number changed from " +                                        "{%"PRId64",%"PRId64"} to {%"PRId64",%"PRId64"}", +                                        local->loc.parent ? +                                        local->loc.parent->ino : (uint64_t) 0, +                                        local->loc.name, +                                        local->loc.path, +                                        oldgen, oldino, stbuf.ia_gen, stbuf.ia_ino); +                                op_errno = ESTALE; +                                goto out; +                        } + +                        ret = inode_ctx_put2 (inode, frame->this, +                                              stbuf.ia_ino, stbuf.ia_gen); +                        if (ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "LOOKUP %"PRId64"/%s (%s) : " +                                        "failed to set remote inode " +                                        "number to inode ctx", +                                        local->loc.parent ? +                                        local->loc.parent->ino : (uint64_t) 0, +                                        local->loc.name, +                                        local->loc.path); +                        } +                } + +                if (rsp.dict.dict_len > 0) { +                        xattr = dict_new(); +                        GF_VALIDATE_OR_GOTO (frame->this->name, xattr, out); + +                        buf = memdup (rsp.dict.dict_val, rsp.dict.dict_len); +                        GF_VALIDATE_OR_GOTO (frame->this->name, buf, out); + +                        ret = dict_unserialize (buf, rsp.dict.dict_len, &xattr); +                        if (ret < 0) { +                                gf_log (frame->this->name, GF_LOG_DEBUG, +                                        "%s (%"PRId64"): failed to " +                                        "unserialize dictionary", +                                        local->loc.path, inode->ino); +                                op_errno = EINVAL; +                                goto out; +                        } + +                        xattr->extra_free = buf; +                        buf = NULL; +                } + +                rsp.op_ret = 0; +        } + +out: +        frame->local = NULL; +        STACK_UNWIND_STRICT (lookup, frame, rsp.op_ret, rsp.op_errno, inode, +                             &stbuf, xattr, &postparent); + +        client_local_wipe (local); + +        if (xattr) +                dict_unref (xattr); + +        if (rsp.dict.dict_val) { +                /* don't use GF_FREE, this memory was allocated by libc +                 */ +                free (rsp.dict.dict_val); +                rsp.dict.dict_val = NULL; +        } + +        if (buf) { +                GF_FREE (buf); +        } + +        return 0; +} + +int +client3_1_readv_cbk (struct rpc_req *req, struct iovec *iov, int count, +                     void *myframe) +{ +        call_frame_t  *frame  = NULL; +        struct iobref *iobref = NULL; +        struct iovec   vector = {0,}; +        struct iatt    stat   = {0,}; +        gfs3_read_rsp  rsp    = {0,}; +        int            ret    = 0; + +        frame = myframe; + +        if (-1 == req->rpc_status) { +                rsp.op_ret   = -1; +                rsp.op_errno = ENOTCONN; +                goto out; +        } + +        ret = xdr_to_readv_rsp (*iov, &rsp); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "error"); +                rsp.op_ret   = -1; +                rsp.op_errno = EINVAL; +                goto out; +        } + +        if (rsp.op_ret != -1) { +                iobref = iobref_new (); +                gf_stat_to_iatt (&rsp.stat, &stat); +                vector.iov_len  = rsp.op_ret; + +                if (rsp.op_ret > 0) { +                        vector.iov_base = req->rsp_procpayload->ptr; +                        iobref_add (iobref, req->rsp_procpayload); +                } +        } +out: +        STACK_UNWIND_STRICT (readv, frame, rsp.op_ret, +                             gf_error_to_errno (rsp.op_errno), &vector, 1, +                             &stat, iobref); + +        if (iobref) { +                iobref_unref (iobref); +        } + +        return 0; +} + +/* Table Specific to FOPS */ + + +rpc_clnt_procedure_t clnt3_1_fop_actors[GF_FOP_MAXVALUE] = { +        [GF_FOP_NULL]        = {"NULL", NULL, NULL }, +        [GF_FOP_STAT]        = { "STAT", client3_1_stat, client3_1_stat_cbk }, +        [GF_FOP_READLINK]    = { "READLINK", client3_1_readlink, client3_1_readlink_cbk }, +        [GF_FOP_MKNOD]       = { "MKNOD", client3_1_mknod, client3_1_mknod_cbk }, +        [GF_FOP_MKDIR]       = { "MKDIR", client3_1_mkdir, client3_1_mkdir_cbk }, +        [GF_FOP_UNLINK]      = { "UNLINK", client3_1_unlink, client3_1_unlink_cbk }, +        [GF_FOP_RMDIR]       = { "RMDIR", client3_1_rmdir, client3_1_rmdir_cbk }, +        [GF_FOP_SYMLINK]     = { "SYMLINK", client3_1_symlink, client3_1_symlink_cbk }, +        [GF_FOP_RENAME]      = { "RENAME", client3_1_rename, client3_1_rename_cbk }, +        [GF_FOP_LINK]        = { "LINK",  client3_1_link, client3_1_link_cbk }, +        [GF_FOP_TRUNCATE]    = { "TRUNCATE",  client3_1_truncate, client3_1_truncate_cbk }, +        [GF_FOP_OPEN]        = { "OPEN",  client3_1_open, client3_1_open_cbk }, +        [GF_FOP_READ]        = { "READ",  client3_1_readv, client3_1_readv_cbk }, +        [GF_FOP_WRITE]       = { "WRITE", client3_1_writev, client3_1_writev_cbk }, +        [GF_FOP_STATFS]      = { "STATFS", client3_1_statfs, client3_1_statfs_cbk }, +        [GF_FOP_FLUSH]       = { "FLUSH", client3_1_flush, client3_1_flush_cbk }, +        [GF_FOP_FSYNC]       = { "FSYNC",         client3_1_fsync, client3_1_fsync_cbk }, +        [GF_FOP_SETXATTR]    = { "SETXATTR",     client3_1_setxattr, client3_1_setxattr_cbk }, +        [GF_FOP_GETXATTR]    = { "GETXATTR",     client3_1_getxattr, client3_1_getxattr_cbk }, +        [GF_FOP_REMOVEXATTR] = { "REMOVEXATTR",  client3_1_removexattr, client3_1_removexattr_cbk }, +        [GF_FOP_OPENDIR]     = { "OPENDIR",     client3_1_opendir, client3_1_opendir_cbk }, +        [GF_FOP_FSYNCDIR]    = { "FSYNCDIR",    client3_1_fsyncdir, client3_1_fsyncdir_cbk }, +        [GF_FOP_ACCESS]      = { "ACCESS",      client3_1_access, client3_1_access_cbk }, +        [GF_FOP_CREATE]      = { "CREATE",      client3_1_create, client3_1_create_cbk }, +        [GF_FOP_FTRUNCATE]   = { "FTRUNCATE",   client3_1_ftruncate, client3_1_ftruncate_cbk }, +        [GF_FOP_FSTAT]       = { "FSTAT",       client3_1_fstat, client3_1_fstat_cbk }, +        [GF_FOP_LK]          = { "LK",          client3_1_lk, client3_1_lk_cbk }, +        [GF_FOP_LOOKUP]      = { "LOOKUP",      client3_1_lookup, client3_1_lookup_cbk }, +        [GF_FOP_READDIR]     = { "READDIR",     client3_1_readdir, client3_1_readdir_cbk }, +        [GF_FOP_INODELK]     = { "INODELK",     client3_1_inodelk, client3_1_inodelk_cbk }, +        [GF_FOP_FINODELK]    = { "FINODELK",    client3_1_finodelk, client3_1_finodelk_cbk }, +        [GF_FOP_ENTRYLK]     = { "ENTRYLK",     client3_1_entrylk, client3_1_entrylk_cbk }, +        [GF_FOP_FENTRYLK]    = { "FENTRYLK",    client3_1_fentrylk, client3_1_fentrylk_cbk }, +        [GF_FOP_CHECKSUM]    = { "CHECKSUM",    client3_1_checksum, client3_1_checksum_cbk }, +        [GF_FOP_XATTROP]     = { "XATTROP",     client3_1_xattrop, client3_1_xattrop_cbk }, +        [GF_FOP_FXATTROP]    = { "FXATTROP",    client3_1_fxattrop, client3_1_fxattrop_cbk }, +        [GF_FOP_FGETXATTR]   = { "FGETXATTR",   client3_1_fgetxattr, client3_1_fgetxattr_cbk }, +        [GF_FOP_FSETXATTR]   = { "FSETXATTR",   client3_1_fsetxattr, client3_1_fsetxattr_cbk }, +        [GF_FOP_RCHECKSUM]   = { "RCHECKSUM",   client3_1_rchecksum, client3_1_rchecksum_cbk }, +        [GF_FOP_SETATTR]     = { "SETATTR",     client3_1_setattr, client3_1_setattr_cbk }, +        [GF_FOP_FSETATTR]    = { "FSETATTR",    client3_1_fsetattr, client3_1_fsetattr_cbk }, +        [GF_FOP_READDIRP]    = { "READDIRP",    client3_1_readdirp, client3_1_readdirp_cbk }, +        [GF_FOP_FORGET]      = { "FORGET",      NULL, client3_1_release_cbk }, +        [GF_FOP_RELEASE]     = { "RELEASE",     client3_1_release, client3_1_release_cbk }, +        [GF_FOP_RELEASEDIR]  = { "RELEASEDIR",  client3_1_releasedir, client3_1_releasedir_cbk }, +//        [GF_FOP_GETSPEC]     = { "GETSPEC",   client_getspec, client_getspec_cbk }, +}; + +rpc_clnt_prog_t clnt3_1_fop_prog = { +        .progname = "GlusterFS 3.1", +        .prognum  = GLUSTER3_1_FOP_PROGRAM, +        .progver  = GLUSTER3_1_FOP_VERSION, +        .numproc  = GLUSTER3_1_FOP_PROCCNT, +        .actor    = clnt3_1_fop_actors, +}; + +rpc_clnt_procedure_t clnt3_1_mgmt_actors[] = { +        {0,} +}; + +rpc_clnt_prog_t clnt3_1_mgmt_prog = { +        .progname = "Mgmt 3.1", +        .prognum  = GLUSTER1_MGMT_PROGRAM, +        .progver  = GLUSTER1_MGMT_VERSION, +        .actor    = clnt3_1_mgmt_actors, +        .numproc  = (sizeof (*clnt3_1_mgmt_actors) / +                     sizeof (rpc_clnt_procedure_t)), +};  | 
