summaryrefslogtreecommitdiffstats
path: root/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
diff options
context:
space:
mode:
authorJoseph Fernandes <josferna@redhat.com>2015-04-24 19:22:44 +0530
committerVijay Bellur <vbellur@redhat.com>2015-05-08 00:34:30 -0700
commit268b7fcb307e14cce5bcd28495f24333710ba82c (patch)
tree009782cecfdb7fb411d39ae1daaf4dea991c9777 /xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
parentffbe47e0ec8411313b666a8705f31a67d3862763 (diff)
ctr/xlator: Named lookup heal of pre-existing files, before ctr was ON.
Problem: The CTR xlator records file meta (heat/hardlinks) into the data. This works fine for files which are created after ctr xlator is switched ON. But for files which were created before CTR xlator is ON, CTR xlator is not able to record either of the meta i.e heat or hardlinks. Thus making those files immune to promotions/demotions. Solution: The solution that is implemented in this patch is do ctr-db heal of all those pre-existent files, using named lookup. For this purpose we use the inode-xlator context variable option in gluster. The inode-xlator context variable for ctr xlator will have the following, a. A Lock for the context variable b. A hardlink list: This list represents the successful looked up hardlinks. These are the scenarios when the hardlink list is updated: 1) Named-Lookup: Whenever a named lookup happens on a file, in the wind path we copy all required hardlink and inode information to ctr_db_record structure, which resides in the frame->local variable. We dont update the database in wind. During the unwind, we read the information from the ctr_db_record and , Check if the inode context variable is created, if not we create it. Check if the hard link is there in the hardlink list. If its not there we add it to the list and send a update to the database using libgfdb. Please note: The database transaction can fail(and we ignore) as there already might be a record in the db. This update to the db is to heal if its not there. If its there in the list we ignore it. 2) Inode Forget: Whenever an inode forget hits we clear the hardlink list in the inode context variable and delete the inode context variable. Please note: An inode forget may happen for two reason, a. when the inode is delete. b. the in-memory inode is evicted from the inode table due to cache limits. 3) create: whenever a create happens we create the inode context variable and add the hardlink. The database updation is done as usual by ctr. 4) link: whenever a hardlink is created for the inode, we create the inode context variable, if not present, and add the hardlink to the list. 5) unlink: whenever a unlink happens we delete the hardlink from the list. 6) mknod: same as create. 7) rename: whenever a rename happens we update the hardlink in list. if the hardlink was not present for updation, we add the hardlink to the list. What is pending: 1) This solution will only work for named lookups. 2) We dont track afr-self-heal/dht-rebalancer traffic for healing. > http://review.gluster.org/#/c/10370/ > Cherry picked from commit cb11dd91a6cc296e4a3808364077f4eacb810e48 > Change-Id: Ia4bbaf84128ad6ce8c3ddd70bcfa82894c79585f > BUG: 1212037 > Signed-off-by: Joseph Fernandes <josferna@redhat.com> > Signed-off-by: Dan Lambright <dlambrig@redhat.com> > Reviewed-on: http://review.gluster.org/10370 > Reviewed-by: Jeff Darcy <jdarcy@redhat.com> > Tested-by: Gluster Build System <jenkins@build.gluster.com> > Tested-by: NetBSD Build System > Reviewed-by: Vijay Bellur <vbellur@redhat.com> Change-Id: I367aa46c3f4b8f912248fb8be75866507f2538df BUG: 1219075 Signed-off-by: Joseph Fernandes <josferna@redhat.com> Signed-off-by: Dan Lambright <dlambrig@redhat.com> Reviewed-on: http://review.gluster.org/10370 Reviewed-by: Jeff Darcy <jdarcy@redhat.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com> Signed-off-by: Joseph Fernandes <josferna@redhat.com> Reviewed-on: http://review.gluster.org/10615 Tested-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators/features/changetimerecorder/src/ctr-xlator-ctx.c')
-rw-r--r--xlators/features/changetimerecorder/src/ctr-xlator-ctx.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
new file mode 100644
index 00000000000..927c8542c4e
--- /dev/null
+++ b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c
@@ -0,0 +1,370 @@
+/*
+ Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include "ctr-xlator-ctx.h"
+
+#define IS_THE_ONLY_HARDLINK(ctr_hard_link)\
+ (ctr_hard_link->list.next == ctr_hard_link->list.prev)
+
+
+static inline void
+fini_ctr_hard_link (ctr_hard_link_t **ctr_hard_link) {
+
+ GF_ASSERT (ctr_hard_link);
+
+ if (*ctr_hard_link)
+ return;
+ GF_FREE ((*ctr_hard_link)->base_name);
+ GF_FREE (*ctr_hard_link);
+ *ctr_hard_link = NULL;
+}
+
+
+/* Please lock the ctr_xlator_ctx before using this function */
+ctr_hard_link_t *
+ctr_search_hard_link_ctx (xlator_t *this,
+ ctr_xlator_ctx_t *ctr_xlator_ctx,
+ uuid_t pgfid,
+ const char *base_name)
+{
+ ctr_hard_link_t *_hard_link = NULL;
+ ctr_hard_link_t *searched_hardlink = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (ctr_xlator_ctx);
+
+ if (pgfid == NULL || base_name == NULL)
+ goto out;
+
+ /*linear search*/
+ list_for_each_entry (_hard_link, &ctr_xlator_ctx->hardlink_list, list) {
+ if (gf_uuid_compare (_hard_link->pgfid, pgfid) == 0
+ && _hard_link->base_name
+ && strcmp(_hard_link->base_name, base_name) == 0) {
+ searched_hardlink = _hard_link;
+ break;
+ }
+ }
+
+out:
+ return searched_hardlink;
+}
+
+
+
+
+/* Please lock the ctr_xlator_ctx before using this function */
+int
+ctr_add_hard_link (xlator_t *this,
+ ctr_xlator_ctx_t *ctr_xlator_ctx,
+ uuid_t pgfid,
+ const char *base_name)
+{
+ int ret = -1;
+ ctr_hard_link_t *ctr_hard_link = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (ctr_xlator_ctx);
+
+ if (pgfid == NULL || base_name == NULL)
+ goto out;
+
+ ctr_hard_link = GF_CALLOC (1, sizeof (*ctr_hard_link),
+ gf_ctr_mt_hard_link_t);
+ if (!ctr_hard_link) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed allocating "
+ "ctr_hard_link");
+ goto out;
+ }
+
+ /*Initialize the ctr_hard_link object and
+ * Assign the values : parent GFID and basename*/
+ INIT_LIST_HEAD (&ctr_hard_link->list);
+ gf_uuid_copy (ctr_hard_link->pgfid, pgfid);
+ ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed copying basename"
+ "to ctr_hard_link");
+ goto error;
+ }
+
+ /*Add the hard link to the list*/
+ list_add_tail (&ctr_hard_link->list,
+ &ctr_xlator_ctx->hardlink_list);
+
+ /*aal izz well!*/
+ ret = 0;
+ goto out;
+error:
+ GF_FREE (ctr_hard_link);
+out:
+ return ret;
+}
+
+static void
+__delete_hard_link_from_list (ctr_hard_link_t **ctr_hard_link)
+{
+ GF_ASSERT (ctr_hard_link);
+ GF_ASSERT (*ctr_hard_link);
+
+ /*Remove hard link from list*/
+ list_del(&(*ctr_hard_link)->list);
+ fini_ctr_hard_link (ctr_hard_link);
+}
+
+
+int
+ctr_delete_hard_link (xlator_t *this,
+ ctr_xlator_ctx_t *ctr_xlator_ctx,
+ uuid_t pgfid,
+ const char *base_name)
+{
+ int ret = -1;
+ ctr_hard_link_t *ctr_hard_link = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (ctr_xlator_ctx);
+
+
+ LOCK (&ctr_xlator_ctx->lock);
+
+ /*Check if the hard link is present */
+ ctr_hard_link = ctr_search_hard_link_ctx (this, ctr_xlator_ctx,
+ pgfid, base_name);
+ if (!ctr_hard_link) {
+ gf_log (this->name, GF_LOG_ERROR, "Hard link doesnt exist"
+ " in the list");
+ goto out;
+ }
+
+ __delete_hard_link_from_list (&ctr_hard_link);
+ ctr_hard_link = NULL;
+
+ ret = 0;
+out:
+ UNLOCK (&ctr_xlator_ctx->lock);
+
+ return ret;
+}
+
+
+
+
+int
+ctr_update_hard_link (xlator_t *this,
+ ctr_xlator_ctx_t *ctr_xlator_ctx,
+ uuid_t pgfid,
+ const char *base_name,
+ uuid_t old_pgfid,
+ const char *old_base_name)
+{
+ int ret = -1;
+ ctr_hard_link_t *ctr_hard_link = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (ctr_xlator_ctx);
+
+
+ LOCK (&ctr_xlator_ctx->lock);
+
+ /*Check if the hard link is present */
+ ctr_hard_link = ctr_search_hard_link_ctx (this, ctr_xlator_ctx,
+ old_pgfid, old_base_name);
+ if (!ctr_hard_link) {
+ gf_log (this->name, GF_LOG_TRACE, "Hard link doesnt exist"
+ " in the list");
+ /* Since the hard link is not present in the list
+ * we add it to the list */
+ ret = ctr_add_hard_link (this, ctr_xlator_ctx,
+ pgfid, base_name);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed adding"
+ "hard link to the list");
+ goto out;
+ }
+ ret = 0;
+ goto out;
+ }
+
+ /* update the hard link */
+ gf_uuid_copy (ctr_hard_link->pgfid, pgfid);
+ GF_FREE (&ctr_hard_link->base_name);
+ ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name);
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed copying basename"
+ "to ctr_hard_link");
+ /* delete the corrupted entry */
+ __delete_hard_link_from_list (&ctr_hard_link);
+ ctr_hard_link = NULL;
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ UNLOCK (&ctr_xlator_ctx->lock);
+
+ return ret;
+}
+
+
+
+
+/* Delete all hardlinks */
+static inline int
+ctr_delete_all_hard_link (xlator_t *this,
+ ctr_xlator_ctx_t *ctr_xlator_ctx)
+{
+ int ret = -1;
+ ctr_hard_link_t *ctr_hard_link = NULL;
+ ctr_hard_link_t *tmp = NULL;
+
+ GF_ASSERT (ctr_xlator_ctx);
+
+ LOCK (&ctr_xlator_ctx->lock);
+
+ list_for_each_entry_safe(ctr_hard_link, tmp,
+ &ctr_xlator_ctx->hardlink_list, list)
+ {
+ /*Remove hard link from list*/
+ __delete_hard_link_from_list (&ctr_hard_link);
+ ctr_hard_link = NULL;
+
+ }
+
+
+ UNLOCK (&ctr_xlator_ctx->lock);
+
+ ret = 0;
+
+ return ret;
+}
+
+
+/* Please lock the inode before using this function */
+static inline ctr_xlator_ctx_t *
+__get_ctr_xlator_ctx (xlator_t *this,
+ inode_t *inode)
+{
+ int ret = 0;
+ uint64_t _addr = 0;
+ ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (inode);
+
+ ret = __inode_ctx_get (inode, this, &_addr);
+ if (ret < 0)
+ _addr = 0;
+ if (_addr != 0) {
+ ctr_xlator_ctx = (ctr_xlator_ctx_t *) (long)_addr;
+ }
+
+ return ctr_xlator_ctx;
+}
+
+
+ctr_xlator_ctx_t *
+init_ctr_xlator_ctx (xlator_t *this,
+ inode_t *inode)
+{
+ int ret = -1;
+ uint64_t _addr = 0;
+ ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
+
+ GF_ASSERT (this);
+ GF_ASSERT (inode);
+
+ LOCK (&inode->lock);
+ {
+ ctr_xlator_ctx = __get_ctr_xlator_ctx (this, inode);
+ if (ctr_xlator_ctx) {
+ ret = 0;
+ goto out;
+ }
+ ctr_xlator_ctx = GF_CALLOC (1, sizeof (*ctr_xlator_ctx),
+ gf_ctr_mt_xlator_ctx);
+ if (!ctr_xlator_ctx)
+ goto out;
+
+ ret = LOCK_INIT (&ctr_xlator_ctx->lock);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed init lock %s", strerror(ret));
+ goto out;
+ }
+ _addr = (uint64_t) ctr_xlator_ctx;
+
+ ret = __inode_ctx_set (inode, this, &_addr);
+ if (ret) {
+ goto out;
+ }
+
+ INIT_LIST_HEAD (&ctr_xlator_ctx->hardlink_list);
+
+ }
+ ret = 0;
+out:
+ if (ret) {
+ GF_FREE (ctr_xlator_ctx);
+ ctr_xlator_ctx = NULL;
+ }
+
+ UNLOCK (&inode->lock);
+
+ return ctr_xlator_ctx;
+}
+
+
+
+
+void
+fini_ctr_xlator_ctx (xlator_t *this,
+ inode_t *inode)
+{
+ int ret = 0;
+ uint64_t _addr = 0;
+ ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
+
+
+ inode_ctx_del (inode, this, &_addr);
+ if (!_addr)
+ return;
+
+ ctr_xlator_ctx = (ctr_xlator_ctx_t *) (long) _addr;
+
+ ret = ctr_delete_all_hard_link (this, ctr_xlator_ctx);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING , "Failed deleting all hard"
+ " links from inode context");
+ }
+
+ LOCK_DESTROY (&ctr_xlator_ctx->lock);
+
+ GF_FREE (ctr_xlator_ctx);
+
+}
+
+
+
+
+ctr_xlator_ctx_t *
+get_ctr_xlator_ctx (xlator_t *this,
+ inode_t *inode)
+{
+ ctr_xlator_ctx_t *ctr_xlator_ctx = NULL;
+
+ LOCK (&inode->lock);
+ ctr_xlator_ctx = __get_ctr_xlator_ctx (this, inode);
+ UNLOCK (&inode->lock);
+
+ return ctr_xlator_ctx;
+}
+