7f4c2a
From 7c8df30e18538917e361faff2ed032024d5ba16f Mon Sep 17 00:00:00 2001
7f4c2a
From: Gaurav Kumar Garg <ggarg@redhat.com>
7f4c2a
Date: Fri, 5 Jun 2015 13:58:28 +0530
7f4c2a
Subject: [PATCH 117/129] features/bitrot: tuanble object signing waiting time value for bitrot
7f4c2a
7f4c2a
 Currently bitrot using 120 second waiting time for object to be signed
7f4c2a
 after all fop's released. This signing waiting time value should be tunable.
7f4c2a
7f4c2a
 Command for changing the signing waiting time will be
7f4c2a
 #gluster volume bitrot <VOLNAME> signing-time <waiting time value in second>
7f4c2a
7f4c2a
BUG: 1227900
7f4c2a
Change-Id: I6f63cc77c996bfc576a05801be39a2028e5db866
7f4c2a
Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com>
7f4c2a
upstream patch url: http://review.gluster.org/#/c/11105/
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/50741
7f4c2a
Reviewed-by: Venky Shankar <vshankar@redhat.com>
7f4c2a
Tested-by: Venky Shankar <vshankar@redhat.com>
7f4c2a
---
7f4c2a
 cli/src/cli-cmd-parser.c                        |   33 ++++++++++++++-
7f4c2a
 rpc/xdr/src/cli1-xdr.x                          |    1 +
7f4c2a
 tests/bugs/bitrot/bug-1228680.t                 |   31 ++++++++++++++
7f4c2a
 xlators/features/bit-rot/src/bitd/bit-rot.c     |   37 ++++++++++++++---
7f4c2a
 xlators/features/bit-rot/src/bitd/bit-rot.h     |    2 +-
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-bitrot.c     |   49 +++++++++++++++++++++++
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-volgen.c     |   33 +++++++++++++++
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-volume-set.c |    7 +++
7f4c2a
 8 files changed, 182 insertions(+), 11 deletions(-)
7f4c2a
 create mode 100644 tests/bugs/bitrot/bug-1228680.t
7f4c2a
7f4c2a
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
7f4c2a
index 2ddbe88..51da792 100644
7f4c2a
--- a/cli/src/cli-cmd-parser.c
7f4c2a
+++ b/cli/src/cli-cmd-parser.c
7f4c2a
@@ -5018,8 +5018,8 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
7f4c2a
         char               *volname               = NULL;
7f4c2a
         char               *opwords[]             = {"enable", "disable",
7f4c2a
                                                      "scrub-throttle",
7f4c2a
-                                                     "scrub-frequency",
7f4c2a
-                                                     "scrub", NULL};
7f4c2a
+                                                     "scrub-frequency", "scrub",
7f4c2a
+                                                     "signing-time", NULL};
7f4c2a
         char               *scrub_throt_values[]  = {"lazy", "normal",
7f4c2a
                                                      "aggressive", NULL};
7f4c2a
         char               *scrub_freq_values[]   = {"hourly",
7f4c2a
@@ -5030,6 +5030,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
7f4c2a
                                                       NULL};
7f4c2a
         dict_t             *dict                  = NULL;
7f4c2a
         gf_bitrot_type     type                   = GF_BITROT_OPTION_TYPE_NONE;
7f4c2a
+        uint32_t           expiry_time            = 0;
7f4c2a
 
7f4c2a
         GF_ASSERT (words);
7f4c2a
         GF_ASSERT (options);
7f4c2a
@@ -5039,7 +5040,7 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
         if (wordcount < 4 || wordcount > 5) {
7f4c2a
-                gf_log ("", GF_LOG_ERROR, "Invalid syntax");
7f4c2a
+                gf_log ("cli", GF_LOG_ERROR, "Invalid syntax");
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
@@ -5167,6 +5168,32 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options)
7f4c2a
                                 goto set_type;
7f4c2a
                         }
7f4c2a
                 }
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        if (!strcmp (words[3], "signing-time")) {
7f4c2a
+                if (!words[4]) {
7f4c2a
+                        cli_err ("Missing signing-time value for bitrot "
7f4c2a
+                                 "option");
7f4c2a
+                        ret = -1;
7f4c2a
+                        goto out;
7f4c2a
+                } else {
7f4c2a
+                        type = GF_BITROT_OPTION_TYPE_EXPIRY_TIME;
7f4c2a
+
7f4c2a
+                        expiry_time = strtol (words[4], NULL, 0);
7f4c2a
+                        if (expiry_time < 1) {
7f4c2a
+                                cli_err ("Expiry time  value should not be less"
7f4c2a
+                                         " than 1");
7f4c2a
+                                ret = -1;
7f4c2a
+                                goto out;
7f4c2a
+                        }
7f4c2a
+
7f4c2a
+                        ret = dict_set_int32 (dict, "expiry-time", expiry_time);
7f4c2a
+                        if (ret) {
7f4c2a
+                                cli_out ("Failed to set dict for bitrot");
7f4c2a
+                                goto out;
7f4c2a
+                        }
7f4c2a
+                        goto set_type;
7f4c2a
+                }
7f4c2a
         } else {
7f4c2a
                 cli_err ("Invalid option %s for bitrot. Please enter valid "
7f4c2a
                          "bitrot option", words[3]);
7f4c2a
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
7f4c2a
index 0d5d3cc..34f324f 100644
7f4c2a
--- a/rpc/xdr/src/cli1-xdr.x
7f4c2a
+++ b/rpc/xdr/src/cli1-xdr.x
7f4c2a
@@ -40,6 +40,7 @@ enum gf_bitrot_type {
7f4c2a
         GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE,
7f4c2a
         GF_BITROT_OPTION_TYPE_SCRUB_FREQ,
7f4c2a
         GF_BITROT_OPTION_TYPE_SCRUB,
7f4c2a
+        GF_BITROT_OPTION_TYPE_EXPIRY_TIME,
7f4c2a
         GF_BITROT_OPTION_TYPE_MAX
7f4c2a
 };
7f4c2a
 
7f4c2a
diff --git a/tests/bugs/bitrot/bug-1228680.t b/tests/bugs/bitrot/bug-1228680.t
7f4c2a
new file mode 100644
7f4c2a
index 0000000..c77beed
7f4c2a
--- /dev/null
7f4c2a
+++ b/tests/bugs/bitrot/bug-1228680.t
7f4c2a
@@ -0,0 +1,31 @@
7f4c2a
+#!/bin/bash
7f4c2a
+
7f4c2a
+## Test case for bitrot
7f4c2a
+## Tunable object signing waiting time value for bitrot.
7f4c2a
+
7f4c2a
+
7f4c2a
+. $(dirname $0)/../../include.rc
7f4c2a
+. $(dirname $0)/../../volume.rc
7f4c2a
+. $(dirname $0)/../../cluster.rc
7f4c2a
+
7f4c2a
+cleanup;
7f4c2a
+
7f4c2a
+
7f4c2a
+## Start glusterd
7f4c2a
+TEST glusterd;
7f4c2a
+TEST pidof glusterd;
7f4c2a
+
7f4c2a
+## Lets create and start the volume
7f4c2a
+TEST $CLI volume create $V0 $H0:$B0/${V0}0 $H0:$B0/${V0}1
7f4c2a
+TEST $CLI volume start $V0
7f4c2a
+
7f4c2a
+## Enable bitrot on volume $V0
7f4c2a
+TEST $CLI volume bitrot $V0 enable
7f4c2a
+
7f4c2a
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" get_bitd_count
7f4c2a
+
7f4c2a
+## Set object expiry time value 20 second.
7f4c2a
+TEST $CLI volume bitrot $V0 signing-time 20
7f4c2a
+
7f4c2a
+
7f4c2a
+cleanup;
7f4c2a
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c
7f4c2a
index 8149083..a4821ba 100644
7f4c2a
--- a/xlators/features/bit-rot/src/bitd/bit-rot.c
7f4c2a
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.c
7f4c2a
@@ -753,8 +753,11 @@ br_initialize_timer (xlator_t *this, br_object_t *object, br_child_t *child,
7f4c2a
                 goto out;
7f4c2a
         INIT_LIST_HEAD (&timer->entry);
7f4c2a
 
7f4c2a
+        timer->expires  = (priv->expiry_time >> 1);
7f4c2a
+        if (!timer->expires)
7f4c2a
+                timer->expires = 1;
7f4c2a
+
7f4c2a
         timer->data     = object;
7f4c2a
-        timer->expires  = priv->expiry_time;
7f4c2a
         timer->function = br_add_object_to_queue;
7f4c2a
         gf_tw_add_timer (priv->timer_wheel, timer);
7f4c2a
 
7f4c2a
@@ -1491,12 +1494,28 @@ br_rate_limit_signer (xlator_t *this, int child_count, int numbricks)
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int32_t
7f4c2a
+br_signer_handle_options (xlator_t *this, br_private_t *priv, dict_t *options)
7f4c2a
+{
7f4c2a
+        if (options)
7f4c2a
+                GF_OPTION_RECONF ("expiry-time", priv->expiry_time,
7f4c2a
+                                  options, uint32, error_return);
7f4c2a
+        else
7f4c2a
+                GF_OPTION_INIT ("expiry-time", priv->expiry_time,
7f4c2a
+                                uint32, error_return);
7f4c2a
+
7f4c2a
+        return 0;
7f4c2a
+
7f4c2a
+error_return:
7f4c2a
+        return -1;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static int32_t
7f4c2a
 br_signer_init (xlator_t *this, br_private_t *priv)
7f4c2a
 {
7f4c2a
         int32_t ret = 0;
7f4c2a
         int numbricks = 0;
7f4c2a
 
7f4c2a
-        GF_OPTION_INIT ("expiry-time", priv->expiry_time, int32, error_return);
7f4c2a
+        GF_OPTION_INIT ("expiry-time", priv->expiry_time, uint32, error_return);
7f4c2a
         GF_OPTION_INIT ("brick-count", numbricks, int32, error_return);
7f4c2a
 
7f4c2a
         ret = br_rate_limit_signer (this, priv->child_count, numbricks);
7f4c2a
@@ -1581,6 +1600,8 @@ init (xlator_t *this)
7f4c2a
 
7f4c2a
         if (!priv->iamscrubber) {
7f4c2a
                 ret = br_signer_init (this, priv);
7f4c2a
+                if (!ret)
7f4c2a
+                        ret = br_signer_handle_options (this, priv, NULL);
7f4c2a
         } else {
7f4c2a
                 ret = br_scrubber_init (this, priv);
7f4c2a
                 if (!ret)
7f4c2a
@@ -1651,8 +1672,12 @@ reconfigure (xlator_t *this, dict_t *options)
7f4c2a
 
7f4c2a
         priv = this->private;
7f4c2a
 
7f4c2a
-        if (!priv->iamscrubber)
7f4c2a
+        if (!priv->iamscrubber) {
7f4c2a
+                ret = br_signer_handle_options (this, priv, options);
7f4c2a
+                if (ret)
7f4c2a
+                        goto err;
7f4c2a
                 return 0;
7f4c2a
+        }
7f4c2a
 
7f4c2a
         ret = br_scrubber_handle_options (this, priv, options);
7f4c2a
         if (ret)
7f4c2a
@@ -1700,10 +1725,8 @@ struct xlator_cbks cbks;
7f4c2a
 struct volume_options options[] = {
7f4c2a
         { .key = {"expiry-time"},
7f4c2a
           .type = GF_OPTION_TYPE_INT,
7f4c2a
-          /* Let the default timer be half the value of the wait time for
7f4c2a
-           * sining (which is 120 as of now) */
7f4c2a
-          .default_value = "60",
7f4c2a
-          .description = "default time duration for which an object waits "
7f4c2a
+          .default_value = "120",
7f4c2a
+          .description = "Waiting time for an object on which it waits "
7f4c2a
                          "before it is signed",
7f4c2a
         },
7f4c2a
         { .key = {"brick-count"},
7f4c2a
diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h
7f4c2a
index 40e02eb..562f17e 100644
7f4c2a
--- a/xlators/features/bit-rot/src/bitd/bit-rot.h
7f4c2a
+++ b/xlators/features/bit-rot/src/bitd/bit-rot.h
7f4c2a
@@ -162,7 +162,7 @@ struct br_private {
7f4c2a
                                              and ready to be picked up for
7f4c2a
                                              signing and the workers which sign
7f4c2a
                                              the objects */
7f4c2a
-        int32_t expiry_time;              /* objects "wait" time */
7f4c2a
+        uint32_t expiry_time;              /* objects "wait" time */
7f4c2a
 
7f4c2a
         br_tbf_t *tbf;                    /* token bucket filter */
7f4c2a
 
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-bitrot.c b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
7f4c2a
index 08976cf..1563102 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-bitrot.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-bitrot.c
7f4c2a
@@ -37,6 +37,7 @@ const char *gd_bitrot_op_list[GF_BITROT_OPTION_TYPE_MAX] = {
7f4c2a
         [GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE]  = "scrub-throttle",
7f4c2a
         [GF_BITROT_OPTION_TYPE_SCRUB_FREQ]      = "scrub-frequency",
7f4c2a
         [GF_BITROT_OPTION_TYPE_SCRUB]           = "scrub",
7f4c2a
+        [GF_BITROT_OPTION_TYPE_EXPIRY_TIME]     = "expiry-time",
7f4c2a
 };
7f4c2a
 
7f4c2a
 int
7f4c2a
@@ -248,6 +249,46 @@ out:
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
+glusterd_bitrot_expiry_time (glusterd_volinfo_t *volinfo, dict_t *dict,
7f4c2a
+                             char *key, char **op_errstr)
7f4c2a
+{
7f4c2a
+        int32_t        ret                  = -1;
7f4c2a
+        uint32_t       expiry_time          = 0;
7f4c2a
+        xlator_t       *this                = NULL;
7f4c2a
+        char           dkey[1024]           = {0,};
7f4c2a
+        char           *key_value           = NULL;
7f4c2a
+
7f4c2a
+        this = THIS;
7f4c2a
+        GF_ASSERT (this);
7f4c2a
+
7f4c2a
+        ret = dict_get_uint32 (dict, "expiry-time", &expiry_time);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "Unable to get bitrot expiry"
7f4c2a
+                        " timer value.");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        snprintf (dkey, sizeof (dkey), "%d", expiry_time);
7f4c2a
+        key_value = gf_strdup (dkey);
7f4c2a
+
7f4c2a
+        ret = dict_set_dynstr (volinfo->dict, key, key_value);
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "Failed to set option %s",
7f4c2a
+                        key);
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        ret = glusterd_bitdsvc_reconfigure ();
7f4c2a
+        if (ret) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR, "Failed to reconfigure bitrot"
7f4c2a
+                         "services");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+out:
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static int
7f4c2a
 glusterd_bitrot_enable (glusterd_volinfo_t *volinfo, char **op_errstr)
7f4c2a
 {
7f4c2a
         int32_t         ret             = -1;
7f4c2a
@@ -476,6 +517,14 @@ glusterd_op_bitrot (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
7f4c2a
                         goto out;
7f4c2a
                 break;
7f4c2a
 
7f4c2a
+        case GF_BITROT_OPTION_TYPE_EXPIRY_TIME:
7f4c2a
+                ret = glusterd_bitrot_expiry_time (volinfo, dict,
7f4c2a
+                                                   "features.expiry-time",
7f4c2a
+                                                   op_errstr);
7f4c2a
+                if (ret)
7f4c2a
+                        goto out;
7f4c2a
+                break;
7f4c2a
+
7f4c2a
         default:
7f4c2a
                 gf_asprintf (op_errstr, "Bitrot command failed. Invalid "
7f4c2a
                              "opcode");
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
index 9c09c78..a79e129 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
@@ -3743,6 +3743,33 @@ gd_get_matching_option (char **options, char *option)
7f4c2a
 }
7f4c2a
 
7f4c2a
 static int
7f4c2a
+bitrot_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
7f4c2a
+                       void *param)
7f4c2a
+{
7f4c2a
+        xlator_t           *xl                 = NULL;
7f4c2a
+        char               *bitrot_option      = NULL;
7f4c2a
+        int                 ret                = 0;
7f4c2a
+        glusterd_volinfo_t *volinfo            = NULL;
7f4c2a
+
7f4c2a
+        volinfo = param;
7f4c2a
+
7f4c2a
+        xl = first_of (graph);
7f4c2a
+
7f4c2a
+        if (!strcmp (vme->option, "expiry-time")) {
7f4c2a
+                ret = gf_asprintf (&bitrot_option, "expiry-time");
7f4c2a
+                if (ret != -1) {
7f4c2a
+                        ret = xlator_set_option (xl, bitrot_option, vme->value);
7f4c2a
+                        GF_FREE (bitrot_option);
7f4c2a
+                }
7f4c2a
+
7f4c2a
+                if (ret)
7f4c2a
+                        return -1;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static int
7f4c2a
 scrubber_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,
7f4c2a
                        void *param)
7f4c2a
 {
7f4c2a
@@ -4981,6 +5008,12 @@ build_bitd_volume_graph (volgen_graph_t *graph,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        ret = volgen_graph_set_options_generic (&cgraph, set_dict,
7f4c2a
+                                                volinfo,
7f4c2a
+                                                bitrot_option_handler);
7f4c2a
+        if (ret)
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
         ret = volgen_graph_merge_sub (graph, &cgraph, clusters);
7f4c2a
         if (ret)
7f4c2a
                 goto out;
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
index 624e577..415bc01 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
@@ -1866,6 +1866,13 @@ struct volopt_map_entry glusterd_volopt_map[] = {
7f4c2a
           .flags      = OPT_FLAG_FORCE,
7f4c2a
           .type       = NO_DOC,
7f4c2a
         },
7f4c2a
+        { .key        = "features.expiry-time",
7f4c2a
+          .voltype    = "features/bitrot",
7f4c2a
+          .value      = "120",
7f4c2a
+          .option     = "expiry-time",
7f4c2a
+          .op_version = GD_OP_VERSION_3_7_0,
7f4c2a
+          .type       = NO_DOC,
7f4c2a
+        },
7f4c2a
         /* Upcall translator options */
7f4c2a
         { .key         = "features.cache-invalidation",
7f4c2a
           .voltype     = "features/upcall",
7f4c2a
-- 
7f4c2a
1.7.1
7f4c2a