7f4c2a
From e9fd069cea243707a47d9892f04e488ddae6012c Mon Sep 17 00:00:00 2001
7f4c2a
From: Dan Lambright <dlambrig@redhat.com>
7f4c2a
Date: Sat, 27 Jun 2015 07:36:36 -0400
7f4c2a
Subject: [PATCH 187/190] tier/ctr: Ignore creation of T file and Ctr Lookup heal improvememnts
7f4c2a
7f4c2a
This is a back port of 11334
7f4c2a
7f4c2a
1) Ignore creation of T file in ctr_mknod
7f4c2a
2) Ignore lookup for T file in ctr_lookup
7f4c2a
3) Ctr_lookup:
7f4c2a
    a. If the gfid and pgfid in empty dont record
7f4c2a
    b. Decreased log level for multiple heal attempts
7f4c2a
    c. Inode/File heal happens after an expiry period, which is configurable.
7f4c2a
    d. Hardlink heal happens after an expiry period, which is configurable.
7f4c2a
7f4c2a
> Change-Id: Id8eb5092e78beaec22d05f5283645081619e2452
7f4c2a
> BUG: 1235269
7f4c2a
> Signed-off-by: Joseph Fernandes <josferna@redhat.com>
7f4c2a
> Reviewed-on: http://review.gluster.org/11334
7f4c2a
> Tested-by: Gluster Build System <jenkins@build.gluster.com>
7f4c2a
> Reviewed-by: Dan Lambright <dlambrig@redhat.com>
7f4c2a
> Tested-by: Dan Lambright <dlambrig@redhat.com>
7f4c2a
7f4c2a
Change-Id: I244f3155bdb27227c060cd256c5801ec8ea7cc90
7f4c2a
BUG: 1232625
7f4c2a
Signed-off-by: Dan Lambright <dlambrig@redhat.com>
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/51756
7f4c2a
Reviewed-by: Joseph Fernandes <josferna@redhat.com>
7f4c2a
Tested-by: Joseph Fernandes <josferna@redhat.com>
7f4c2a
---
7f4c2a
 libglusterfs/src/gfdb/gfdb_data_store_types.h      |   15 ++-
7f4c2a
 libglusterfs/src/gfdb/gfdb_sqlite3.c               |    2 -
7f4c2a
 libglusterfs/src/gfdb/gfdb_sqlite3_helper.c        |   49 ++++++---
7f4c2a
 xlators/cluster/dht/src/tier.h                     |    5 +-
7f4c2a
 .../changetimerecorder/src/changetimerecorder.c    |  121 +++++++++++++++++---
7f4c2a
 .../features/changetimerecorder/src/ctr-helper.c   |   10 ++
7f4c2a
 .../features/changetimerecorder/src/ctr-helper.h   |  108 +++++++++++++++++-
7f4c2a
 .../changetimerecorder/src/ctr-xlator-ctx.c        |   35 ++++++-
7f4c2a
 .../changetimerecorder/src/ctr-xlator-ctx.h        |    4 +
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-volgen.c        |    8 ++
7f4c2a
 xlators/mgmt/glusterd/src/glusterd-volume-set.c    |   24 ++++
7f4c2a
 11 files changed, 336 insertions(+), 45 deletions(-)
7f4c2a
7f4c2a
diff --git a/libglusterfs/src/gfdb/gfdb_data_store_types.h b/libglusterfs/src/gfdb/gfdb_data_store_types.h
7f4c2a
index f642c63..fb41c38 100644
7f4c2a
--- a/libglusterfs/src/gfdb/gfdb_data_store_types.h
7f4c2a
+++ b/libglusterfs/src/gfdb/gfdb_data_store_types.h
7f4c2a
@@ -26,6 +26,16 @@
7f4c2a
 #include "dict.h"
7f4c2a
 #include "libglusterfs-messages.h"
7f4c2a
 
7f4c2a
+/*
7f4c2a
+ * Helps in dynamically choosing log level
7f4c2a
+ * */
7f4c2a
+static inline gf_loglevel_t
7f4c2a
+_gfdb_log_level (gf_loglevel_t given_level,
7f4c2a
+                 gf_boolean_t ignore_level)
7f4c2a
+{
7f4c2a
+        return (ignore_level) ? GF_LOG_DEBUG : given_level;
7f4c2a
+}
7f4c2a
+
7f4c2a
 typedef enum gf_db_operation {
7f4c2a
         GFDB_INVALID_DB_OP = -1,
7f4c2a
         /* Query DB OPS : All the Query DB_OP should be added */
7f4c2a
@@ -71,8 +81,6 @@ typedef enum gf_db_operation {
7f4c2a
 #define GF_COL_LINK_UPDATE              "LINK_UPDATE"
7f4c2a
 
7f4c2a
 
7f4c2a
-
7f4c2a
-
7f4c2a
 /***********************Time related********************************/
7f4c2a
 /*1 sec = 1000000 microsec*/
7f4c2a
 #define GFDB_MICROSEC         1000000
7f4c2a
@@ -305,6 +313,9 @@ typedef struct gfdb_db_record {
7f4c2a
         /* Global flag to Record/Not Record wind or wind time.
7f4c2a
          * This flag will overrule do_record_uwind_time*/
7f4c2a
         gf_boolean_t                    do_record_times;
7f4c2a
+        /* Ignoring errors while inserting.
7f4c2a
+         * */
7f4c2a
+        gf_boolean_t                    ignore_errors;
7f4c2a
 } gfdb_db_record_t;
7f4c2a
 
7f4c2a
 
7f4c2a
diff --git a/libglusterfs/src/gfdb/gfdb_sqlite3.c b/libglusterfs/src/gfdb/gfdb_sqlite3.c
7f4c2a
index 7eca03f..94553fb 100644
7f4c2a
--- a/libglusterfs/src/gfdb/gfdb_sqlite3.c
7f4c2a
+++ b/libglusterfs/src/gfdb/gfdb_sqlite3.c
7f4c2a
@@ -176,8 +176,6 @@ sql_stmt_fini (char **sql_stmt)
7f4c2a
 
7f4c2a
 /******************************************************************************
7f4c2a
  *                      DB Essential functions used by
7f4c2a
- *                      create/insert/delete/update/query functions
7f4c2a
- *                      > execute_sqlstmt ()
7f4c2a
  *                      > gf_open_sqlite3_conn ()
7f4c2a
  *                      > gf_close_sqlite3_conn ()
7f4c2a
  * ***************************************************************************/
7f4c2a
diff --git a/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c b/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c
7f4c2a
index f3e0e97..40ee24c 100644
7f4c2a
--- a/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c
7f4c2a
+++ b/libglusterfs/src/gfdb/gfdb_sqlite3_helper.c
7f4c2a
@@ -9,7 +9,7 @@
7f4c2a
 */
7f4c2a
 
7f4c2a
 #include "gfdb_sqlite3_helper.h"
7f4c2a
-#include "libglusterfs-messages.h"
7f4c2a
+
7f4c2a
 
7f4c2a
 #define GFDB_SQL_STMT_SIZE 256
7f4c2a
 
7f4c2a
@@ -309,7 +309,8 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
                    char                 *pargfid,
7f4c2a
                    char                 *basename,
7f4c2a
                    char                 *basepath,
7f4c2a
-                   gf_boolean_t         link_consistency)
7f4c2a
+                   gf_boolean_t         link_consistency,
7f4c2a
+                   gf_boolean_t         ignore_errors)
7f4c2a
 {
7f4c2a
         int ret = -1;
7f4c2a
         sqlite3_stmt *insert_stmt = NULL;
7f4c2a
@@ -332,8 +333,11 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
         ret = sqlite3_prepare (sql_conn->sqlite3_db_conn, insert_str, -1,
7f4c2a
                                 &insert_stmt, 0);
7f4c2a
         if (ret != SQLITE_OK) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
-                        LG_MSG_PREPARE_FAILED, "Failed preparing insert "
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors),
7f4c2a
+                        0,
7f4c2a
+                        LG_MSG_PREPARE_FAILED,
7f4c2a
+                        "Failed preparing insert "
7f4c2a
                         "statment %s : %s", insert_str,
7f4c2a
                         sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
@@ -343,8 +347,11 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
         /*Bind gfid*/
7f4c2a
         ret = sqlite3_bind_text (insert_stmt, 1, gfid, -1, NULL);
7f4c2a
         if (ret != SQLITE_OK) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
-                        LG_MSG_BINDING_FAILED, "Failed binding gfid %s : %s",
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors),
7f4c2a
+                        0,
7f4c2a
+                        LG_MSG_BINDING_FAILED,
7f4c2a
+                        "Failed binding gfid %s : %s",
7f4c2a
                         gfid, sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
                 goto out;
7f4c2a
@@ -353,8 +360,10 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
         /*Bind pargfid*/
7f4c2a
         ret = sqlite3_bind_text (insert_stmt, 2, pargfid, -1, NULL);
7f4c2a
         if (ret != SQLITE_OK) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
-                        LG_MSG_BINDING_FAILED, "Failed binding parent gfid %s "
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors),
7f4c2a
+                        0, LG_MSG_BINDING_FAILED,
7f4c2a
+                        "Failed binding parent gfid %s "
7f4c2a
                         ": %s", pargfid,
7f4c2a
                         sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
@@ -364,8 +373,9 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
         /*Bind basename*/
7f4c2a
         ret = sqlite3_bind_text (insert_stmt, 3, basename, -1, NULL);
7f4c2a
         if (ret != SQLITE_OK) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
-                        LG_MSG_BINDING_FAILED,
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors),
7f4c2a
+                        0, LG_MSG_BINDING_FAILED,
7f4c2a
                         "Failed binding basename %s : %s", basename,
7f4c2a
                         sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
@@ -375,8 +385,10 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
         /*Bind basepath*/
7f4c2a
         ret = sqlite3_bind_text (insert_stmt, 4, basepath, -1, NULL);
7f4c2a
         if (ret != SQLITE_OK) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
-                        LG_MSG_BINDING_FAILED, "Failed binding basepath %s : "
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors), 0,
7f4c2a
+                        LG_MSG_BINDING_FAILED,
7f4c2a
+                        "Failed binding basepath %s : "
7f4c2a
                         "%s", basepath,
7f4c2a
                         sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
@@ -385,8 +397,11 @@ gf_sql_insert_link (gf_sql_connection_t  *sql_conn,
7f4c2a
 
7f4c2a
         /*Execute the prepare statement*/
7f4c2a
         if (sqlite3_step (insert_stmt) != SQLITE_DONE) {
7f4c2a
-                gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_EXEC_FAILED,
7f4c2a
-                        "Failed executing the prepared stmt %s %s %s %s %s : %s",
7f4c2a
+                gf_msg (GFDB_STR_SQLITE3,
7f4c2a
+                        _gfdb_log_level (GF_LOG_ERROR, ignore_errors),
7f4c2a
+                        0, LG_MSG_EXEC_FAILED,
7f4c2a
+                        "Failed executing the prepared "
7f4c2a
+                        "stmt %s %s %s %s %s : %s",
7f4c2a
                         gfid, pargfid, basename, basepath, insert_str,
7f4c2a
                         sqlite3_errmsg (sql_conn->sqlite3_db_conn));
7f4c2a
                 ret = -1;
7f4c2a
@@ -777,7 +792,8 @@ gf_sql_insert_wind (gf_sql_connection_t  *sql_conn,
7f4c2a
                                         gfid_str, pargfid_str,
7f4c2a
                                         gfdb_db_record->file_name,
7f4c2a
                                         gfdb_db_record->file_path,
7f4c2a
-                                        gfdb_db_record->link_consistency);
7f4c2a
+                                        gfdb_db_record->link_consistency,
7f4c2a
+                                        gfdb_db_record->ignore_errors);
7f4c2a
                         if (ret) {
7f4c2a
                                 gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0,
7f4c2a
                                         LG_MSG_INSERT_FAILED, "Failed "
7f4c2a
@@ -836,7 +852,8 @@ gf_sql_insert_wind (gf_sql_connection_t  *sql_conn,
7f4c2a
                                         gfid_str, pargfid_str,
7f4c2a
                                         gfdb_db_record->file_name,
7f4c2a
                                         gfdb_db_record->file_path,
7f4c2a
-                                        gfdb_db_record->link_consistency);
7f4c2a
+                                        gfdb_db_record->link_consistency,
7f4c2a
+                                        gfdb_db_record->ignore_errors);
7f4c2a
                                 if (ret) {
7f4c2a
                                         gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR,
7f4c2a
                                                 0, LG_MSG_INSERT_FAILED,
7f4c2a
diff --git a/xlators/cluster/dht/src/tier.h b/xlators/cluster/dht/src/tier.h
7f4c2a
index 7d4ea6b..34631b0 100644
7f4c2a
--- a/xlators/cluster/dht/src/tier.h
7f4c2a
+++ b/xlators/cluster/dht/src/tier.h
7f4c2a
@@ -27,9 +27,8 @@
7f4c2a
 
7f4c2a
 #define DEFAULT_PROMOTE_FREQ_SEC 120
7f4c2a
 #define DEFAULT_DEMOTE_FREQ_SEC  120
7f4c2a
-#define DEFAULT_WRITE_FREQ_SEC 120
7f4c2a
-#define DEFAULT_READ_FREQ_SEC 120
7f4c2a
-
7f4c2a
+#define DEFAULT_WRITE_FREQ_SEC 0
7f4c2a
+#define DEFAULT_READ_FREQ_SEC 0
7f4c2a
 /*
7f4c2a
  * Size of timer wheel. We would not promote or demote less
7f4c2a
  * frequently than this number.
7f4c2a
diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.c b/xlators/features/changetimerecorder/src/changetimerecorder.c
7f4c2a
index 1fdeb7c..703df49 100644
7f4c2a
--- a/xlators/features/changetimerecorder/src/changetimerecorder.c
7f4c2a
+++ b/xlators/features/changetimerecorder/src/changetimerecorder.c
7f4c2a
@@ -114,7 +114,7 @@ ctr_lookup_wind(call_frame_t                    *frame,
7f4c2a
                 /*Don't record time at all*/
7f4c2a
                 CTR_DB_REC(ctr_local).do_record_times = _gf_false;
7f4c2a
 
7f4c2a
-                /*Copy gfid into db record*/
7f4c2a
+                /* Copy gfid into db record*/
7f4c2a
                 gf_uuid_copy (CTR_DB_REC(ctr_local).gfid,
7f4c2a
                                 *(ctr_inode_cx->gfid));
7f4c2a
 
7f4c2a
@@ -131,6 +131,12 @@ ctr_lookup_wind(call_frame_t                    *frame,
7f4c2a
                 strcpy (CTR_DB_REC(ctr_local).file_path,
7f4c2a
                         NEW_LINK_CX(ctr_inode_cx)->basepath);
7f4c2a
 
7f4c2a
+                /* Since we are in lookup we can ignore errors while
7f4c2a
+                 * Inserting in the DB, because there may be many
7f4c2a
+                 * to write to the DB attempts for healing.
7f4c2a
+                 * We dont want to log all failed attempts and
7f4c2a
+                 * bloat the log*/
7f4c2a
+                 ctr_local->gfdb_db_record.ignore_errors = _gf_true;
7f4c2a
         }
7f4c2a
 
7f4c2a
         ret = 0;
7f4c2a
@@ -171,8 +177,11 @@ ctr_lookup_unwind (call_frame_t          *frame,
7f4c2a
                 ret = insert_record(_priv->_db_conn,
7f4c2a
                                 &ctr_local->gfdb_db_record);
7f4c2a
                 if (ret == -1) {
7f4c2a
-                        gf_msg(this->name, GF_LOG_ERROR, 0,
7f4c2a
-                               CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND,
7f4c2a
+                        gf_msg (this->name,
7f4c2a
+                                _gfdb_log_level (GF_LOG_ERROR,
7f4c2a
+                                        ctr_local->
7f4c2a
+                                        gfdb_db_record.ignore_errors),
7f4c2a
+                                0, CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND,
7f4c2a
                                "UNWIND: Error filling ctr local");
7f4c2a
                         goto out;
7f4c2a
                 }
7f4c2a
@@ -198,9 +207,11 @@ ctr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                    int32_t op_ret, int32_t op_errno, inode_t *inode,
7f4c2a
                    struct iatt *buf, dict_t *dict, struct iatt *postparent)
7f4c2a
 {
7f4c2a
-        int ret                         = -1;
7f4c2a
-        ctr_xlator_ctx_t *ctr_xlator_ctx;
7f4c2a
-        gf_ctr_local_t *ctr_local       = NULL;
7f4c2a
+        int ret                                 = -1;
7f4c2a
+        ctr_xlator_ctx_t *ctr_xlator_ctx        = NULL;
7f4c2a
+        gf_ctr_local_t *ctr_local               = NULL;
7f4c2a
+        ctr_heal_ret_val_t  ret_val             = CTR_CTX_ERROR;
7f4c2a
+        gf_boolean_t    _is_heal_needed         = _gf_false;
7f4c2a
 
7f4c2a
         CTR_IS_DISABLED_THEN_GOTO(this, out);
7f4c2a
         CTR_IF_INTERNAL_FOP_THEN_GOTO (frame, dict, out);
7f4c2a
@@ -223,34 +234,70 @@ ctr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        /* if the lookup is for dht link donot record*/
7f4c2a
+        if (dht_is_linkfile (buf, dict)) {
7f4c2a
+                gf_msg_trace (this->name, 0, "Ignoring Lookup "
7f4c2a
+                                "for dht link file");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         ctr_local = frame->local;
7f4c2a
         /*Assign the proper inode type*/
7f4c2a
         ctr_local->ia_inode_type = inode->ia_type;
7f4c2a
 
7f4c2a
+        /* Copy gfid directly from inode */
7f4c2a
+        gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, inode->gfid);
7f4c2a
+
7f4c2a
+        /* Checking if gfid and parent gfid is valid */
7f4c2a
+        if (gf_uuid_is_null(CTR_DB_REC(ctr_local).gfid) ||
7f4c2a
+                gf_uuid_is_null(CTR_DB_REC(ctr_local).pargfid)) {
7f4c2a
+                gf_msg_trace (this->name, 0,
7f4c2a
+                        "Invalid GFID");
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         /* if its a first entry
7f4c2a
          * then mark the ctr_record for create
7f4c2a
          * A create will attempt a file and a hard link created in the db*/
7f4c2a
         ctr_xlator_ctx = get_ctr_xlator_ctx (this, inode);
7f4c2a
         if (!ctr_xlator_ctx) {
7f4c2a
+                 /* This marks inode heal */
7f4c2a
                 CTR_DB_REC(ctr_local).gfdb_fop_type = GFDB_FOP_CREATE_WRITE;
7f4c2a
+                _is_heal_needed = _gf_true;
7f4c2a
         }
7f4c2a
 
7f4c2a
         /* Copy the correct gfid from resolved inode */
7f4c2a
         gf_uuid_copy (CTR_DB_REC(ctr_local).gfid, inode->gfid);
7f4c2a
 
7f4c2a
         /* Add hard link to the list */
7f4c2a
-        ret = add_hard_link_ctx (frame, this, inode);
7f4c2a
-        if (ret < 0) {
7f4c2a
-                gf_msg_trace (this->name, 0, "Failed adding hard link");
7f4c2a
+        ret_val = add_hard_link_ctx (frame, this, inode);
7f4c2a
+        if (ret_val == CTR_CTX_ERROR) {
7f4c2a
+                gf_msg_trace (this->name, 0,
7f4c2a
+                        "Failed adding hardlink to list");
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
+        /* If inode needs healing then heal the hardlink also */
7f4c2a
+        else if (ret_val & CTR_TRY_INODE_HEAL) {
7f4c2a
+                /* This marks inode heal */
7f4c2a
+                CTR_DB_REC(ctr_local).gfdb_fop_type = GFDB_FOP_CREATE_WRITE;
7f4c2a
+                _is_heal_needed = _gf_true;
7f4c2a
+        }
7f4c2a
+        /* If hardlink needs healing */
7f4c2a
+        else if (ret_val & CTR_TRY_HARDLINK_HEAL) {
7f4c2a
+                _is_heal_needed = _gf_true;
7f4c2a
+        }
7f4c2a
 
7f4c2a
-        /* Inserts the ctr_db_record populated by ctr_lookup_wind
7f4c2a
+        /* If lookup heal needed */
7f4c2a
+        if (!_is_heal_needed)
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
+        /* FINALLY HEAL : Inserts the ctr_db_record populated by ctr_lookup_wind
7f4c2a
         * in to the db. It also destroys the frame->local
7f4c2a
         * created by ctr_lookup_wind */
7f4c2a
         ret = ctr_lookup_unwind(frame, this);
7f4c2a
         if (ret) {
7f4c2a
-                gf_msg_trace (this->name, 0, "Failed inserting link wind");
7f4c2a
+                gf_msg_trace (this->name, 0,
7f4c2a
+                        "Failed healing/inserting link");
7f4c2a
         }
7f4c2a
 
7f4c2a
 
7f4c2a
@@ -793,6 +840,7 @@ ctr_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
         }
7f4c2a
         /*Last link that was deleted*/
7f4c2a
         else if (remaining_links == 1) {
7f4c2a
+
7f4c2a
                 ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE,
7f4c2a
                                         GFDB_FOP_UNDEL_ALL);
7f4c2a
                 if (ret) {
7f4c2a
@@ -819,6 +867,7 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
7f4c2a
         gf_ctr_link_context_t ctr_link_cx;
7f4c2a
         gf_ctr_link_context_t *_link_cx = &ctr_link_cx;
7f4c2a
         gf_boolean_t is_xdata_created = _gf_false;
7f4c2a
+        struct iatt dummy_stat        = {0};
7f4c2a
 
7f4c2a
         GF_ASSERT (frame);
7f4c2a
 
7f4c2a
@@ -835,6 +884,12 @@ ctr_unlink (call_frame_t *frame, xlator_t *this,
7f4c2a
         /*Internal FOP*/
7f4c2a
         _inode_cx->is_internal_fop = CTR_IS_INTERNAL_FOP(frame, xdata);
7f4c2a
 
7f4c2a
+        /* If its a internal FOP and dht link file donot record*/
7f4c2a
+        if (_inode_cx->is_internal_fop &&
7f4c2a
+                        dht_is_linkfile (&dummy_stat, xdata)) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         /*record into the database*/
7f4c2a
         ret = ctr_insert_wind(frame, this, _inode_cx);
7f4c2a
         if (ret) {
7f4c2a
@@ -1014,12 +1069,13 @@ ctr_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
7f4c2a
                  struct iatt *postparent, dict_t *xdata)
7f4c2a
 {
7f4c2a
         int ret = -1;
7f4c2a
+        ctr_heal_ret_val_t ret_val = CTR_CTX_ERROR;
7f4c2a
 
7f4c2a
         CTR_IS_DISABLED_THEN_GOTO(this, out);
7f4c2a
 
7f4c2a
         /* Add hard link to the list */
7f4c2a
-        ret = add_hard_link_ctx (frame, this, inode);
7f4c2a
-        if (ret) {
7f4c2a
+        ret_val = add_hard_link_ctx (frame, this, inode);
7f4c2a
+        if (ret_val == CTR_CTX_ERROR) {
7f4c2a
                 gf_msg_trace (this->name, 0, "Failed adding hard link");
7f4c2a
         }
7f4c2a
 
7f4c2a
@@ -1053,6 +1109,7 @@ ctr_mknod (call_frame_t *frame, xlator_t *this,
7f4c2a
         uuid_t *ptr_gfid                        = &gfi;;
7f4c2a
 
7f4c2a
         CTR_IS_DISABLED_THEN_GOTO(this, out);
7f4c2a
+        CTR_IF_INTERNAL_FOP_THEN_GOTO (frame, xdata, out);
7f4c2a
 
7f4c2a
         GF_ASSERT(frame);
7f4c2a
         GF_ASSERT(frame->root);
7f4c2a
@@ -1073,9 +1130,6 @@ ctr_mknod (call_frame_t *frame, xlator_t *this,
7f4c2a
                 *ptr_gfid, _link_cx, NULL,
7f4c2a
                 GFDB_FOP_CREATE_WRITE, GFDB_FOP_WIND);
7f4c2a
 
7f4c2a
-        /*Internal FOP*/
7f4c2a
-        _inode_cx->is_internal_fop = CTR_IS_INTERNAL_FOP(frame, xdata);
7f4c2a
-
7f4c2a
         /*record into the database*/
7f4c2a
         ret = ctr_insert_wind(frame, this, _inode_cx);
7f4c2a
         if (ret) {
7f4c2a
@@ -1140,6 +1194,7 @@ ctr_create (call_frame_t *frame, xlator_t *this,
7f4c2a
         void             *uuid_req              = NULL;
7f4c2a
         uuid_t            gfid                  = {0,};
7f4c2a
         uuid_t            *ptr_gfid             = &gfi;;
7f4c2a
+        struct iatt dummy_stat                  = {0};
7f4c2a
 
7f4c2a
         CTR_IS_DISABLED_THEN_GOTO(this, out);
7f4c2a
 
7f4c2a
@@ -1167,6 +1222,12 @@ ctr_create (call_frame_t *frame, xlator_t *this,
7f4c2a
         /*Internal FOP*/
7f4c2a
         _inode_cx->is_internal_fop = CTR_IS_INTERNAL_FOP(frame, xdata);
7f4c2a
 
7f4c2a
+        /* If its a internal FOP and dht link file donot record*/
7f4c2a
+        if (_inode_cx->is_internal_fop &&
7f4c2a
+                        dht_is_linkfile (&dummy_stat, xdata)) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         /*record into the database*/
7f4c2a
         ret = ctr_insert_wind(frame, this, &ctr_inode_cx);
7f4c2a
         if (ret) {
7f4c2a
@@ -1222,6 +1283,7 @@ ctr_link (call_frame_t *frame, xlator_t *this,
7f4c2a
         gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx;
7f4c2a
         gf_ctr_link_context_t  ctr_link_cx;
7f4c2a
         gf_ctr_link_context_t  *_link_cx = &ctr_link_cx;
7f4c2a
+        struct iatt dummy_stat          = {0};
7f4c2a
 
7f4c2a
         CTR_IS_DISABLED_THEN_GOTO(this, out);
7f4c2a
 
7f4c2a
@@ -1240,6 +1302,13 @@ ctr_link (call_frame_t *frame, xlator_t *this,
7f4c2a
         /*Internal FOP*/
7f4c2a
         _inode_cx->is_internal_fop = CTR_IS_INTERNAL_FOP(frame, xdata);
7f4c2a
 
7f4c2a
+        /* If its a internal FOP and dht link file donot record*/
7f4c2a
+        if (_inode_cx->is_internal_fop &&
7f4c2a
+                        dht_is_linkfile (&dummy_stat, xdata)) {
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
+
7f4c2a
         /*record into the database*/
7f4c2a
         ret = ctr_insert_wind(frame, this, _inode_cx);
7f4c2a
         if (ret) {
7f4c2a
@@ -1334,6 +1403,14 @@ reconfigure (xlator_t *this, dict_t *options)
7f4c2a
         GF_OPTION_RECONF ("ctr_link_consistency", _priv->ctr_link_consistency,
7f4c2a
                         options, bool, out);
7f4c2a
 
7f4c2a
+        GF_OPTION_RECONF ("ctr_inode_heal_expire_period",
7f4c2a
+                                _priv->ctr_inode_heal_expire_period,
7f4c2a
+                                options, uint64, out);
7f4c2a
+
7f4c2a
+        GF_OPTION_RECONF ("ctr_hardlink_heal_expire_period",
7f4c2a
+                                _priv->ctr_hardlink_heal_expire_period,
7f4c2a
+                                options, uint64, out);
7f4c2a
+
7f4c2a
         GF_OPTION_RECONF ("record-exit", _priv->ctr_record_unwind, options,
7f4c2a
                           bool, out);
7f4c2a
 
7f4c2a
@@ -1385,6 +1462,10 @@ init (xlator_t *this)
7f4c2a
         _priv->gfdb_sync_type           = GFDB_DB_SYNC;
7f4c2a
         _priv->enabled                  = _gf_true;
7f4c2a
         _priv->_db_conn                 = NULL;
7f4c2a
+        _priv->ctr_hardlink_heal_expire_period =
7f4c2a
+                                CTR_DEFAULT_HARDLINK_EXP_PERIOD;
7f4c2a
+        _priv->ctr_inode_heal_expire_period =
7f4c2a
+                                CTR_DEFAULT_INODE_EXP_PERIOD;
7f4c2a
 
7f4c2a
         /*Extract ctr xlator options*/
7f4c2a
         ret_db = extract_ctr_options (this, _priv);
7f4c2a
@@ -1549,6 +1630,14 @@ struct volume_options options[] = {
7f4c2a
           .value = {"on", "off"},
7f4c2a
           .default_value = "off"
7f4c2a
         },
7f4c2a
+        { .key  = {"ctr_hardlink_heal_expire_period"},
7f4c2a
+          .type = GF_OPTION_TYPE_INT,
7f4c2a
+          .default_value = "300"
7f4c2a
+        },
7f4c2a
+        { .key  = {"ctr_inode_heal_expire_period"},
7f4c2a
+          .type = GF_OPTION_TYPE_INT,
7f4c2a
+          .default_value = "300"
7f4c2a
+        },
7f4c2a
         { .key  = {"hot-brick"},
7f4c2a
           .type = GF_OPTION_TYPE_BOOL,
7f4c2a
           .value = {"on", "off"},
7f4c2a
diff --git a/xlators/features/changetimerecorder/src/ctr-helper.c b/xlators/features/changetimerecorder/src/ctr-helper.c
7f4c2a
index c4d9769..f5d4c47 100644
7f4c2a
--- a/xlators/features/changetimerecorder/src/ctr-helper.c
7f4c2a
+++ b/xlators/features/changetimerecorder/src/ctr-helper.c
7f4c2a
@@ -276,6 +276,16 @@ int extract_ctr_options (xlator_t *this, gf_ctr_private_t *_priv) {
7f4c2a
         GF_OPTION_INIT ("ctr_link_consistency", _priv->ctr_link_consistency,
7f4c2a
                         bool, out);
7f4c2a
 
7f4c2a
+        /*Extract ctr_inode_heal_expire_period */
7f4c2a
+        GF_OPTION_INIT ("ctr_inode_heal_expire_period",
7f4c2a
+                        _priv->ctr_inode_heal_expire_period,
7f4c2a
+                        uint64, out);
7f4c2a
+
7f4c2a
+        /*Extract ctr_hardlink_heal_expire_period*/
7f4c2a
+        GF_OPTION_INIT ("ctr_hardlink_heal_expire_period",
7f4c2a
+                        _priv->ctr_hardlink_heal_expire_period,
7f4c2a
+                        uint64, out);
7f4c2a
+
7f4c2a
         /*Extract flag for hot tier brick*/
7f4c2a
         GF_OPTION_INIT ("hot-brick", _priv->ctr_hot_brick, bool, out);
7f4c2a
 
7f4c2a
diff --git a/xlators/features/changetimerecorder/src/ctr-helper.h b/xlators/features/changetimerecorder/src/ctr-helper.h
7f4c2a
index a3df971..82a0c8b 100644
7f4c2a
--- a/xlators/features/changetimerecorder/src/ctr-helper.h
7f4c2a
+++ b/xlators/features/changetimerecorder/src/ctr-helper.h
7f4c2a
@@ -31,6 +31,9 @@
7f4c2a
 #include "ctr-xlator-ctx.h"
7f4c2a
 #include "ctr-messages.h"
7f4c2a
 
7f4c2a
+#define CTR_DEFAULT_HARDLINK_EXP_PERIOD 300  /* Five mins */
7f4c2a
+#define CTR_DEFAULT_INODE_EXP_PERIOD    300 /* Five mins */
7f4c2a
+
7f4c2a
 /*CTR Xlator Private structure*/
7f4c2a
 typedef struct gf_ctr_private {
7f4c2a
         gf_boolean_t                    enabled;
7f4c2a
@@ -43,6 +46,8 @@ typedef struct gf_ctr_private {
7f4c2a
         gfdb_db_type_t                  gfdb_db_type;
7f4c2a
         gfdb_sync_type_t                gfdb_sync_type;
7f4c2a
         gfdb_conn_node_t                *_db_conn;
7f4c2a
+        uint64_t                        ctr_hardlink_heal_expire_period;
7f4c2a
+        uint64_t                        ctr_inode_heal_expire_period;
7f4c2a
 } gf_ctr_private_t;
7f4c2a
 
7f4c2a
 
7f4c2a
@@ -472,19 +477,91 @@ out:
7f4c2a
 
7f4c2a
 /******************************* Hard link function ***************************/
7f4c2a
 
7f4c2a
-static inline int
7f4c2a
+static inline gf_boolean_t
7f4c2a
+__is_inode_expired (ctr_xlator_ctx_t *ctr_xlator_ctx,
7f4c2a
+                    gf_ctr_private_t *_priv,
7f4c2a
+                    gfdb_time_t *current_time)
7f4c2a
+{
7f4c2a
+        gf_boolean_t    ret       = _gf_false;
7f4c2a
+        uint64_t        time_diff = 0;
7f4c2a
+
7f4c2a
+        GF_ASSERT (ctr_xlator_ctx);
7f4c2a
+        GF_ASSERT (_priv);
7f4c2a
+        GF_ASSERT (current_time);
7f4c2a
+
7f4c2a
+        time_diff = current_time->tv_sec -
7f4c2a
+                        ctr_xlator_ctx->inode_heal_period;
7f4c2a
+
7f4c2a
+        ret = (time_diff >= _priv->ctr_inode_heal_expire_period) ?
7f4c2a
+                        _gf_true : _gf_false;
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+static inline gf_boolean_t
7f4c2a
+__is_hardlink_expired (ctr_hard_link_t *ctr_hard_link,
7f4c2a
+                       gf_ctr_private_t *_priv,
7f4c2a
+                       gfdb_time_t *current_time)
7f4c2a
+{
7f4c2a
+        gf_boolean_t    ret       = _gf_false;
7f4c2a
+        uint64_t        time_diff = 0;
7f4c2a
+
7f4c2a
+        GF_ASSERT (ctr_hard_link);
7f4c2a
+        GF_ASSERT (_priv);
7f4c2a
+        GF_ASSERT (current_time);
7f4c2a
+
7f4c2a
+        time_diff = current_time->tv_sec -
7f4c2a
+                        ctr_hard_link->hardlink_heal_period;
7f4c2a
+
7f4c2a
+        ret = ret || (time_diff >= _priv->ctr_hardlink_heal_expire_period) ?
7f4c2a
+                        _gf_true : _gf_false;
7f4c2a
+
7f4c2a
+        return ret;
7f4c2a
+}
7f4c2a
+
7f4c2a
+
7f4c2a
+/* Return values of heal*/
7f4c2a
+typedef enum ctr_heal_ret_val {
7f4c2a
+        CTR_CTX_ERROR = -1,
7f4c2a
+        /* No healing required */
7f4c2a
+        CTR_TRY_NO_HEAL = 0,
7f4c2a
+        /* Try healing hard link */
7f4c2a
+        CTR_TRY_HARDLINK_HEAL = 1,
7f4c2a
+        /* Try healing inode */
7f4c2a
+        CTR_TRY_INODE_HEAL = 2,
7f4c2a
+} ctr_heal_ret_val_t;
7f4c2a
+
7f4c2a
+
7f4c2a
+
7f4c2a
+/**
7f4c2a
+ * @brief Function to add hard link to the inode context variable.
7f4c2a
+ *        The inode context maintainences a in-memory list. This is used
7f4c2a
+ *        smart healing of database.
7f4c2a
+ * @param frame of the FOP
7f4c2a
+ * @param this is the Xlator instant
7f4c2a
+ * @param inode
7f4c2a
+ * @return Return ctr_heal_ret_val_t
7f4c2a
+ */
7f4c2a
+
7f4c2a
+static inline ctr_heal_ret_val_t
7f4c2a
 add_hard_link_ctx (call_frame_t *frame,
7f4c2a
                    xlator_t     *this,
7f4c2a
                    inode_t      *inode)
7f4c2a
 {
7f4c2a
+        ctr_heal_ret_val_t ret_val = CTR_TRY_NO_HEAL;
7f4c2a
         int ret = -1;
7f4c2a
         gf_ctr_local_t   *ctr_local       = NULL;
7f4c2a
         ctr_xlator_ctx_t *ctr_xlator_ctx  = NULL;
7f4c2a
         ctr_hard_link_t  *ctr_hard_link   = NULL;
7f4c2a
+        gf_ctr_private_t *_priv           = NULL;
7f4c2a
+        gfdb_time_t       current_time    = {0};
7f4c2a
+
7f4c2a
 
7f4c2a
         GF_ASSERT (frame);
7f4c2a
         GF_ASSERT (this);
7f4c2a
         GF_ASSERT (inode);
7f4c2a
+        GF_ASSERT (this->private);
7f4c2a
+
7f4c2a
+        _priv = this->private;
7f4c2a
 
7f4c2a
         ctr_local = frame->local;
7f4c2a
         if (!ctr_local) {
7f4c2a
@@ -509,7 +586,29 @@ add_hard_link_ctx (call_frame_t *frame,
7f4c2a
                                 CTR_DB_REC(ctr_local).file_name);
7f4c2a
         /* if there then ignore */
7f4c2a
         if (ctr_hard_link) {
7f4c2a
-                ret = 1;
7f4c2a
+
7f4c2a
+                ret = gettimeofday (&current_time, NULL);
7f4c2a
+                if (ret == -1) {
7f4c2a
+                        gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                                "Failed to get current time");
7f4c2a
+                        ret_val = CTR_CTX_ERROR;
7f4c2a
+                        goto unlock;
7f4c2a
+                }
7f4c2a
+
7f4c2a
+                if (__is_hardlink_expired (ctr_hard_link,
7f4c2a
+                                           _priv, &current_time)) {
7f4c2a
+                        ctr_hard_link->hardlink_heal_period =
7f4c2a
+                                        current_time.tv_sec;
7f4c2a
+                        ret_val = ret_val | CTR_TRY_HARDLINK_HEAL;
7f4c2a
+                }
7f4c2a
+
7f4c2a
+                if (__is_inode_expired (ctr_xlator_ctx,
7f4c2a
+                                           _priv, &current_time)) {
7f4c2a
+                        ctr_xlator_ctx->inode_heal_period =
7f4c2a
+                                                current_time.tv_sec;
7f4c2a
+                        ret_val = ret_val | CTR_TRY_INODE_HEAL;
7f4c2a
+                }
7f4c2a
+
7f4c2a
                 goto unlock;
7f4c2a
         }
7f4c2a
 
7f4c2a
@@ -521,14 +620,15 @@ add_hard_link_ctx (call_frame_t *frame,
7f4c2a
                 gf_msg (this->name, GF_LOG_ERROR, 0,
7f4c2a
                         CTR_MSG_ADD_HARDLINK_TO_CTR_INODE_CONTEXT_FAILED,
7f4c2a
                         "Failed to add hardlink to the ctr inode context");
7f4c2a
+                ret_val = CTR_CTX_ERROR;
7f4c2a
                 goto unlock;
7f4c2a
         }
7f4c2a
 
7f4c2a
-        ret = 0;
7f4c2a
+        ret_val = CTR_TRY_NO_HEAL;
7f4c2a
 unlock:
7f4c2a
         UNLOCK (&ctr_xlator_ctx->lock);
7f4c2a
 out:
7f4c2a
-        return ret;
7f4c2a
+        return ret_val;
7f4c2a
 }
7f4c2a
 
7f4c2a
 static inline int
7f4c2a
diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
7f4c2a
index a91a2bb..b8f6f03 100644
7f4c2a
--- a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
7f4c2a
+++ b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
7f4c2a
@@ -10,6 +10,8 @@
7f4c2a
 
7f4c2a
 #include "ctr-xlator-ctx.h"
7f4c2a
 #include "ctr-messages.h"
7f4c2a
+#include <time.h>
7f4c2a
+#include <sys/time.h>
7f4c2a
 
7f4c2a
 #define IS_THE_ONLY_HARDLINK(ctr_hard_link)\
7f4c2a
         (ctr_hard_link->list.next == ctr_hard_link->list.prev)
7f4c2a
@@ -63,13 +65,14 @@ out:
7f4c2a
 
7f4c2a
 /* Please lock the ctr_xlator_ctx before using this function */
7f4c2a
 int
7f4c2a
-ctr_add_hard_link (xlator_t           *this,
7f4c2a
+ctr_add_hard_link (xlator_t             *this,
7f4c2a
                ctr_xlator_ctx_t         *ctr_xlator_ctx,
7f4c2a
                uuid_t                   pgfid,
7f4c2a
                const char               *base_name)
7f4c2a
 {
7f4c2a
         int ret                                 = -1;
7f4c2a
         ctr_hard_link_t *ctr_hard_link          = NULL;
7f4c2a
+        struct timeval  current_time                   = {0};
7f4c2a
 
7f4c2a
         GF_ASSERT (this);
7f4c2a
         GF_ASSERT (ctr_xlator_ctx);
7f4c2a
@@ -98,10 +101,19 @@ ctr_add_hard_link (xlator_t           *this,
7f4c2a
                 goto error;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        ret = gettimeofday (&current_time, NULL);
7f4c2a
+        if (ret == -1) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                        "Failed to get current time");
7f4c2a
+                goto error;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         /*Add the hard link to the list*/
7f4c2a
         list_add_tail (&ctr_hard_link->list,
7f4c2a
                         &ctr_xlator_ctx->hardlink_list);
7f4c2a
 
7f4c2a
+        ctr_hard_link->hardlink_heal_period = current_time.tv_sec;
7f4c2a
+
7f4c2a
         /*aal izz well!*/
7f4c2a
         ret = 0;
7f4c2a
         goto out;
7f4c2a
@@ -169,8 +181,9 @@ ctr_update_hard_link (xlator_t                *this,
7f4c2a
                   uuid_t                old_pgfid,
7f4c2a
                   const char            *old_base_name)
7f4c2a
 {
7f4c2a
-        int ret                         = -1;
7f4c2a
+        int ret                            = -1;
7f4c2a
         ctr_hard_link_t *ctr_hard_link     = NULL;
7f4c2a
+        struct timeval current_time        = {0};
7f4c2a
 
7f4c2a
         GF_ASSERT (this);
7f4c2a
         GF_ASSERT (ctr_xlator_ctx);
7f4c2a
@@ -212,6 +225,15 @@ ctr_update_hard_link (xlator_t                *this,
7f4c2a
                 goto out;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        ret = gettimeofday (&current_time, NULL);
7f4c2a
+        if (ret == -1) {
7f4c2a
+                gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                        "Failed to get current time");
7f4c2a
+                ctr_hard_link->hardlink_heal_period = 0;
7f4c2a
+        } else {
7f4c2a
+                ctr_hard_link->hardlink_heal_period = current_time.tv_sec;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         ret = 0;
7f4c2a
 
7f4c2a
 out:
7f4c2a
@@ -284,6 +306,7 @@ init_ctr_xlator_ctx (xlator_t *this,
7f4c2a
         int ret                                 = -1;
7f4c2a
         uint64_t _addr                          = 0;
7f4c2a
         ctr_xlator_ctx_t *ctr_xlator_ctx        = NULL;
7f4c2a
+        struct timeval current_time             = {0};
7f4c2a
 
7f4c2a
         GF_ASSERT (this);
7f4c2a
         GF_ASSERT (inode);
7f4c2a
@@ -316,6 +339,14 @@ init_ctr_xlator_ctx (xlator_t *this,
7f4c2a
 
7f4c2a
                 INIT_LIST_HEAD (&ctr_xlator_ctx->hardlink_list);
7f4c2a
 
7f4c2a
+                ret = gettimeofday (&current_time, NULL);
7f4c2a
+                if (ret == -1) {
7f4c2a
+                        gf_log (this->name, GF_LOG_ERROR,
7f4c2a
+                                "Failed to get current time");
7f4c2a
+                        goto out;
7f4c2a
+                }
7f4c2a
+
7f4c2a
+                ctr_xlator_ctx->inode_heal_period = current_time.tv_sec;
7f4c2a
         }
7f4c2a
         ret = 0;
7f4c2a
 out:
7f4c2a
diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h
7f4c2a
index bc93501..7f1c6cb 100644
7f4c2a
--- a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h
7f4c2a
+++ b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h
7f4c2a
@@ -25,6 +25,9 @@
7f4c2a
 typedef struct ctr_hard_link {
7f4c2a
         uuid_t                  pgfid;
7f4c2a
         char                    *base_name;
7f4c2a
+        /* Hardlink expiry : Defines the expiry period after which a
7f4c2a
+         * database heal is attempted. */
7f4c2a
+        uint64_t                  hardlink_heal_period;
7f4c2a
         struct list_head        list;
7f4c2a
 } ctr_hard_link_t;
7f4c2a
 
7f4c2a
@@ -32,6 +35,7 @@ typedef struct ctr_xlator_ctx {
7f4c2a
         /* This represents the looked up hardlinks
7f4c2a
          * NOTE: This doesn't represent all physical hardlinks of the inode*/
7f4c2a
         struct list_head        hardlink_list;
7f4c2a
+        uint64_t                inode_heal_period;
7f4c2a
         gf_lock_t               lock;
7f4c2a
 } ctr_xlator_ctx_t;
7f4c2a
 
7f4c2a
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
index 09671a8..c3ec10b 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
7f4c2a
@@ -1717,6 +1717,14 @@ brick_graph_add_changetimerecorder (volgen_graph_t *graph,
7f4c2a
         if (ret)
7f4c2a
                 goto out;
7f4c2a
 
7f4c2a
+        ret = xlator_set_option (xl, "ctr_hardlink_heal_expire_period", "300");
7f4c2a
+        if (ret)
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
+        ret = xlator_set_option (xl, "ctr_inode_heal_expire_period", "300");
7f4c2a
+        if (ret)
7f4c2a
+                goto out;
7f4c2a
+
7f4c2a
         ret = xlator_set_option (xl, "record-entry", "on");
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 ecaf04f..7bbd729 100644
7f4c2a
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
7f4c2a
@@ -1910,6 +1910,30 @@ struct volopt_map_entry glusterd_volopt_map[] = {
7f4c2a
                          "updates by Change Time Recorder Xlator. When recording in a crash "
7f4c2a
                          "consistent way the data operations will experience more latency."
7f4c2a
         },
7f4c2a
+        { .key         = "features.ctr_hardlink_heal_expire_period",
7f4c2a
+          .voltype     = "features/changetimerecorder",
7f4c2a
+          .value       = "300",
7f4c2a
+          .option      = "ctr_hardlink_heal_expire_period",
7f4c2a
+          .op_version  = GD_OP_VERSION_3_7_2,
7f4c2a
+          .description = "Defines the expiry period of in-memory "
7f4c2a
+                         "hardlink of an inode,"
7f4c2a
+                         "used by lookup heal in Change Time Recorder."
7f4c2a
+                         "Once the expiry period"
7f4c2a
+                         "hits an attempt to heal the database per "
7f4c2a
+                         "hardlink is done and the "
7f4c2a
+                         "in-memory hardlink period is reset"
7f4c2a
+        },
7f4c2a
+        { .key         = "features.ctr_inode_heal_expire_period",
7f4c2a
+          .voltype     = "features/changetimerecorder",
7f4c2a
+          .value       = "300",
7f4c2a
+          .option      = "ctr_inode_heal_expire_period",
7f4c2a
+          .op_version  = GD_OP_VERSION_3_7_2,
7f4c2a
+          .description = "Defines the expiry period of in-memory inode,"
7f4c2a
+                         "used by lookup heal in Change Time Recorder. "
7f4c2a
+                         "Once the expiry period"
7f4c2a
+                         "hits an attempt to heal the database per "
7f4c2a
+                         "inode is done"
7f4c2a
+        },
7f4c2a
 #endif /* USE_GFDB */
7f4c2a
         { .key         = "locks.trace",
7f4c2a
           .voltype     = "features/locks",
7f4c2a
-- 
7f4c2a
1.7.1
7f4c2a