diff options
Diffstat (limited to '0445-feature-changelog-Avoid-thread-creation-if-xlator-is.patch')
-rw-r--r-- | 0445-feature-changelog-Avoid-thread-creation-if-xlator-is.patch | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/0445-feature-changelog-Avoid-thread-creation-if-xlator-is.patch b/0445-feature-changelog-Avoid-thread-creation-if-xlator-is.patch new file mode 100644 index 0000000..dea23f2 --- /dev/null +++ b/0445-feature-changelog-Avoid-thread-creation-if-xlator-is.patch @@ -0,0 +1,481 @@ +From dc03340654d921916ac3890d713fc84ef4bb1e28 Mon Sep 17 00:00:00 2001 +From: Mohit Agrawal <moagrawal@redhat.com> +Date: Sat, 29 Sep 2018 13:15:35 +0530 +Subject: [PATCH 445/449] feature/changelog: Avoid thread creation if xlator is + not enabled + +Problem: +Changelog creates threads even if the changelog is not enabled + +Background: +Changelog xlator broadly does two things + 1. Journalling - Cosumers are geo-rep and glusterfind + 2. Event Notification for registered events like (open, release etc) - + Consumers are bitrot, geo-rep + +The existing option "changelog.changelog" controls journalling and +there is no option to control event notification and is enabled by +default. So when bitrot/geo-rep is not enabled on the volume, threads +and resources(rpc and rbuf) related to event notifications consumes +resources and cpu cycle which is unnecessary. + +Solution: +The solution is to have two different options as below. + 1. changelog-notification : Event notifications + 2. changelog : Journalling + +This patch introduces the option "changelog-notification" which is +not exposed to user. When either bitrot or changelog (journalling) +is enabled, it internally enbales 'changelog-notification'. But +once the 'changelog-notification' is enabled, it will not be disabled +for the life time of the brick process even after bitrot and changelog +is disabled. As of now, rpc resource cleanup has lot of races and is +difficult to cleanup cleanly. If allowed, it leads to memory leaks +and crashes on enable/disable of bitrot or changelog (journal) in a +loop. Hence to be safer, the event notification is not disabled within +lifetime of process once enabled. + +> Change-Id: Ifd00286e0966049e8eb9f21567fe407cf11bb02a +> Updates: #475 +> Signed-off-by: Mohit Agrawal <moagrawal@redhat.com> +> (Cherry pick from commit 6de80bcd6366778ac34ce58ec496fa08cc02bd0b) +> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/21896/) + +BUG: 1790336 +Change-Id: Ifd00286e0966049e8eb9f21567fe407cf11bb02a +Signed-off-by: Mohit Agrawal <moagrawal@redhat.com> +Reviewed-on: https://code.engineering.redhat.com/gerrit/202778 +Tested-by: Mohit Agrawal <moagrawa@redhat.com> +Tested-by: RHGS Build Bot <nigelb@redhat.com> +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com> +--- + rpc/rpc-lib/src/rpcsvc.c | 26 ++-- + tests/basic/changelog/changelog-history.t | 12 +- + tests/bugs/bitrot/bug-1227996.t | 1 - + tests/bugs/bitrot/bug-1245981.t | 4 +- + xlators/features/changelog/src/changelog-helpers.h | 4 + + .../features/changelog/src/changelog-rpc-common.c | 3 + + xlators/features/changelog/src/changelog.c | 149 +++++++++++++++------ + xlators/mgmt/glusterd/src/glusterd-volgen.c | 13 ++ + 8 files changed, 154 insertions(+), 58 deletions(-) + +diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c +index b058932..3f184bf 100644 +--- a/rpc/rpc-lib/src/rpcsvc.c ++++ b/rpc/rpc-lib/src/rpcsvc.c +@@ -1865,6 +1865,18 @@ rpcsvc_program_unregister(rpcsvc_t *svc, rpcsvc_program_t *program) + goto out; + } + ++ pthread_rwlock_rdlock(&svc->rpclock); ++ { ++ list_for_each_entry(prog, &svc->programs, program) ++ { ++ if ((prog->prognum == program->prognum) && ++ (prog->progver == program->progver)) { ++ break; ++ } ++ } ++ } ++ pthread_rwlock_unlock(&svc->rpclock); ++ + ret = rpcsvc_program_unregister_portmap(program); + if (ret == -1) { + gf_log(GF_RPCSVC, GF_LOG_ERROR, +@@ -1881,17 +1893,6 @@ rpcsvc_program_unregister(rpcsvc_t *svc, rpcsvc_program_t *program) + goto out; + } + #endif +- pthread_rwlock_rdlock(&svc->rpclock); +- { +- list_for_each_entry(prog, &svc->programs, program) +- { +- if ((prog->prognum == program->prognum) && +- (prog->progver == program->progver)) { +- break; +- } +- } +- } +- pthread_rwlock_unlock(&svc->rpclock); + + gf_log(GF_RPCSVC, GF_LOG_DEBUG, + "Program unregistered: %s, Num: %d," +@@ -1912,6 +1913,9 @@ rpcsvc_program_unregister(rpcsvc_t *svc, rpcsvc_program_t *program) + + ret = 0; + out: ++ if (prog) ++ GF_FREE(prog); ++ + if (ret == -1) { + if (program) { + gf_log(GF_RPCSVC, GF_LOG_ERROR, +diff --git a/tests/basic/changelog/changelog-history.t b/tests/basic/changelog/changelog-history.t +index 3ce4098..b56e247 100644 +--- a/tests/basic/changelog/changelog-history.t ++++ b/tests/basic/changelog/changelog-history.t +@@ -5,6 +5,7 @@ + + cleanup; + ++SCRIPT_TIMEOUT=300 + HISTORY_BIN_PATH=$(dirname $0)/../../utils/changelog + build_tester $HISTORY_BIN_PATH/get-history.c -lgfchangelog + +@@ -68,18 +69,21 @@ TEST $CLI volume set $V0 changelog.changelog off + sleep 3 + time_after_disable=$(date '+%s') + ++TEST $CLI volume set $V0 changelog.changelog on ++sleep 5 ++ + #Passes, gives the changelogs till continuous changelogs are available + # but returns 1 +-EXPECT "1" $HISTORY_BIN_PATH/get-history $time_after_enable1 $time_in_sec_htime2 ++EXPECT_WITHIN 10 "1" $HISTORY_BIN_PATH/get-history $time_after_enable1 $time_in_sec_htime2 + + #Fails as start falls between htime files +-EXPECT "-3" $HISTORY_BIN_PATH/get-history $time_between_htime $time_in_sec_htime1 ++EXPECT_WITHIN 10 "-3" $HISTORY_BIN_PATH/get-history $time_between_htime $time_in_sec_htime1 + + #Passes as start and end falls in same htime file +-EXPECT "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime1 $time_in_sec_htime2 ++EXPECT_WITHIN 10 "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime1 $time_in_sec_htime2 + + #Passes, gives the changelogs till continuous changelogs are available +-EXPECT "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime2 $time_after_disable ++EXPECT_WITHIN 10 "0" $HISTORY_BIN_PATH/get-history $time_in_sec_htime2 $time_after_disable + + TEST rm $HISTORY_BIN_PATH/get-history + +diff --git a/tests/bugs/bitrot/bug-1227996.t b/tests/bugs/bitrot/bug-1227996.t +index 47ebc42..121c7b5 100644 +--- a/tests/bugs/bitrot/bug-1227996.t ++++ b/tests/bugs/bitrot/bug-1227996.t +@@ -17,7 +17,6 @@ TEST pidof glusterd; + ## Lets create and start the volume + TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1 + TEST $CLI volume start $V0 +- + ## Enable bitrot on volume $V0 + TEST $CLI volume bitrot $V0 enable + +diff --git a/tests/bugs/bitrot/bug-1245981.t b/tests/bugs/bitrot/bug-1245981.t +index 2bed4d9..f395525 100644 +--- a/tests/bugs/bitrot/bug-1245981.t ++++ b/tests/bugs/bitrot/bug-1245981.t +@@ -47,9 +47,9 @@ touch $M0/5 + sleep `expr $SLEEP_TIME \* 2` + + backpath=$(get_backend_paths $fname) +-TEST getfattr -m . -n trusted.bit-rot.signature $backpath ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.bit-rot.signature' check_for_xattr 'trusted.bit-rot.signature' $backpath + + backpath=$(get_backend_paths $M0/new_file) +-TEST getfattr -m . -n trusted.bit-rot.signature $backpath ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.bit-rot.signature' check_for_xattr 'trusted.bit-rot.signature' $backpath + + cleanup; +diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h +index 517c4dc..3afacc9 100644 +--- a/xlators/features/changelog/src/changelog-helpers.h ++++ b/xlators/features/changelog/src/changelog-helpers.h +@@ -190,8 +190,12 @@ typedef struct changelog_ev_selector { + + /* changelog's private structure */ + struct changelog_priv { ++ /* changelog journalling */ + gf_boolean_t active; + ++ /* changelog live notifications */ ++ gf_boolean_t rpc_active; ++ + /* to generate unique socket file per brick */ + char *changelog_brick; + +diff --git a/xlators/features/changelog/src/changelog-rpc-common.c b/xlators/features/changelog/src/changelog-rpc-common.c +index dcdcfb1..f2d1853 100644 +--- a/xlators/features/changelog/src/changelog-rpc-common.c ++++ b/xlators/features/changelog/src/changelog-rpc-common.c +@@ -263,6 +263,9 @@ changelog_rpc_server_destroy(xlator_t *this, rpcsvc_t *rpc, char *sockfile, + struct rpcsvc_program *prog = NULL; + rpc_transport_t *trans = NULL; + ++ if (!rpc) ++ return; ++ + while (*progs) { + prog = *progs; + (void)rpcsvc_program_unregister(rpc, prog); +diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c +index d9025f3..ff06c09 100644 +--- a/xlators/features/changelog/src/changelog.c ++++ b/xlators/features/changelog/src/changelog.c +@@ -34,6 +34,12 @@ static struct changelog_bootstrap cb_bootstrap[] = { + }, + }; + ++static int ++changelog_init_rpc(xlator_t *this, changelog_priv_t *priv); ++ ++static int ++changelog_init(xlator_t *this, changelog_priv_t *priv); ++ + /* Entry operations - TYPE III */ + + /** +@@ -2008,6 +2014,11 @@ notify(xlator_t *this, int event, void *data, ...) + uint64_t clntcnt = 0; + changelog_clnt_t *conn = NULL; + gf_boolean_t cleanup_notify = _gf_false; ++ char sockfile[UNIX_PATH_MAX] = { ++ 0, ++ }; ++ rpcsvc_listener_t *listener = NULL; ++ rpcsvc_listener_t *next = NULL; + + INIT_LIST_HEAD(&queue); + +@@ -2021,23 +2032,40 @@ notify(xlator_t *this, int event, void *data, ...) + "cleanup changelog rpc connection of brick %s", + priv->victim->name); + +- this->cleanup_starting = 1; +- changelog_destroy_rpc_listner(this, priv); +- conn = &priv->connections; +- if (conn) +- changelog_ev_cleanup_connections(this, conn); +- xprtcnt = GF_ATOMIC_GET(priv->xprtcnt); +- clntcnt = GF_ATOMIC_GET(priv->clntcnt); +- +- if (!xprtcnt && !clntcnt) { +- LOCK(&priv->lock); +- { +- cleanup_notify = priv->notify_down; +- priv->notify_down = _gf_true; ++ if (priv->rpc_active) { ++ this->cleanup_starting = 1; ++ changelog_destroy_rpc_listner(this, priv); ++ conn = &priv->connections; ++ if (conn) ++ changelog_ev_cleanup_connections(this, conn); ++ xprtcnt = GF_ATOMIC_GET(priv->xprtcnt); ++ clntcnt = GF_ATOMIC_GET(priv->clntcnt); ++ if (!xprtcnt && !clntcnt) { ++ LOCK(&priv->lock); ++ { ++ cleanup_notify = priv->notify_down; ++ priv->notify_down = _gf_true; ++ } ++ UNLOCK(&priv->lock); ++ list_for_each_entry_safe(listener, next, &priv->rpc->listeners, ++ list) ++ { ++ if (listener->trans) { ++ rpc_transport_unref(listener->trans); ++ } ++ } ++ CHANGELOG_MAKE_SOCKET_PATH(priv->changelog_brick, sockfile, ++ UNIX_PATH_MAX); ++ sys_unlink(sockfile); ++ if (priv->rpc) { ++ rpcsvc_destroy(priv->rpc); ++ priv->rpc = NULL; ++ } ++ if (!cleanup_notify) ++ default_notify(this, GF_EVENT_PARENT_DOWN, data); + } +- UNLOCK(&priv->lock); +- if (!cleanup_notify) +- default_notify(this, GF_EVENT_PARENT_DOWN, data); ++ } else { ++ default_notify(this, GF_EVENT_PARENT_DOWN, data); + } + goto out; + } +@@ -2425,6 +2453,22 @@ changelog_barrier_pthread_destroy(changelog_priv_t *priv) + LOCK_DESTROY(&priv->bflags.lock); + } + ++static void ++changelog_cleanup_rpc(xlator_t *this, changelog_priv_t *priv) ++{ ++ /* terminate rpc server */ ++ if (!this->cleanup_starting) ++ changelog_destroy_rpc_listner(this, priv); ++ ++ (void)changelog_cleanup_rpc_threads(this, priv); ++ /* cleanup rot buffs */ ++ rbuf_dtor(priv->rbuf); ++ ++ /* cleanup poller thread */ ++ if (priv->poller) ++ (void)changelog_thread_cleanup(this, priv->poller); ++} ++ + int + reconfigure(xlator_t *this, dict_t *options) + { +@@ -2433,6 +2477,9 @@ reconfigure(xlator_t *this, dict_t *options) + changelog_priv_t *priv = NULL; + gf_boolean_t active_earlier = _gf_true; + gf_boolean_t active_now = _gf_true; ++ gf_boolean_t rpc_active_earlier = _gf_true; ++ gf_boolean_t rpc_active_now = _gf_true; ++ gf_boolean_t iniate_rpc = _gf_false; + changelog_time_slice_t *slice = NULL; + changelog_log_data_t cld = { + 0, +@@ -2454,6 +2501,7 @@ reconfigure(xlator_t *this, dict_t *options) + + ret = -1; + active_earlier = priv->active; ++ rpc_active_earlier = priv->rpc_active; + + /* first stop the rollover and the fsync thread */ + changelog_cleanup_helper_threads(this, priv); +@@ -2487,6 +2535,29 @@ reconfigure(xlator_t *this, dict_t *options) + goto out; + + GF_OPTION_RECONF("changelog", active_now, options, bool, out); ++ GF_OPTION_RECONF("changelog-notification", rpc_active_now, options, bool, ++ out); ++ ++ /* If journalling is enabled, enable rpc notifications */ ++ if (active_now && !active_earlier) { ++ if (!rpc_active_earlier) ++ iniate_rpc = _gf_true; ++ } ++ ++ if (rpc_active_now && !rpc_active_earlier) { ++ iniate_rpc = _gf_true; ++ } ++ ++ /* TODO: Disable of changelog-notifications is not supported for now ++ * as there is no clean way of cleaning up of rpc resources ++ */ ++ ++ if (iniate_rpc) { ++ ret = changelog_init_rpc(this, priv); ++ if (ret) ++ goto out; ++ priv->rpc_active = _gf_true; ++ } + + /** + * changelog_handle_change() handles changes that could possibly +@@ -2618,6 +2689,7 @@ changelog_init_options(xlator_t *this, changelog_priv_t *priv) + goto dealloc_2; + + GF_OPTION_INIT("changelog", priv->active, bool, dealloc_2); ++ GF_OPTION_INIT("changelog-notification", priv->rpc_active, bool, dealloc_2); + GF_OPTION_INIT("capture-del-path", priv->capture_del_path, bool, dealloc_2); + + GF_OPTION_INIT("op-mode", tmp, str, dealloc_2); +@@ -2656,22 +2728,6 @@ error_return: + return -1; + } + +-static void +-changelog_cleanup_rpc(xlator_t *this, changelog_priv_t *priv) +-{ +- /* terminate rpc server */ +- if (!this->cleanup_starting) +- changelog_destroy_rpc_listner(this, priv); +- +- (void)changelog_cleanup_rpc_threads(this, priv); +- /* cleanup rot buffs */ +- rbuf_dtor(priv->rbuf); +- +- /* cleanup poller thread */ +- if (priv->poller) +- (void)changelog_thread_cleanup(this, priv->poller); +-} +- + static int + changelog_init_rpc(xlator_t *this, changelog_priv_t *priv) + { +@@ -2768,10 +2824,13 @@ init(xlator_t *this) + INIT_LIST_HEAD(&priv->queue); + priv->barrier_enabled = _gf_false; + +- /* RPC ball rolling.. */ +- ret = changelog_init_rpc(this, priv); +- if (ret) +- goto cleanup_barrier; ++ if (priv->rpc_active || priv->active) { ++ /* RPC ball rolling.. */ ++ ret = changelog_init_rpc(this, priv); ++ if (ret) ++ goto cleanup_barrier; ++ priv->rpc_active = _gf_true; ++ } + + ret = changelog_init(this, priv); + if (ret) +@@ -2783,7 +2842,9 @@ init(xlator_t *this) + return 0; + + cleanup_rpc: +- changelog_cleanup_rpc(this, priv); ++ if (priv->rpc_active) { ++ changelog_cleanup_rpc(this, priv); ++ } + cleanup_barrier: + changelog_barrier_pthread_destroy(priv); + cleanup_options: +@@ -2808,9 +2869,10 @@ fini(xlator_t *this) + priv = this->private; + + if (priv) { +- /* terminate RPC server/threads */ +- changelog_cleanup_rpc(this, priv); +- ++ if (priv->active || priv->rpc_active) { ++ /* terminate RPC server/threads */ ++ changelog_cleanup_rpc(this, priv); ++ } + /* call barrier_disable to cancel timer */ + if (priv->barrier_enabled) + __chlog_barrier_disable(this, &queue); +@@ -2879,6 +2941,13 @@ struct volume_options options[] = { + .flags = OPT_FLAG_SETTABLE, + .level = OPT_STATUS_BASIC, + .tags = {"journal", "georep", "glusterfind"}}, ++ {.key = {"changelog-notification"}, ++ .type = GF_OPTION_TYPE_BOOL, ++ .default_value = "off", ++ .description = "enable/disable changelog live notification", ++ .op_version = {3}, ++ .level = OPT_STATUS_BASIC, ++ .tags = {"bitrot", "georep"}}, + {.key = {"changelog-brick"}, + .type = GF_OPTION_TYPE_PATH, + .description = "brick path to generate unique socket file name." +diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c +index 16346e7..13f84ea 100644 +--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c ++++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c +@@ -1876,6 +1876,19 @@ brick_graph_add_changelog(volgen_graph_t *graph, glusterd_volinfo_t *volinfo, + ret = xlator_set_fixed_option(xl, "changelog-dir", changelog_basepath); + if (ret) + goto out; ++ ++ ret = glusterd_is_bitrot_enabled(volinfo); ++ if (ret == -1) { ++ goto out; ++ } else if (ret) { ++ ret = xlator_set_fixed_option(xl, "changelog-notification", "on"); ++ if (ret) ++ goto out; ++ } else { ++ ret = xlator_set_fixed_option(xl, "changelog-notification", "off"); ++ if (ret) ++ goto out; ++ } + out: + return ret; + } +-- +1.8.3.1 + |