summaryrefslogtreecommitdiffstats
path: root/xlators/features/marker
diff options
context:
space:
mode:
authorvmallika <vmallika@redhat.com>2015-08-27 21:11:53 +0530
committerKaushal M <kaushal@redhat.com>2015-08-31 04:14:44 -0700
commit06a9b9f7a911b75a09eb3cc1b5d44b2392ad141e (patch)
treed43f9ef07f529c7a30e78b91916a1b0f86343ced /xlators/features/marker
parent713f59cc197d86c5048e5cab2d3d3ae502634ed7 (diff)
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: I10b81e5c0d9ffa00082171e295199d924a81ee0e BUG: 1257441 Signed-off-by: vmallika <vmallika@redhat.com> Reviewed-on: http://review.gluster.org/12037 Tested-by: Gluster Build System <jenkins@build.gluster.com> Tested-by: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Kaushal M <kaushal@redhat.com>
Diffstat (limited to 'xlators/features/marker')
-rw-r--r--xlators/features/marker/src/marker-quota.c106
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 edea8fb7254..0ba30bb8eaf 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);