|
|
cb8e9e |
From bc759c626e16af3be07f82bb8203a3c455973757 Mon Sep 17 00:00:00 2001
|
|
|
cb8e9e |
From: vmallika <vmallika@redhat.com>
|
|
|
cb8e9e |
Date: Mon, 24 Aug 2015 08:07:14 +0530
|
|
|
cb8e9e |
Subject: [PATCH 310/320] cli: on error invoke cli_cmd_broadcast_response function in separate thread
|
|
|
cb8e9e |
|
|
|
cb8e9e |
This is a backport of http://review.gluster.org/#/c/11990/
|
|
|
cb8e9e |
|
|
|
cb8e9e |
There is a problem in current CLI framework
|
|
|
cb8e9e |
CLI holds the lock when processing command.
|
|
|
cb8e9e |
When processing quota list command, below sequence of steps executed in the
|
|
|
cb8e9e |
same thread and causing deadlock
|
|
|
cb8e9e |
|
|
|
cb8e9e |
1) CLI holds the lock
|
|
|
cb8e9e |
2) Send rpc_clnt_submit request to quotad for quota usage
|
|
|
cb8e9e |
3) If quotad is down, rpc_clnt_submit invokes cbk function with error
|
|
|
cb8e9e |
4) cbk function cli_quotad_getlimit_cbk tries to hold lock to broadcast
|
|
|
cb8e9e |
the results and hangs, because same thread has already holding the lock
|
|
|
cb8e9e |
|
|
|
cb8e9e |
This patch fixes the problem by creating seperate thread for
|
|
|
cb8e9e |
broadcasting the result
|
|
|
cb8e9e |
|
|
|
cb8e9e |
> Change-Id: I53be006eadf6aaf348083d9168535530d70a8ab3
|
|
|
cb8e9e |
> BUG: 1242819
|
|
|
cb8e9e |
> Signed-off-by: vmallika <vmallika@redhat.com>
|
|
|
cb8e9e |
|
|
|
cb8e9e |
Change-Id: Id010b95be689a947dd7ef75500d6c00d0f78cd3c
|
|
|
cb8e9e |
BUG: 1242803
|
|
|
cb8e9e |
Signed-off-by: vmallika <vmallika@redhat.com>
|
|
|
cb8e9e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/56573
|
|
|
cb8e9e |
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
|
|
|
cb8e9e |
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
|
|
|
cb8e9e |
---
|
|
|
cb8e9e |
cli/src/cli-cmd-volume.c | 12 ------
|
|
|
cb8e9e |
cli/src/cli-rpc-ops.c | 94 ++++++++++++++++++++++++++++++++++++++++++---
|
|
|
cb8e9e |
cli/src/cli.c | 1 +
|
|
|
cb8e9e |
cli/src/cli.h | 1 +
|
|
|
cb8e9e |
4 files changed, 89 insertions(+), 19 deletions(-)
|
|
|
cb8e9e |
|
|
|
cb8e9e |
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
|
|
|
cb8e9e |
index 6dd3058..ca18108 100644
|
|
|
cb8e9e |
--- a/cli/src/cli-cmd-volume.c
|
|
|
cb8e9e |
+++ b/cli/src/cli-cmd-volume.c
|
|
|
cb8e9e |
@@ -1381,18 +1381,6 @@ cli_cmd_quota_handle_list_all (const char **words, dict_t *options)
|
|
|
cb8e9e |
CLI_LOCAL_INIT (local, words, frame, xdata);
|
|
|
cb8e9e |
proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT];
|
|
|
cb8e9e |
|
|
|
cb8e9e |
- if (!(global_state->mode & GLUSTER_MODE_XML)) {
|
|
|
cb8e9e |
- print_quota_list_header (type);
|
|
|
cb8e9e |
- } else {
|
|
|
cb8e9e |
- ret = cli_xml_output_vol_quota_limit_list_begin
|
|
|
cb8e9e |
- (local, 0, 0, NULL);
|
|
|
cb8e9e |
- if (ret) {
|
|
|
cb8e9e |
- gf_log ("cli", GF_LOG_ERROR, "Error in printing "
|
|
|
cb8e9e |
- "xml output");
|
|
|
cb8e9e |
- goto out;
|
|
|
cb8e9e |
- }
|
|
|
cb8e9e |
- }
|
|
|
cb8e9e |
-
|
|
|
cb8e9e |
gfid_str = GF_CALLOC (1, gf_common_mt_char, 64);
|
|
|
cb8e9e |
if (!gfid_str) {
|
|
|
cb8e9e |
ret = -1;
|
|
|
cb8e9e |
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
|
|
|
cb8e9e |
index dfc5c6b..fd76df7 100644
|
|
|
cb8e9e |
--- a/cli/src/cli-rpc-ops.c
|
|
|
cb8e9e |
+++ b/cli/src/cli-rpc-ops.c
|
|
|
cb8e9e |
@@ -3232,7 +3232,8 @@ out:
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
|
|
|
cb8e9e |
int
|
|
|
cb8e9e |
-print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict)
|
|
|
cb8e9e |
+print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict,
|
|
|
cb8e9e |
+ int32_t list_count)
|
|
|
cb8e9e |
{
|
|
|
cb8e9e |
char *path = NULL;
|
|
|
cb8e9e |
char *default_sl = NULL;
|
|
|
cb8e9e |
@@ -3244,11 +3245,11 @@ print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict)
|
|
|
cb8e9e |
quota_limits_t *size_limits = NULL;
|
|
|
cb8e9e |
int32_t type = 0;
|
|
|
cb8e9e |
|
|
|
cb8e9e |
+ GF_ASSERT (frame);
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
local = frame->local;
|
|
|
cb8e9e |
gd_rsp_dict = local->dict;
|
|
|
cb8e9e |
|
|
|
cb8e9e |
- GF_ASSERT (frame);
|
|
|
cb8e9e |
-
|
|
|
cb8e9e |
ret = dict_get_int32 (rsp_dict, "type", &type);
|
|
|
cb8e9e |
if (ret) {
|
|
|
cb8e9e |
gf_log ("cli", GF_LOG_ERROR, "Failed to get type");
|
|
|
cb8e9e |
@@ -3306,12 +3307,37 @@ print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict)
|
|
|
cb8e9e |
goto out;
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
|
|
|
cb8e9e |
+ if (list_count == 0) {
|
|
|
cb8e9e |
+ if (!(global_state->mode & GLUSTER_MODE_XML)) {
|
|
|
cb8e9e |
+ print_quota_list_header (type);
|
|
|
cb8e9e |
+ } else {
|
|
|
cb8e9e |
+ ret = cli_xml_output_vol_quota_limit_list_begin
|
|
|
cb8e9e |
+ (local, 0, 0, NULL);
|
|
|
cb8e9e |
+ if (ret) {
|
|
|
cb8e9e |
+ gf_log ("cli", GF_LOG_ERROR, "Error in "
|
|
|
cb8e9e |
+ "printing xml output");
|
|
|
cb8e9e |
+ goto out;
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
ret = print_quota_list_output (local, path, default_sl, &limits,
|
|
|
cb8e9e |
&used_space, type);
|
|
|
cb8e9e |
out:
|
|
|
cb8e9e |
return ret;
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
|
|
|
cb8e9e |
+void*
|
|
|
cb8e9e |
+cli_cmd_broadcast_response_detached (void *opaque)
|
|
|
cb8e9e |
+{
|
|
|
cb8e9e |
+ int32_t ret = 0;
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
+ ret = (intptr_t) opaque;
|
|
|
cb8e9e |
+ cli_cmd_broadcast_response (ret);
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
+ return NULL;
|
|
|
cb8e9e |
+}
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
int
|
|
|
cb8e9e |
cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov,
|
|
|
cb8e9e |
int count, void *myframe)
|
|
|
cb8e9e |
@@ -3321,12 +3347,41 @@ cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov,
|
|
|
cb8e9e |
int ret = -1;
|
|
|
cb8e9e |
dict_t *dict = NULL;
|
|
|
cb8e9e |
call_frame_t *frame = NULL;
|
|
|
cb8e9e |
+ cli_local_t *local = NULL;
|
|
|
cb8e9e |
+ dict_t *gd_rsp_dict = NULL;
|
|
|
cb8e9e |
+ int32_t list_count = 0;
|
|
|
cb8e9e |
+ pthread_t th_id = {0, };
|
|
|
cb8e9e |
|
|
|
cb8e9e |
- if (-1 == req->rpc_status) {
|
|
|
cb8e9e |
+ frame = myframe;
|
|
|
cb8e9e |
+ GF_ASSERT (frame);
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
+ local = frame->local;
|
|
|
cb8e9e |
+ gd_rsp_dict = local->dict;
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
+ LOCK (&local->lock);
|
|
|
cb8e9e |
+ {
|
|
|
cb8e9e |
+ ret = dict_get_int32 (gd_rsp_dict, "quota-list-count",
|
|
|
cb8e9e |
+ &list_count);
|
|
|
cb8e9e |
+ if (ret)
|
|
|
cb8e9e |
+ list_count = 0;
|
|
|
cb8e9e |
+ ret = dict_set_int32 (gd_rsp_dict, "quota-list-count",
|
|
|
cb8e9e |
+ list_count + 1);
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
+ UNLOCK (&local->lock);
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
+ if (ret) {
|
|
|
cb8e9e |
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set "
|
|
|
cb8e9e |
+ "quota-list-count in dict");
|
|
|
cb8e9e |
goto out;
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
|
|
|
cb8e9e |
- frame = myframe;
|
|
|
cb8e9e |
+ if (-1 == req->rpc_status) {
|
|
|
cb8e9e |
+ if (list_count == 0)
|
|
|
cb8e9e |
+ cli_err ("Connection failed. Please check if quota "
|
|
|
cb8e9e |
+ "daemon is operational.");
|
|
|
cb8e9e |
+ ret = -1;
|
|
|
cb8e9e |
+ goto out;
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
|
|
|
cb8e9e |
ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
|
|
|
cb8e9e |
if (ret < 0) {
|
|
|
cb8e9e |
@@ -3357,11 +3412,36 @@ cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov,
|
|
|
cb8e9e |
"unserialize req-buffer to dictionary");
|
|
|
cb8e9e |
goto out;
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
- print_quota_list_from_quotad (frame, dict);
|
|
|
cb8e9e |
+ print_quota_list_from_quotad (frame, dict, list_count);
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
|
|
|
cb8e9e |
out:
|
|
|
cb8e9e |
- cli_cmd_broadcast_response (ret);
|
|
|
cb8e9e |
+ /* Bad Fix: CLI holds the lock to process a command.
|
|
|
cb8e9e |
+ * When processing quota list command, below sequence of steps executed
|
|
|
cb8e9e |
+ * in the same thread and causing deadlock
|
|
|
cb8e9e |
+ *
|
|
|
cb8e9e |
+ * 1) CLI holds the lock
|
|
|
cb8e9e |
+ * 2) Send rpc_clnt_submit request to quotad for quota usage
|
|
|
cb8e9e |
+ * 3) If quotad is down, rpc_clnt_submit invokes cbk function with error
|
|
|
cb8e9e |
+ * 4) cbk function cli_quotad_getlimit_cbk invokes
|
|
|
cb8e9e |
+ * cli_cmd_broadcast_response which tries to hold lock to broadcast
|
|
|
cb8e9e |
+ * the results and hangs, because same thread has already holding
|
|
|
cb8e9e |
+ * the lock
|
|
|
cb8e9e |
+ *
|
|
|
cb8e9e |
+ * Broadcasting response in a seperate thread which is not a
|
|
|
cb8e9e |
+ * good fix. This needs to be re-visted with better solution
|
|
|
cb8e9e |
+ */
|
|
|
cb8e9e |
+ if (ret == -1) {
|
|
|
cb8e9e |
+ ret = pthread_create (&th_id, NULL,
|
|
|
cb8e9e |
+ cli_cmd_broadcast_response_detached,
|
|
|
cb8e9e |
+ (void *)-1);
|
|
|
cb8e9e |
+ if (ret)
|
|
|
cb8e9e |
+ gf_log ("cli", GF_LOG_ERROR, "pthread_create failed: "
|
|
|
cb8e9e |
+ "%s", strerror (errno));
|
|
|
cb8e9e |
+ } else {
|
|
|
cb8e9e |
+ cli_cmd_broadcast_response (ret);
|
|
|
cb8e9e |
+ }
|
|
|
cb8e9e |
+
|
|
|
cb8e9e |
if (dict)
|
|
|
cb8e9e |
dict_unref (dict);
|
|
|
cb8e9e |
|
|
|
cb8e9e |
diff --git a/cli/src/cli.c b/cli/src/cli.c
|
|
|
cb8e9e |
index 851178b..fa5b682 100644
|
|
|
cb8e9e |
--- a/cli/src/cli.c
|
|
|
cb8e9e |
+++ b/cli/src/cli.c
|
|
|
cb8e9e |
@@ -653,6 +653,7 @@ cli_local_get ()
|
|
|
cb8e9e |
cli_local_t *local = NULL;
|
|
|
cb8e9e |
|
|
|
cb8e9e |
local = GF_CALLOC (1, sizeof (*local), cli_mt_cli_local_t);
|
|
|
cb8e9e |
+ LOCK_INIT (&local->lock);
|
|
|
cb8e9e |
|
|
|
cb8e9e |
return local;
|
|
|
cb8e9e |
}
|
|
|
cb8e9e |
diff --git a/cli/src/cli.h b/cli/src/cli.h
|
|
|
cb8e9e |
index 6c0fbce..d831af0 100644
|
|
|
cb8e9e |
--- a/cli/src/cli.h
|
|
|
cb8e9e |
+++ b/cli/src/cli.h
|
|
|
cb8e9e |
@@ -151,6 +151,7 @@ struct cli_local {
|
|
|
cb8e9e |
xmlDocPtr doc;
|
|
|
cb8e9e |
int vol_count;
|
|
|
cb8e9e |
#endif
|
|
|
cb8e9e |
+ gf_lock_t lock;
|
|
|
cb8e9e |
};
|
|
|
cb8e9e |
|
|
|
cb8e9e |
struct cli_volume_status {
|
|
|
cb8e9e |
--
|
|
|
cb8e9e |
1.7.1
|
|
|
cb8e9e |
|