diff options
| -rw-r--r-- | api/src/glfs-internal.h | 4 | ||||
| -rw-r--r-- | api/src/glfs-mgmt.c | 258 | ||||
| -rw-r--r-- | api/src/glfs.h | 32 | ||||
| -rw-r--r-- | configure.ac | 4 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 8 | ||||
| -rw-r--r-- | rpc/xdr/src/glusterfs3-xdr.x | 10 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 137 | 
7 files changed, 445 insertions, 8 deletions
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 14e94e2116f..6fdec961a1c 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -80,6 +80,7 @@ typedef int (*glfs_init_cbk) (struct glfs *fs, int ret);  struct glfs {  	char               *volname; +        uuid_t              vol_uuid;  	glusterfs_ctx_t    *ctx; @@ -222,4 +223,7 @@ dict_t * dict_for_key_value (const char *name, const char *value, size_t size);  int glfs_getxattr_process (void *value, size_t size, dict_t *xattr,  			   const char *name); +/* Sends RPC call to glusterd to fetch required volume info */ +int glfs_get_volume_info (struct glfs *fs); +  #endif /* !_GLFS_INTERNAL_H */ diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c index 5c7e8b2fc2a..bb82dc9a188 100644 --- a/api/src/glfs-mgmt.c +++ b/api/src/glfs-mgmt.c @@ -22,6 +22,7 @@  #endif /* _CONFIG_H */  #include "glusterfs.h" +#include "glfs.h"  #include "stack.h"  #include "dict.h"  #include "event.h" @@ -40,8 +41,9 @@  #include "glfs-internal.h"  #include "glfs-mem-types.h" -  int glfs_volfile_fetch (struct glfs *fs); +int32_t glfs_get_volume_info_rpc (call_frame_t *frame, xlator_t *this, +                                  struct glfs *fs);  int  glfs_process_volfp (struct glfs *fs, FILE *fp) @@ -136,6 +138,7 @@ char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = {  	[GF_HNDSK_GETSPEC]	= "GETSPEC",  	[GF_HNDSK_PING]		= "PING",  	[GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY", +        [GF_HNDSK_GET_VOLUME_INFO] = "GETVOLUMEINFO",  };  rpc_clnt_prog_t clnt_handshake_prog = { @@ -202,6 +205,249 @@ out:  	return ret;  } +/* + * Callback routine for 'GF_HNDSK_GET_VOLUME_INFO' rpc request + */ +int +mgmt_get_volinfo_cbk (struct rpc_req *req, struct iovec *iov, +                      int count, void *myframe) +{ +        int                        ret                  = 0; +        char                       *volume_id_str       = NULL; +        dict_t                     *dict                = NULL; +        char                       key[1024]            = {0}; +        gf_get_volume_info_rsp     rsp                  = {0,}; +        call_frame_t               *frame               = NULL; +        glusterfs_ctx_t            *ctx                 = NULL; +        struct glfs                *fs                  = NULL; +        struct syncargs            *args; + +        frame = myframe; +        ctx = frame->this->ctx; +        args = frame->local; + +        if (!ctx) { +                gf_log (frame->this->name, GF_LOG_ERROR, "NULL context"); +                errno = EINVAL; +                ret = -1; +                goto out; +        } + +        fs = ((xlator_t *)ctx->master)->private; + +        if (-1 == req->rpc_status) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "GET_VOLUME_INFO RPC call is not successfull"); +                errno = EINVAL; +                ret = -1; +                goto out; +        } + +        ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_get_volume_info_rsp); + +        if (ret < 0) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "Failed to decode xdr response for GET_VOLUME_INFO"); +                goto out; +        } + +        gf_log (frame->this->name, GF_LOG_DEBUG, +                "Received resp to GET_VOLUME_INFO RPC: %d", rsp.op_ret); + +        if (rsp.op_ret == -1) { +                errno = rsp.op_errno; +                ret = -1; +                goto out; +        } + +        if (!rsp.dict.dict_len) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "Response received for GET_VOLUME_INFO RPC call is not valid"); +                ret = -1; +                errno = EINVAL; +                goto out; +        } + +        dict = dict_new (); + +        if (!dict) { +                ret = -1; +                errno = ENOMEM; +                goto out; +        } + +        ret = dict_unserialize (rsp.dict.dict_val, +                                rsp.dict.dict_len, +                                &dict); + +        if (ret) { +                errno = ENOMEM; +                goto out; +        } + +        snprintf (key, sizeof (key), "volume_id"); +        ret = dict_get_str (dict, key, &volume_id_str); +        if (ret) { +                errno = EINVAL; +                goto out; +        } + +        ret = 0; +out: +        if (volume_id_str) { +                gf_log (frame->this->name, GF_LOG_DEBUG, +                        "Volume Id: %s", volume_id_str); +                pthread_mutex_lock (&fs->mutex); +                uuid_parse (volume_id_str, fs->vol_uuid); +                pthread_mutex_unlock (&fs->mutex); +        } + +        if (ret) { +               gf_log (frame->this->name, GF_LOG_ERROR, +                       "In GET_VOLUME_INFO cbk, received error: %s", +                       strerror(errno)); +        } + +        if (dict) +                dict_destroy (dict); + +        if (rsp.dict.dict_val) +                free (rsp.dict.dict_val); + +        if (rsp.op_errstr && *rsp.op_errstr) +                free (rsp.op_errstr); + +        gf_log (frame->this->name, GF_LOG_DEBUG, "Returning: %d", ret); + +        __wake (args); + +        return ret; +} + +int +glfs_get_volumeid (struct glfs *fs, char *volid, size_t size) +{ +        /* TODO: Define a global macro to store UUID size */ +        size_t uuid_size = 16; + +        pthread_mutex_lock (&fs->mutex); +        { +                /* check if the volume uuid is initialized */ +                if (!uuid_is_null (fs->vol_uuid)) { +                        pthread_mutex_unlock (&fs->mutex); +                        goto done; +                } +        } +        pthread_mutex_unlock (&fs->mutex); + +        /* Need to fetch volume_uuid */ +        glfs_get_volume_info (fs); + +        if (uuid_is_null (fs->vol_uuid)) { +                gf_log (THIS->name, GF_LOG_ERROR, "Unable to fetch volume UUID"); +                return -1; +        } + +done: +        if (!volid || !size) { +                gf_log (THIS->name, GF_LOG_DEBUG, "volumeid/size is null"); +                return uuid_size; +        } + +        if (size < uuid_size) { +                gf_log (THIS->name, GF_LOG_ERROR, "Insufficient size passed"); +                errno = ERANGE; +                return -1; +        } + +        memcpy (volid, fs->vol_uuid, uuid_size); + +        gf_log (THIS->name, GF_LOG_INFO, "volume uuid: %s", volid); + +        return uuid_size; +} + +int +glfs_get_volume_info (struct glfs *fs) +{ +        call_frame_t     *frame = NULL; +        glusterfs_ctx_t  *ctx   = NULL; +        struct syncargs  args   = {0, }; +        int              ret    = 0; + +        ctx = fs->ctx; +        frame = create_frame (THIS, ctx->pool); +        frame->local = &args; + +        __yawn ((&args)); + +        ret = glfs_get_volume_info_rpc (frame, THIS, fs); +        if (ret) +                goto out; + +        __yield ((&args)); + +        frame->local = NULL; +        STACK_DESTROY (frame->root); + +out: +        return ret; +} + +int32_t +glfs_get_volume_info_rpc (call_frame_t *frame, xlator_t *this, +                          struct glfs *fs) +{ +        gf_get_volume_info_req  req       = {{0,}}; +        int                     ret       = 0; +        glusterfs_ctx_t         *ctx      = NULL; +        dict_t                  *dict     = NULL; +        int32_t                 flags     = 0; + +        if (!frame || !this || !fs) { +                ret = -1; +                goto out; +        } + +        ctx = fs->ctx; + +        dict = dict_new (); +        if (!dict) { +                ret = -1; +                goto out; +        } + +        if (fs->volname) { +                ret = dict_set_str (dict, "volname", fs->volname); +                if (ret) +                        goto out; +        } + +        // Set the flags for the fields which we are interested in +        flags = (int32_t)GF_GET_VOLUME_UUID; //ctx->flags; +        ret = dict_set_int32 (dict, "flags", flags); +        if (ret) { +                gf_log (frame->this->name, GF_LOG_ERROR, "failed to set flags"); +                goto out; +        } + +        ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, +                                           &req.dict.dict_len); + + +        ret = mgmt_submit_request (&req, frame, ctx, &clnt_handshake_prog, +                                   GF_HNDSK_GET_VOLUME_INFO, +                                   mgmt_get_volinfo_cbk, +                                   (xdrproc_t)xdr_gf_get_volume_info_req); +out: +        if (dict) { +                dict_unref (dict); +        } + +        GF_FREE (req.dict.dict_val); + +        return ret; +}  static int  glusterfs_oldvolfile_update (struct glfs *fs, char *volfile, ssize_t size) @@ -514,12 +760,12 @@ mgmt_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,  			/* Exit the process.. there are some wrong options */  			gf_log ("glfs-mgmt", GF_LOG_ERROR,  				"failed to fetch volume file (key:%s)", -				ctx->cmd_args.volfile_id); -			errno = EINVAL; -			glfs_init_done (fs, -1); -		} +                                ctx->cmd_args.volfile_id); +                        errno = EINVAL; +                        glfs_init_done (fs, -1); +                } -		break; +                break;  	default:  		break;  	} diff --git a/api/src/glfs.h b/api/src/glfs.h index 4344df24dc7..8f1d09d1094 100644 --- a/api/src/glfs.h +++ b/api/src/glfs.h @@ -285,6 +285,38 @@ int glfs_fini (glfs_t *fs) __THROW;  ssize_t glfs_get_volfile (glfs_t *fs, void *buf, size_t len) __THROW; + +/* +  SYNOPSIS + +       glfs_get_volumeid: Copy the Volume UUID stored in the glfs object fs. + +  DESCRIPTION + +       This function when invoked for the first time sends RPC call to the +       the management server (glusterd) to fetch volume uuid and stores it +       in the glusterfs_context linked to the glfs object fs which can be used +       in the subsequent calls. Later it parses that UUID to convert it from +       cannonical string format into an opaque byte array and copy it into +       the volid array. Incase if either of the input parameters, volid or size, +       is NULL, number of bytes required to copy the volume UUID is returned. + +  PARAMETERS + +       @fs: The 'virtual mount' object to be used to retrieve and store +            volume's UUID. +       @volid: Pointer to a place for the volume UUID to be stored +       @size: Length of @volid + +  RETURN VALUES + +       -1 : Failure. @errno will be set with the type of failure. +        Others : length of the volume UUID stored. +*/ + +int glfs_get_volumeid (struct glfs *fs, char *volid, size_t size); + +  /*   * FILE OPERATION   * diff --git a/configure.ac b/configure.ac index b824cf92178..d16bcb12363 100644 --- a/configure.ac +++ b/configure.ac @@ -995,7 +995,7 @@ AM_CONDITIONAL([GF_DARWIN_HOST_OS], test "${GF_HOST_OS}" = "GF_DARWIN_HOST_OS")  AM_CONDITIONAL([GF_INSTALL_VAR_LIB_GLUSTERD], test ! -d ${localstatedir}/lib/glusterd && test -d ${sysconfdir}/glusterd )  dnl pkg-config versioning -GFAPI_VERSION="6.0.0" +GFAPI_VERSION="7.0.0"  LIBGFCHANGELOG_VERSION="0.0.1"  AC_SUBST(GFAPI_VERSION)  AC_SUBST(LIBGFCHANGELOG_VERSION) @@ -1005,7 +1005,7 @@ LIBGFXDR_LT_VERSION="0:1:0"  LIBGFRPC_LT_VERSION="0:1:0"  LIBGLUSTERFS_LT_VERSION="0:1:0"  LIBGFCHANGELOG_LT_VERSION="0:1:0" -GFAPI_LT_VERSION="6:0:0" +GFAPI_LT_VERSION="7:0:0"  AC_SUBST(LIBGFXDR_LT_VERSION)  AC_SUBST(LIBGFRPC_LT_VERSION)  AC_SUBST(LIBGLUSTERFS_LT_VERSION) diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 02e0d244a4f..00ba2d1fc95 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -69,6 +69,7 @@ enum gf_handshake_procnum {          GF_HNDSK_PING,          GF_HNDSK_SET_LK_VER,          GF_HNDSK_EVENT_NOTIFY, +        GF_HNDSK_GET_VOLUME_INFO,          GF_HNDSK_MAXVALUE,  }; @@ -255,6 +256,13 @@ enum glusterd_mgmt_v3_procnum {  typedef struct gf_gsync_detailed_status_ gf_gsync_status_t; +enum gf_get_volume_info_type { +        GF_GET_VOLUME_NONE,    /* 0 */ +        GF_GET_VOLUME_UUID +}; + +typedef enum gf_get_volume_info_type gf_get_volume_info_type; +  #define GLUSTER_HNDSK_PROGRAM    14398633 /* Completely random */  #define GLUSTER_HNDSK_VERSION    2   /* 0.0.2 */ diff --git a/rpc/xdr/src/glusterfs3-xdr.x b/rpc/xdr/src/glusterfs3-xdr.x index 72f528e0a1c..b2fa4de9737 100644 --- a/rpc/xdr/src/glusterfs3-xdr.x +++ b/rpc/xdr/src/glusterfs3-xdr.x @@ -653,6 +653,16 @@ struct gfs3_fstat_req {          opaque   xdata<>; /* Extra data */  } ; + struct gf_get_volume_info_req { +        opaque   dict<>; /* Extra data */ +}  ; + struct  gf_get_volume_info_rsp { +        int    op_ret; +        int    op_errno; +        string op_errstr<>; +        opaque   dict<>; /* Extra data */ +} ; +   struct gf_mgmt_hndsk_req {          opaque   hndsk<>;  }  ; diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 2b89545c80d..dbaa972937b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -1001,10 +1001,147 @@ glusterd_mgmt_hndsk_versions_ack (rpcsvc_request_t *req)                                              __glusterd_mgmt_hndsk_versions_ack);  } +int +__server_get_volume_info (rpcsvc_request_t *req) +{ +        int                     ret             = -1; +        int32_t                 op_errno        = ENOENT; +        gf_get_volume_info_req	vol_info_req    = {{0,}}; +        gf_get_volume_info_rsp	vol_info_rsp    = {0,}; +        char                    *volname        = NULL; +        glusterd_volinfo_t      *volinfo        = NULL; +        dict_t                  *dict           = NULL; +        dict_t                  *dict_rsp       = NULL; +        char                    *volume_id_str  = NULL; +        int32_t                 flags           = 0; + +        ret = xdr_to_generic (req->msg[0], &vol_info_req, +                             (xdrproc_t)xdr_gf_get_volume_info_req); +        if (ret < 0) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } +        gf_log ("glusterd", GF_LOG_INFO, "Received get volume info req"); + +        if (vol_info_req.dict.dict_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); +                if (!dict) { +                        gf_log ("", GF_LOG_WARNING, "Out of Memory"); +                        op_errno = ENOMEM; +                        ret = -1; +                        goto out; +                } + +                ret = dict_unserialize (vol_info_req.dict.dict_val, +                                        vol_info_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        op_errno = -ret; +                        ret = -1; +                        goto out; +                } else { +                        dict->extra_stdfree = vol_info_req.dict.dict_val; +                } +        } + +        ret = dict_get_int32 (dict, "flags", &flags); +        if (ret) { +                gf_log (THIS->name, GF_LOG_ERROR, "failed to get flags"); +                op_errno = -ret; +                ret = -1; +                goto out; +        } + +        if (!flags) { +                //Nothing to query about. Just return success +                gf_log (THIS->name, GF_LOG_ERROR, "No flags set"); +                ret = 0; +                goto out; +        } + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                op_errno = EINVAL; +                ret = -1; +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                op_errno = EINVAL; +                ret = -1; +                goto out; +        } + +        if (flags | (int32_t)GF_GET_VOLUME_UUID) { +                volume_id_str = gf_strdup (uuid_utoa (volinfo->volume_id)); +                if (!volume_id_str) { +                        op_errno = ENOMEM; +                        ret = -1; +                        goto out; +                } + +                dict_rsp = dict_new (); +                if (!dict_rsp) { +                        gf_log ("", GF_LOG_WARNING, "Out of Memory"); +                        op_errno = ENOMEM; +                        ret = -1; +                        goto out; +                } +                ret = dict_set_dynstr (dict_rsp, "volume_id", volume_id_str); +                if (ret) { +                        op_errno = -ret; +                        ret = -1; +                        goto out; +                } +        } +        ret = dict_allocate_and_serialize (dict_rsp, &vol_info_rsp.dict.dict_val, +                                           &vol_info_rsp.dict.dict_len); +        if (ret) { +                op_errno = -ret; +                ret = -1; +                goto out; +        } + +out: +        vol_info_rsp.op_ret = ret; +        vol_info_rsp.op_errno = op_errno; +        vol_info_rsp.op_errstr = ""; +        glusterd_submit_reply (req, &vol_info_rsp, NULL, 0, NULL, +                               (xdrproc_t)xdr_gf_get_volume_info_rsp); +        ret = 0; + +        if (dict) { +                dict_unref (dict); +        } + +        if (dict_rsp) { +                dict_unref (dict_rsp); +        } + +        if (vol_info_rsp.dict.dict_val) { +                GF_FREE (vol_info_rsp.dict.dict_val); +        } +        return ret; +} + +int +server_get_volume_info (rpcsvc_request_t *req) +{ +        return glusterd_big_locked_handler (req, +                                            __server_get_volume_info); +} +  rpcsvc_actor_t gluster_handshake_actors[] = {          [GF_HNDSK_NULL]         = {"NULL",        GF_HNDSK_NULL,         NULL,                NULL, 0, DRC_NA},          [GF_HNDSK_GETSPEC]      = {"GETSPEC",     GF_HNDSK_GETSPEC,      server_getspec,      NULL, 0, DRC_NA},          [GF_HNDSK_EVENT_NOTIFY] = {"EVENTNOTIFY", GF_HNDSK_EVENT_NOTIFY, server_event_notify, NULL, 0, DRC_NA}, +        [GF_HNDSK_GET_VOLUME_INFO] = {"GETVOLUMEINFO", GF_HNDSK_GET_VOLUME_INFO, server_get_volume_info, NULL, 0, DRC_NA},  };  | 
