diff options
author | Soumya Koduri <skoduri@redhat.com> | 2014-05-07 14:05:31 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-05-11 02:47:42 -0700 |
commit | 5adb10b9ac1c634334f29732e062b12d747ae8c5 (patch) | |
tree | 135e0279c4f220b520386e8677c8dd209ef00ed7 /api/src/glfs-mgmt.c | |
parent | 2fd499d148fc8865c77de8b2c73fe0b7e1737882 (diff) |
libgfapi: Added support to fetch volume info from glusterd and store in glfs object.
Defined new APIs in the libgfapi module, given a glfs object,
* to send handshake RPC call to glusterd process to fetch UUID of the volume
* store it in the glusterfs_context linked to the glfs object.
* to parse UUID from its cannonical string format into 16-byte array
before sending it to the libgfapi users.
Defined a RPC call in glusterd which can be used to query volume related
info by other processes using 'clnt_handshake_procs'.
Note - Currently this RPC call to glusterd process is used only to fetch UUID.
But it can be extended to get other volume related structures as well.
In addition to the above, defined a new variable to keep track of such handshake
RPCs still in progress to make sure all the corresponding RPC callbacks have been
processed before libgfapi returns the glfs object initialized.
Also bumping up the GFAPI current version number since there is a new API
"glfs_get_volume_id" defined and exposed by libgfapi as part of these changes.
Change-Id: I303f76d7177d32d25bdb301b1dbcf5cd73f42807
BUG: 1090363
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
Reviewed-on: http://review.gluster.org/7218
Reviewed-by: Anand Avati <avati@redhat.com>
Reviewed-by: Harshavardhana <harsha@harshavardhana.net>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'api/src/glfs-mgmt.c')
-rw-r--r-- | api/src/glfs-mgmt.c | 258 |
1 files changed, 252 insertions, 6 deletions
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; } |