diff options
author | vmallika <vmallika@redhat.com> | 2015-08-27 21:11:53 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2015-08-29 23:01:30 -0700 |
commit | a5f00c1c29f71bd9135bba38bd0602a1e8ce71b7 (patch) | |
tree | ccc316e0b79d25f0010e1523210122383122480e | |
parent | 5b3d64b734f463da3344218c6a76aadddbf9cde4 (diff) |
marker: preserve previous dirty flag during update txn
In case if dir has become dirty because of brick crash,
this dirty flag on disk was getting reset in the
next update txn.
This patch now gets the dirty flag before setting the flag
in the update txn and if this 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>
Reviewed-on: http://review.gluster.org/12032
Tested-by: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
-rw-r--r-- | 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 4dd457927d2..2049dd01f6a 100644 --- a/xlators/features/marker/src/marker-quota.c +++ b/xlators/features/marker/src/marker-quota.c @@ -2387,18 +2387,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; } @@ -2408,14 +2420,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 " @@ -2424,6 +2470,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; @@ -3011,6 +3078,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; @@ -3080,7 +3148,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; @@ -3102,11 +3170,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); @@ -3160,6 +3230,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; @@ -3300,7 +3371,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; @@ -3318,8 +3390,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; @@ -3340,11 +3414,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); |