Blob Blame History Raw
From b0061ce310b487858b74dbaa8266a61df87dafb6 Mon Sep 17 00:00:00 2001
From: vmallika <vmallika@redhat.com>
Date: Thu, 27 Aug 2015 21:11:53 +0530
Subject: [PATCH 317/320] marker: preserve previous dirty flag during update txn

This is a backport of http://review.gluster.org/#/c/12032/

In case if dir has become dirty because of crash,
this dirty flag on disk was getting reset in the
next update txn.

This patch now gets the dirty flag before setting
in the update txn and it the value is dirty, it keeps
the flag dirty, so that inspect_directory can fix the
dirty dir

> Change-Id: Iab2c343dbe19bd3b291adbfeebe6d9785b6bb9e3
> BUG: 1251454
> Signed-off-by: vmallika <vmallika@redhat.com>

Change-Id: I4a34c8a0e13aa1c21cd9ddbb272c7e22a4137004
BUG: 1251457
Signed-off-by: vmallika <vmallika@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/56569
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
---
 xlators/features/marker/src/marker-quota.c |  106 ++++++++++++++++++++++++----
 1 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c
index b582158..d9063a8 100644
--- a/xlators/features/marker/src/marker-quota.c
+++ b/xlators/features/marker/src/marker-quota.c
@@ -2386,18 +2386,30 @@ out:
 }
 
 int32_t
-mq_mark_dirty (xlator_t *this, loc_t *loc, int32_t dirty)
+mq_get_set_dirty (xlator_t *this, loc_t *loc, int32_t dirty,
+                  int32_t *prev_dirty)
 {
-        int32_t            ret      = -1;
-        dict_t            *dict     = NULL;
-        quota_inode_ctx_t *ctx      = NULL;
+        int32_t              ret              = -1;
+        int8_t               value            = 0;
+        quota_inode_ctx_t   *ctx              = NULL;
+        dict_t              *dict             = NULL;
+        dict_t              *rsp_dict         = NULL;
 
         GF_VALIDATE_OR_GOTO ("marker", loc, out);
         GF_VALIDATE_OR_GOTO ("marker", loc->inode, out);
+        GF_VALIDATE_OR_GOTO ("marker", prev_dirty, out);
+
+        ret = mq_inode_ctx_get (loc->inode, this, &ctx);
+        if (ret < 0) {
+                gf_log (this->name, GF_LOG_ERROR, "failed to get inode ctx for "
+                        "%s", loc->path);
+                goto out;
+        }
 
         dict = dict_new ();
         if (!dict) {
                 gf_log (this->name, GF_LOG_ERROR, "dict_new failed");
+                ret = -1;
                 goto out;
         }
 
@@ -2407,14 +2419,48 @@ mq_mark_dirty (xlator_t *this, loc_t *loc, int32_t dirty)
                 goto out;
         }
 
-        ret = syncop_setxattr (FIRST_CHILD(this), loc, dict, 0, NULL, NULL);
+        ret = syncop_xattrop (FIRST_CHILD(this), loc, GF_XATTROP_GET_AND_SET,
+                              dict, NULL, &rsp_dict);
         if (ret < 0) {
                 gf_log_callingfn (this->name, (-ret == ENOENT || -ret == ESTALE)
-                        ? GF_LOG_DEBUG:GF_LOG_ERROR, "setxattr dirty = %d "
-                        "failed for %s: %s", dirty, loc->path, strerror (-ret));
+                          ? GF_LOG_DEBUG:GF_LOG_ERROR, "xattrop failed "
+                          "for %s: %s", loc->path, strerror (-ret));
                 goto out;
         }
 
+        *prev_dirty = 0;
+        if (rsp_dict) {
+                ret = dict_get_int8 (rsp_dict, QUOTA_DIRTY_KEY, &value);
+                if (ret == 0)
+                        *prev_dirty = value;
+        }
+
+        LOCK (&ctx->lock);
+        {
+                ctx->dirty = dirty;
+        }
+        UNLOCK (&ctx->lock);
+        ret = 0;
+out:
+        if (dict)
+                dict_unref (dict);
+
+        if (rsp_dict)
+                dict_unref (rsp_dict);
+
+        return ret;
+}
+
+int32_t
+mq_mark_dirty (xlator_t *this, loc_t *loc, int32_t dirty)
+{
+        int32_t            ret      = -1;
+        dict_t            *dict     = NULL;
+        quota_inode_ctx_t *ctx      = NULL;
+
+        GF_VALIDATE_OR_GOTO ("marker", loc, out);
+        GF_VALIDATE_OR_GOTO ("marker", loc->inode, out);
+
         ret = mq_inode_ctx_get (loc->inode, this, &ctx);
         if (ret < 0) {
                 gf_log (this->name, GF_LOG_ERROR, "failed to get inode ctx for "
@@ -2423,6 +2469,27 @@ mq_mark_dirty (xlator_t *this, loc_t *loc, int32_t dirty)
                 goto out;
         }
 
+        dict = dict_new ();
+        if (!dict) {
+                ret = -1;
+                gf_log (this->name, GF_LOG_ERROR, "dict_new failed");
+                goto out;
+        }
+
+        ret = dict_set_int8 (dict, QUOTA_DIRTY_KEY, dirty);
+        if (ret < 0) {
+                gf_log (this->name, GF_LOG_ERROR, "dict_set failed");
+                goto out;
+        }
+
+        ret = syncop_setxattr (FIRST_CHILD(this), loc, dict, 0, NULL, NULL);
+        if (ret < 0) {
+                gf_log_callingfn (this->name, (-ret == ENOENT || -ret == ESTALE)
+                        ? GF_LOG_DEBUG:GF_LOG_ERROR, "setxattr dirty = %d "
+                        "failed for %s: %s", dirty, loc->path, strerror (-ret));
+                goto out;
+        }
+
         LOCK (&ctx->lock);
         {
                 ctx->dirty = dirty;
@@ -3010,6 +3077,7 @@ int32_t
 mq_reduce_parent_size_task (void *opaque)
 {
         int32_t                  ret           = -1;
+        int32_t                  prev_dirty    = 0;
         quota_inode_ctx_t       *ctx           = NULL;
         quota_inode_ctx_t       *parent_ctx    = NULL;
         inode_contribution_t    *contribution  = NULL;
@@ -3079,7 +3147,7 @@ mq_reduce_parent_size_task (void *opaque)
                 UNLOCK (&contribution->lock);
         }
 
-        ret = mq_mark_dirty (this, &parent_loc, 1);
+        ret = mq_get_set_dirty (this, &parent_loc, 1, &prev_dirty);
         if (ret < 0)
                 goto out;
         dirty = _gf_true;
@@ -3101,11 +3169,13 @@ mq_reduce_parent_size_task (void *opaque)
 
 out:
         if (dirty) {
-                if (ret < 0) {
+                if (ret < 0 || prev_dirty) {
                         /* On failure clear dirty status flag.
                          * In the next lookup inspect_directory_xattr
                          * can set the status flag and fix the
-                         * dirty directory
+                         * dirty directory.
+                         * Do the same if dir was dirty before
+                         * the txn
                          */
                         ret = mq_inode_ctx_get (parent_loc.inode, this,
                                                 &parent_ctx);
@@ -3159,6 +3229,7 @@ int
 mq_initiate_quota_task (void *opaque)
 {
         int32_t                ret        = -1;
+        int32_t                prev_dirty = 0;
         loc_t                  child_loc  = {0,};
         loc_t                  parent_loc = {0,};
         gf_boolean_t           locked     = _gf_false;
@@ -3299,7 +3370,8 @@ mq_initiate_quota_task (void *opaque)
                 if (quota_meta_is_null (&delta))
                         goto out;
 
-                ret = mq_mark_dirty (this, &parent_loc, 1);
+                prev_dirty = 0;
+                ret = mq_get_set_dirty (this, &parent_loc, 1, &prev_dirty);
                 if (ret < 0)
                         goto out;
                 dirty = _gf_true;
@@ -3317,8 +3389,10 @@ mq_initiate_quota_task (void *opaque)
                         goto out;
                 }
 
-                ret = mq_mark_dirty (this, &parent_loc, 0);
-                dirty = _gf_false;
+                if (prev_dirty == 0) {
+                        ret = mq_mark_dirty (this, &parent_loc, 0);
+                        dirty = _gf_false;
+                }
 
                 ret = mq_lock (this, &parent_loc, F_UNLCK);
                 locked = _gf_false;
@@ -3339,11 +3413,13 @@ mq_initiate_quota_task (void *opaque)
 
 out:
         if (dirty) {
-                if (ret < 0) {
+                if (ret < 0 || prev_dirty) {
                         /* On failure clear dirty status flag.
                          * In the next lookup inspect_directory_xattr
                          * can set the status flag and fix the
-                         * dirty directory
+                         * dirty directory.
+                         * Do the same if the dir was dirty before
+                         * txn
                          */
                         ret = mq_inode_ctx_get (parent_loc.inode, this,
                                                 &parent_ctx);
-- 
1.7.1