|
|
d1681e |
From 8503ed9b94777d47352f19ebfa844e151352b87f Mon Sep 17 00:00:00 2001
|
|
|
d1681e |
From: Milind Changire <mchangir@redhat.com>
|
|
|
d1681e |
Date: Fri, 2 Mar 2018 15:39:27 +0530
|
|
|
d1681e |
Subject: [PATCH 166/180] rpcsvc: scale rpcsvc_request_handler threads
|
|
|
d1681e |
|
|
|
d1681e |
Scale rpcsvc_request_handler threads to match the scaling of event
|
|
|
d1681e |
handler threads.
|
|
|
d1681e |
|
|
|
d1681e |
Please refer to https://bugzilla.redhat.com/show_bug.cgi?id=1467614#c51
|
|
|
d1681e |
for a discussion about why we need multi-threaded rpcsvc request
|
|
|
d1681e |
handlers.
|
|
|
d1681e |
|
|
|
d1681e |
mainline:
|
|
|
d1681e |
> Reviewed-on: https://review.gluster.org/19337
|
|
|
d1681e |
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
d1681e |
> Signed-off-by: Milind Changire <mchangir@redhat.com>
|
|
|
d1681e |
(cherry picked from commit 7d641313f46789ec0a7ba0cc04f504724c780855)
|
|
|
d1681e |
|
|
|
d1681e |
Change-Id: Ib6838fb8b928e15602a3d36fd66b7ba08999430b
|
|
|
d1681e |
BUG: 1549497
|
|
|
d1681e |
Signed-off-by: Milind Changire <mchangir@redhat.com>
|
|
|
d1681e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/131596
|
|
|
d1681e |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
d1681e |
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
|
|
|
d1681e |
---
|
|
|
d1681e |
glusterfsd/src/Makefile.am | 1 +
|
|
|
d1681e |
glusterfsd/src/glusterfsd-mgmt.c | 16 ++++-
|
|
|
d1681e |
glusterfsd/src/glusterfsd.h | 2 +-
|
|
|
d1681e |
libglusterfs/src/event-poll.c | 7 ++
|
|
|
d1681e |
rpc/rpc-lib/src/rpcsvc.c | 129 +++++++++++++++++++++++++++++++----
|
|
|
d1681e |
rpc/rpc-lib/src/rpcsvc.h | 8 +++
|
|
|
d1681e |
xlators/protocol/server/src/server.c | 10 ++-
|
|
|
d1681e |
7 files changed, 153 insertions(+), 20 deletions(-)
|
|
|
d1681e |
|
|
|
d1681e |
diff --git a/glusterfsd/src/Makefile.am b/glusterfsd/src/Makefile.am
|
|
|
d1681e |
index 0196204..8ab585c 100644
|
|
|
d1681e |
--- a/glusterfsd/src/Makefile.am
|
|
|
d1681e |
+++ b/glusterfsd/src/Makefile.am
|
|
|
d1681e |
@@ -22,6 +22,7 @@ AM_CPPFLAGS = $(GF_CPPFLAGS) \
|
|
|
d1681e |
-I$(top_srcdir)/rpc/xdr/src \
|
|
|
d1681e |
-I$(top_builddir)/rpc/xdr/src \
|
|
|
d1681e |
-I$(top_srcdir)/xlators/nfs/server/src \
|
|
|
d1681e |
+ -I$(top_srcdir)/xlators/protocol/server/src \
|
|
|
d1681e |
-I$(top_srcdir)/api/src
|
|
|
d1681e |
|
|
|
d1681e |
AM_CFLAGS = -Wall $(GF_CFLAGS)
|
|
|
d1681e |
diff --git a/glusterfsd/src/glusterfsd-mgmt.c b/glusterfsd/src/glusterfsd-mgmt.c
|
|
|
d1681e |
index ca706d1..69d93f5 100644
|
|
|
d1681e |
--- a/glusterfsd/src/glusterfsd-mgmt.c
|
|
|
d1681e |
+++ b/glusterfsd/src/glusterfsd-mgmt.c
|
|
|
d1681e |
@@ -33,6 +33,7 @@
|
|
|
d1681e |
#include "syncop.h"
|
|
|
d1681e |
#include "xlator.h"
|
|
|
d1681e |
#include "syscall.h"
|
|
|
d1681e |
+#include "server.h"
|
|
|
d1681e |
|
|
|
d1681e |
static gf_boolean_t is_mgmt_rpc_reconnect = _gf_false;
|
|
|
d1681e |
int need_emancipate = 0;
|
|
|
d1681e |
@@ -185,12 +186,15 @@ glusterfs_terminate_response_send (rpcsvc_request_t *req, int op_ret)
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
void
|
|
|
d1681e |
-glusterfs_autoscale_threads (glusterfs_ctx_t *ctx, int incr)
|
|
|
d1681e |
+glusterfs_autoscale_threads (glusterfs_ctx_t *ctx, int incr, xlator_t *this)
|
|
|
d1681e |
{
|
|
|
d1681e |
struct event_pool *pool = ctx->event_pool;
|
|
|
d1681e |
+ server_conf_t *conf = this->private;
|
|
|
d1681e |
+ int thread_count = pool->eventthreadcount;
|
|
|
d1681e |
|
|
|
d1681e |
pool->auto_thread_count += incr;
|
|
|
d1681e |
- (void) event_reconfigure_threads (pool, pool->eventthreadcount+incr);
|
|
|
d1681e |
+ (void) event_reconfigure_threads (pool, thread_count+incr);
|
|
|
d1681e |
+ rpcsvc_ownthread_reconf (conf->rpc, pool->eventthreadcount);
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
int
|
|
|
d1681e |
@@ -839,6 +843,7 @@ glusterfs_handle_attach (rpcsvc_request_t *req)
|
|
|
d1681e |
xlator_t *nextchild = NULL;
|
|
|
d1681e |
glusterfs_graph_t *newgraph = NULL;
|
|
|
d1681e |
glusterfs_ctx_t *ctx = NULL;
|
|
|
d1681e |
+ xlator_t *protocol_server = NULL;
|
|
|
d1681e |
|
|
|
d1681e |
GF_ASSERT (req);
|
|
|
d1681e |
this = THIS;
|
|
|
d1681e |
@@ -876,7 +881,12 @@ glusterfs_handle_attach (rpcsvc_request_t *req)
|
|
|
d1681e |
nextchild->name);
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
}
|
|
|
d1681e |
- glusterfs_autoscale_threads (this->ctx, 1);
|
|
|
d1681e |
+ /* we need a protocol/server xlator as
|
|
|
d1681e |
+ * nextchild
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ protocol_server = this->ctx->active->first;
|
|
|
d1681e |
+ glusterfs_autoscale_threads (this->ctx, 1,
|
|
|
d1681e |
+ protocol_server);
|
|
|
d1681e |
}
|
|
|
d1681e |
} else {
|
|
|
d1681e |
gf_log (this->name, GF_LOG_WARNING,
|
|
|
d1681e |
diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h
|
|
|
d1681e |
index 6d1e165..43cef52 100644
|
|
|
d1681e |
--- a/glusterfsd/src/glusterfsd.h
|
|
|
d1681e |
+++ b/glusterfsd/src/glusterfsd.h
|
|
|
d1681e |
@@ -124,7 +124,7 @@ int glusterfs_volume_top_read_perf (uint32_t blk_size, uint32_t blk_count,
|
|
|
d1681e |
char *brick_path, double *throughput,
|
|
|
d1681e |
double *time);
|
|
|
d1681e |
void
|
|
|
d1681e |
-glusterfs_autoscale_threads (glusterfs_ctx_t *ctx, int incr);
|
|
|
d1681e |
+glusterfs_autoscale_threads (glusterfs_ctx_t *ctx, int incr, xlator_t *this);
|
|
|
d1681e |
|
|
|
d1681e |
extern glusterfs_ctx_t *glusterfsd_ctx;
|
|
|
d1681e |
#endif /* __GLUSTERFSD_H__ */
|
|
|
d1681e |
diff --git a/libglusterfs/src/event-poll.c b/libglusterfs/src/event-poll.c
|
|
|
d1681e |
index 3bffc47..b1aca82 100644
|
|
|
d1681e |
--- a/libglusterfs/src/event-poll.c
|
|
|
d1681e |
+++ b/libglusterfs/src/event-poll.c
|
|
|
d1681e |
@@ -173,6 +173,13 @@ event_pool_new_poll (int count, int eventthreadcount)
|
|
|
d1681e |
"thread count (%d) ignored", eventthreadcount);
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ /* although, eventhreadcount for poll implementaiton is always
|
|
|
d1681e |
+ * going to be 1, eventthreadcount needs to be set to 1 so that
|
|
|
d1681e |
+ * rpcsvc_request_handler() thread scaling works flawlessly in
|
|
|
d1681e |
+ * both epoll and poll models
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ event_pool->eventthreadcount = 1;
|
|
|
d1681e |
+
|
|
|
d1681e |
return event_pool;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
d1681e |
index 68e27ab..31b5eb5 100644
|
|
|
d1681e |
--- a/rpc/rpc-lib/src/rpcsvc.c
|
|
|
d1681e |
+++ b/rpc/rpc-lib/src/rpcsvc.c
|
|
|
d1681e |
@@ -1877,39 +1877,105 @@ rpcsvc_request_handler (void *arg)
|
|
|
d1681e |
goto unlock;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
- while (list_empty (&program->request_queue))
|
|
|
d1681e |
+ while (list_empty (&program->request_queue) &&
|
|
|
d1681e |
+ (program->threadcount <=
|
|
|
d1681e |
+ program->eventthreadcount)) {
|
|
|
d1681e |
pthread_cond_wait (&program->queue_cond,
|
|
|
d1681e |
&program->queue_lock);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
|
|
|
d1681e |
- req = list_entry (program->request_queue.next,
|
|
|
d1681e |
- typeof (*req), request_list);
|
|
|
d1681e |
-
|
|
|
d1681e |
- list_del_init (&req->request_list);
|
|
|
d1681e |
+ if (program->threadcount > program->eventthreadcount) {
|
|
|
d1681e |
+ done = 1;
|
|
|
d1681e |
+ program->threadcount--;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ gf_log (GF_RPCSVC, GF_LOG_INFO,
|
|
|
d1681e |
+ "program '%s' thread terminated; "
|
|
|
d1681e |
+ "total count:%d",
|
|
|
d1681e |
+ program->progname,
|
|
|
d1681e |
+ program->threadcount);
|
|
|
d1681e |
+ } else if (!list_empty (&program->request_queue)) {
|
|
|
d1681e |
+ req = list_entry (program->request_queue.next,
|
|
|
d1681e |
+ typeof (*req), request_list);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ list_del_init (&req->request_list);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
}
|
|
|
d1681e |
unlock:
|
|
|
d1681e |
pthread_mutex_unlock (&program->queue_lock);
|
|
|
d1681e |
|
|
|
d1681e |
+ if (req) {
|
|
|
d1681e |
+ THIS = req->svc->xl;
|
|
|
d1681e |
+ actor = rpcsvc_program_actor (req);
|
|
|
d1681e |
+ ret = actor->actor (req);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (ret != 0) {
|
|
|
d1681e |
+ rpcsvc_check_and_reply_error (ret, NULL, req);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ req = NULL;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
if (done)
|
|
|
d1681e |
break;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
|
|
|
d1681e |
- THIS = req->svc->xl;
|
|
|
d1681e |
+ return NULL;
|
|
|
d1681e |
+}
|
|
|
d1681e |
|
|
|
d1681e |
- actor = rpcsvc_program_actor (req);
|
|
|
d1681e |
+int
|
|
|
d1681e |
+rpcsvc_spawn_threads (rpcsvc_t *svc, rpcsvc_program_t *program)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0, delta = 0, creates = 0;
|
|
|
d1681e |
|
|
|
d1681e |
- ret = actor->actor (req);
|
|
|
d1681e |
+ if (!program || !svc)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
|
|
|
d1681e |
- if (ret != 0) {
|
|
|
d1681e |
- rpcsvc_check_and_reply_error (ret, NULL, req);
|
|
|
d1681e |
+ pthread_mutex_lock (&program->queue_lock);
|
|
|
d1681e |
+ {
|
|
|
d1681e |
+ delta = program->eventthreadcount - program->threadcount;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (delta >= 0) {
|
|
|
d1681e |
+ while (delta--) {
|
|
|
d1681e |
+ ret = gf_thread_create (&program->thread, NULL,
|
|
|
d1681e |
+ rpcsvc_request_handler,
|
|
|
d1681e |
+ program, "rpcrqhnd");
|
|
|
d1681e |
+ if (!ret) {
|
|
|
d1681e |
+ program->threadcount++;
|
|
|
d1681e |
+ creates++;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (creates) {
|
|
|
d1681e |
+ gf_log (GF_RPCSVC, GF_LOG_INFO,
|
|
|
d1681e |
+ "spawned %d threads for program '%s'; "
|
|
|
d1681e |
+ "total count:%d",
|
|
|
d1681e |
+ creates,
|
|
|
d1681e |
+ program->progname,
|
|
|
d1681e |
+ program->threadcount);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ gf_log (GF_RPCSVC, GF_LOG_INFO,
|
|
|
d1681e |
+ "terminating %d threads for program '%s'",
|
|
|
d1681e |
+ -delta, program->progname);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* this signal is to just wake up the threads so they
|
|
|
d1681e |
+ * test for the change in eventthreadcount and kill
|
|
|
d1681e |
+ * themselves until the program thread count becomes
|
|
|
d1681e |
+ * equal to the event thread count
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ pthread_cond_broadcast (&program->queue_cond);
|
|
|
d1681e |
}
|
|
|
d1681e |
}
|
|
|
d1681e |
+ pthread_mutex_unlock (&program->queue_lock);
|
|
|
d1681e |
|
|
|
d1681e |
- return NULL;
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return creates;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
int
|
|
|
d1681e |
rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t *program)
|
|
|
d1681e |
{
|
|
|
d1681e |
int ret = -1;
|
|
|
d1681e |
+ int creates = -1;
|
|
|
d1681e |
rpcsvc_program_t *newprog = NULL;
|
|
|
d1681e |
char already_registered = 0;
|
|
|
d1681e |
|
|
|
d1681e |
@@ -1957,9 +2023,12 @@ rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t *program)
|
|
|
d1681e |
newprog->ownthread = _gf_false;
|
|
|
d1681e |
|
|
|
d1681e |
if (newprog->ownthread) {
|
|
|
d1681e |
- gf_thread_create (&newprog->thread, NULL,
|
|
|
d1681e |
- rpcsvc_request_handler,
|
|
|
d1681e |
- newprog, "rpcsvcrh");
|
|
|
d1681e |
+ newprog->eventthreadcount = 1;
|
|
|
d1681e |
+ creates = rpcsvc_spawn_threads (svc, newprog);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (creates < 1) {
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
pthread_mutex_lock (&svc->rpclock);
|
|
|
d1681e |
@@ -2816,6 +2885,38 @@ out:
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+/* During reconfigure, Make sure to call this function after event-threads are
|
|
|
d1681e |
+ * reconfigured as programs' threadcount will be made equal to event threads.
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+rpcsvc_ownthread_reconf (rpcsvc_t *svc, int new_eventthreadcount)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ rpcsvc_program_t *program = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!svc) {
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ pthread_rwlock_wrlock (&svc->rpclock);
|
|
|
d1681e |
+ {
|
|
|
d1681e |
+ list_for_each_entry (program, &svc->programs, program) {
|
|
|
d1681e |
+ if (program->ownthread) {
|
|
|
d1681e |
+ program->eventthreadcount =
|
|
|
d1681e |
+ new_eventthreadcount;
|
|
|
d1681e |
+ rpcsvc_spawn_threads (svc, program);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ pthread_rwlock_unlock (&svc->rpclock);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
|
|
|
d1681e |
rpcsvc_actor_t gluster_dump_actors[GF_DUMP_MAXVALUE] = {
|
|
|
d1681e |
[GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, 0, DRC_NA},
|
|
|
d1681e |
diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
d1681e |
index 73507b6..4ae2350 100644
|
|
|
d1681e |
--- a/rpc/rpc-lib/src/rpcsvc.h
|
|
|
d1681e |
+++ b/rpc/rpc-lib/src/rpcsvc.h
|
|
|
d1681e |
@@ -412,6 +412,12 @@ struct rpcsvc_program {
|
|
|
d1681e |
pthread_mutex_t queue_lock;
|
|
|
d1681e |
pthread_cond_t queue_cond;
|
|
|
d1681e |
pthread_t thread;
|
|
|
d1681e |
+ int threadcount;
|
|
|
d1681e |
+ /* eventthreadcount is just a readonly copy of the actual value
|
|
|
d1681e |
+ * owned by the event sub-system
|
|
|
d1681e |
+ * It is used to control the scaling of rpcsvc_request_handler threads
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ int eventthreadcount;
|
|
|
d1681e |
};
|
|
|
d1681e |
|
|
|
d1681e |
typedef struct rpcsvc_cbk_program {
|
|
|
d1681e |
@@ -623,4 +629,6 @@ rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen);
|
|
|
d1681e |
rpcsvc_vector_sizer
|
|
|
d1681e |
rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum,
|
|
|
d1681e |
uint32_t progver, int procnum);
|
|
|
d1681e |
+extern int
|
|
|
d1681e |
+rpcsvc_ownthread_reconf (rpcsvc_t *svc, int new_eventthreadcount);
|
|
|
d1681e |
#endif
|
|
|
d1681e |
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
|
|
|
d1681e |
index 6dc9d0f..4627ea0 100644
|
|
|
d1681e |
--- a/xlators/protocol/server/src/server.c
|
|
|
d1681e |
+++ b/xlators/protocol/server/src/server.c
|
|
|
d1681e |
@@ -990,6 +990,12 @@ do_rpc:
|
|
|
d1681e |
|
|
|
d1681e |
ret = server_init_grace_timer (this, options, conf);
|
|
|
d1681e |
|
|
|
d1681e |
+ /* rpcsvc thread reconfigure should be after events thread
|
|
|
d1681e |
+ * reconfigure
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ new_nthread =
|
|
|
d1681e |
+ ((struct event_pool *)(this->ctx->event_pool))->eventthreadcount;
|
|
|
d1681e |
+ ret = rpcsvc_ownthread_reconf (rpc_conf, new_nthread);
|
|
|
d1681e |
out:
|
|
|
d1681e |
THIS = oldTHIS;
|
|
|
d1681e |
gf_msg_debug ("", 0, "returning %d", ret);
|
|
|
d1681e |
@@ -1569,9 +1575,9 @@ notify (xlator_t *this, int32_t event, void *data, ...)
|
|
|
d1681e |
(*trav_p) = (*trav_p)->next;
|
|
|
d1681e |
glusterfs_mgmt_pmap_signout (ctx,
|
|
|
d1681e |
victim->name);
|
|
|
d1681e |
- glusterfs_autoscale_threads (THIS->ctx, -1);
|
|
|
d1681e |
+ /* we need the protocol/server xlator here as 'this' */
|
|
|
d1681e |
+ glusterfs_autoscale_threads (ctx, -1, this);
|
|
|
d1681e |
default_notify (victim, GF_EVENT_CLEANUP, data);
|
|
|
d1681e |
-
|
|
|
d1681e |
}
|
|
|
d1681e |
break;
|
|
|
d1681e |
|
|
|
d1681e |
--
|
|
|
d1681e |
1.8.3.1
|
|
|
d1681e |
|