cb8e9e
From 9f819fe340a346844b75cde8a676470bd8b1b907 Mon Sep 17 00:00:00 2001
cb8e9e
From: vmallika <vmallika@redhat.com>
cb8e9e
Date: Wed, 24 Jun 2015 11:56:30 +0530
cb8e9e
Subject: [PATCH 145/190] quota/marker: fix mem-leak in marker
cb8e9e
cb8e9e
This is a backport of http://review.gluster.org/#/c/11361/
cb8e9e
cb8e9e
> When removing contribution xattr, we also need to free
cb8e9e
> contribution node in memory.
cb8e9e
> Use ref/unref mechanism to handle contribution node memory
cb8e9e
>
cb8e9e
> local->xdata should be freed in mq_local_unref
cb8e9e
>
cb8e9e
> There is another huge memory consumption happens
cb8e9e
> in function mq_inspect_directory_xattr_task
cb8e9e
> where dirty flag is not set.
cb8e9e
>
cb8e9e
> Change-Id: Ieca3ab4bf410c51259560e778bce4e81b9d888bf
cb8e9e
> BUG: 1207735
cb8e9e
> Signed-off-by: vmallika <vmallika@redhat.com>
cb8e9e
> Reviewed-on: http://review.gluster.org/11361
cb8e9e
> Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
cb8e9e
> Tested-by: NetBSD Build System <jenkins@build.gluster.org>
cb8e9e
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
cb8e9e
> Tested-by: Raghavendra G <rgowdapp@redhat.com>
cb8e9e
cb8e9e
Change-Id: Id82bd071433f8141c6fa1d4ad1a488604ff33978
cb8e9e
BUG: 1224177
cb8e9e
Signed-off-by: vmallika <vmallika@redhat.com>
cb8e9e
Reviewed-on: https://code.engineering.redhat.com/gerrit/51565
cb8e9e
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
cb8e9e
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
cb8e9e
---
cb8e9e
 xlators/features/marker/src/marker-quota-helper.c |   81 ++++++++----
cb8e9e
 xlators/features/marker/src/marker-quota-helper.h |   18 ++-
cb8e9e
 xlators/features/marker/src/marker-quota.c        |  137 +++++++++++++--------
cb8e9e
 xlators/features/marker/src/marker-quota.h        |    4 +-
cb8e9e
 4 files changed, 157 insertions(+), 83 deletions(-)
cb8e9e
cb8e9e
diff --git a/xlators/features/marker/src/marker-quota-helper.c b/xlators/features/marker/src/marker-quota-helper.c
cb8e9e
index 67801c8..a103bb9 100644
cb8e9e
--- a/xlators/features/marker/src/marker-quota-helper.c
cb8e9e
+++ b/xlators/features/marker/src/marker-quota-helper.c
cb8e9e
@@ -130,6 +130,39 @@ out:
cb8e9e
         return ctx;
cb8e9e
 }
cb8e9e
 
cb8e9e
+void
cb8e9e
+mq_contri_fini (void *data)
cb8e9e
+{
cb8e9e
+        inode_contribution_t *contri = data;
cb8e9e
+
cb8e9e
+        LOCK_DESTROY (&contri->lock);
cb8e9e
+        GF_FREE (contri);
cb8e9e
+}
cb8e9e
+
cb8e9e
+inode_contribution_t*
cb8e9e
+mq_contri_init (inode_t *inode)
cb8e9e
+{
cb8e9e
+        inode_contribution_t *contri   = NULL;
cb8e9e
+        int32_t               ret      = 0;
cb8e9e
+
cb8e9e
+        QUOTA_ALLOC (contri, inode_contribution_t, ret);
cb8e9e
+        if (ret == -1)
cb8e9e
+                goto out;
cb8e9e
+
cb8e9e
+        GF_REF_INIT (contri, mq_contri_fini);
cb8e9e
+
cb8e9e
+        contri->contribution = 0;
cb8e9e
+        contri->file_count = 0;
cb8e9e
+        contri->dir_count = 0;
cb8e9e
+        gf_uuid_copy (contri->gfid, inode->gfid);
cb8e9e
+
cb8e9e
+        LOCK_INIT (&contri->lock);
cb8e9e
+        INIT_LIST_HEAD (&contri->contri_list);
cb8e9e
+
cb8e9e
+out:
cb8e9e
+        return contri;
cb8e9e
+}
cb8e9e
+
cb8e9e
 inode_contribution_t *
cb8e9e
 mq_get_contribution_node (inode_t *inode, quota_inode_ctx_t *ctx)
cb8e9e
 {
cb8e9e
@@ -139,35 +172,26 @@ mq_get_contribution_node (inode_t *inode, quota_inode_ctx_t *ctx)
cb8e9e
         if (!inode || !ctx)
cb8e9e
                 goto out;
cb8e9e
 
cb8e9e
-        list_for_each_entry (temp, &ctx->contribution_head, contri_list) {
cb8e9e
-                if (gf_uuid_compare (temp->gfid, inode->gfid) == 0) {
cb8e9e
-                        contri = temp;
cb8e9e
-                        goto out;
cb8e9e
+        LOCK (&ctx->lock);
cb8e9e
+        {
cb8e9e
+                list_for_each_entry (temp, &ctx->contribution_head,
cb8e9e
+                                     contri_list) {
cb8e9e
+                        if (gf_uuid_compare (temp->gfid, inode->gfid) == 0) {
cb8e9e
+                                contri = temp;
cb8e9e
+                                GF_REF_GET (contri);
cb8e9e
+                                break;
cb8e9e
+                        }
cb8e9e
                 }
cb8e9e
         }
cb8e9e
+        UNLOCK (&ctx->lock);
cb8e9e
 out:
cb8e9e
         return contri;
cb8e9e
 }
cb8e9e
 
cb8e9e
-
cb8e9e
-int32_t
cb8e9e
-mq_delete_contribution_node (dict_t *dict, char *key,
cb8e9e
-                             inode_contribution_t *contribution)
cb8e9e
-{
cb8e9e
-        if (dict_get (dict, key) != NULL)
cb8e9e
-                goto out;
cb8e9e
-
cb8e9e
-        QUOTA_FREE_CONTRIBUTION_NODE (contribution);
cb8e9e
-out:
cb8e9e
-        return 0;
cb8e9e
-}
cb8e9e
-
cb8e9e
-
cb8e9e
 inode_contribution_t *
cb8e9e
 __mq_add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx,
cb8e9e
                                 loc_t *loc)
cb8e9e
 {
cb8e9e
-        int32_t               ret          = 0;
cb8e9e
         inode_contribution_t *contribution = NULL;
cb8e9e
 
cb8e9e
         if (!loc->parent) {
cb8e9e
@@ -190,17 +214,10 @@ __mq_add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx,
cb8e9e
                 }
cb8e9e
         }
cb8e9e
 
cb8e9e
-        QUOTA_ALLOC (contribution, inode_contribution_t, ret);
cb8e9e
-        if (ret == -1)
cb8e9e
+        contribution = mq_contri_init (loc->parent);
cb8e9e
+        if (contribution == NULL)
cb8e9e
                 goto out;
cb8e9e
 
cb8e9e
-        contribution->contribution = 0;
cb8e9e
-
cb8e9e
-        gf_uuid_copy (contribution->gfid, loc->parent->gfid);
cb8e9e
-
cb8e9e
-	LOCK_INIT (&contribution->lock);
cb8e9e
-        INIT_LIST_HEAD (&contribution->contri_list);
cb8e9e
-
cb8e9e
         list_add_tail (&contribution->contri_list, &ctx->contribution_head);
cb8e9e
 
cb8e9e
 out:
cb8e9e
@@ -224,6 +241,8 @@ mq_add_new_contribution_node (xlator_t *this, quota_inode_ctx_t *ctx,
cb8e9e
         LOCK (&ctx->lock);
cb8e9e
         {
cb8e9e
                 contribution = __mq_add_new_contribution_node (this, ctx, loc);
cb8e9e
+                if (contribution)
cb8e9e
+                        GF_REF_GET (contribution);
cb8e9e
         }
cb8e9e
         UNLOCK (&ctx->lock);
cb8e9e
 
cb8e9e
@@ -392,6 +411,12 @@ mq_local_unref (xlator_t *this, quota_local_t *local)
cb8e9e
         if (local->fd != NULL)
cb8e9e
                 fd_unref (local->fd);
cb8e9e
 
cb8e9e
+        if (local->contri)
cb8e9e
+                GF_REF_PUT (local->contri);
cb8e9e
+
cb8e9e
+        if (local->xdata)
cb8e9e
+                dict_unref (local->xdata);
cb8e9e
+
cb8e9e
         loc_wipe (&local->loc);
cb8e9e
 
cb8e9e
         loc_wipe (&local->parent_loc);
cb8e9e
diff --git a/xlators/features/marker/src/marker-quota-helper.h b/xlators/features/marker/src/marker-quota-helper.h
cb8e9e
index 161413d..f69447b 100644
cb8e9e
--- a/xlators/features/marker/src/marker-quota-helper.h
cb8e9e
+++ b/xlators/features/marker/src/marker-quota-helper.h
cb8e9e
@@ -18,10 +18,14 @@
cb8e9e
 
cb8e9e
 #include "marker.h"
cb8e9e
 
cb8e9e
-#define QUOTA_FREE_CONTRIBUTION_NODE(_contribution)     \
cb8e9e
-        do {                                            \
cb8e9e
-                list_del (&_contribution->contri_list); \
cb8e9e
-                GF_FREE (_contribution);                \
cb8e9e
+#define QUOTA_FREE_CONTRIBUTION_NODE(ctx, _contribution)          \
cb8e9e
+        do {                                                      \
cb8e9e
+                LOCK (&ctx->lock);                                \
cb8e9e
+                {                                                 \
cb8e9e
+                        list_del (&_contribution->contri_list);   \
cb8e9e
+                        GF_REF_PUT (_contribution);               \
cb8e9e
+                }                                                 \
cb8e9e
+                UNLOCK (&ctx->lock);                              \
cb8e9e
         } while (0)
cb8e9e
 
cb8e9e
 #define QUOTA_SAFE_INCREMENT(lock, var)                 \
cb8e9e
@@ -67,6 +71,12 @@ mq_local_ref (quota_local_t *);
cb8e9e
 int32_t
cb8e9e
 mq_local_unref (xlator_t *, quota_local_t *);
cb8e9e
 
cb8e9e
+void
cb8e9e
+mq_contri_fini (void *data);
cb8e9e
+
cb8e9e
+inode_contribution_t*
cb8e9e
+mq_contri_init (inode_t *inode);
cb8e9e
+
cb8e9e
 inode_contribution_t *
cb8e9e
 mq_get_contribution_node (inode_t *, quota_inode_ctx_t *);
cb8e9e
 
cb8e9e
diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c
cb8e9e
index e183829..bbe2d9d 100644
cb8e9e
--- a/xlators/features/marker/src/marker-quota.c
cb8e9e
+++ b/xlators/features/marker/src/marker-quota.c
cb8e9e
@@ -887,7 +887,10 @@ mq_update_dirty_inode (xlator_t *this, loc_t *loc, quota_inode_ctx_t *ctx,
cb8e9e
 
cb8e9e
         local->ctx = ctx;
cb8e9e
 
cb8e9e
-        local->contri = contribution;
cb8e9e
+        if (contribution) {
cb8e9e
+                local->contri = contribution;
cb8e9e
+                GF_REF_GET (local->contri);
cb8e9e
+        }
cb8e9e
 
cb8e9e
         lock.l_type = F_WRLCK;
cb8e9e
         lock.l_whence = SEEK_SET;
cb8e9e
@@ -1094,6 +1097,9 @@ free_value:
cb8e9e
 err:
cb8e9e
         dict_unref (dict);
cb8e9e
 
cb8e9e
+        if (contri)
cb8e9e
+                GF_REF_PUT (contri);
cb8e9e
+
cb8e9e
 out:
cb8e9e
         if (ret < 0) {
cb8e9e
                 mq_xattr_creation_release_lock (frame, NULL, this, 0, 0, NULL);
cb8e9e
@@ -1267,7 +1273,6 @@ mq_get_parent_inode_local (xlator_t *this, quota_local_t *local)
cb8e9e
 {
cb8e9e
         int32_t            ret = -1;
cb8e9e
         quota_inode_ctx_t *ctx = NULL;
cb8e9e
-        inode_contribution_t *contribution = NULL;
cb8e9e
 
cb8e9e
         GF_VALIDATE_OR_GOTO ("marker", this, out);
cb8e9e
         GF_VALIDATE_OR_GOTO ("marker", local, out);
cb8e9e
@@ -1332,9 +1337,8 @@ mq_get_parent_inode_local (xlator_t *this, quota_local_t *local)
cb8e9e
            contribution will be at the end of the list. So get the proper
cb8e9e
            parent's contribution, by searching the entire list.
cb8e9e
         */
cb8e9e
-        contribution = mq_get_contribution_node (local->loc.parent, ctx);
cb8e9e
-        GF_ASSERT (contribution != NULL);
cb8e9e
-        local->contri = contribution;
cb8e9e
+        local->contri = mq_get_contribution_node (local->loc.parent, ctx);
cb8e9e
+        GF_ASSERT (local->contri != NULL);
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
 out:
cb8e9e
@@ -1997,7 +2001,10 @@ mq_prepare_txn_frame (xlator_t *this, loc_t *loc,
cb8e9e
                 goto fr_destroy;
cb8e9e
 
cb8e9e
         local->ctx = ctx;
cb8e9e
-        local->contri = contri;
cb8e9e
+        if (contri) {
cb8e9e
+                local->contri = contri;
cb8e9e
+                GF_REF_GET (local->contri);
cb8e9e
+        }
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
         *new_frame = frame;
cb8e9e
@@ -2247,6 +2254,9 @@ out:
cb8e9e
         if (dict)
cb8e9e
                 dict_unref (dict);
cb8e9e
 
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -2574,7 +2584,8 @@ out:
cb8e9e
 }
cb8e9e
 
cb8e9e
 int32_t
cb8e9e
-mq_remove_contri (xlator_t *this, loc_t *loc, inode_contribution_t *contri)
cb8e9e
+mq_remove_contri (xlator_t *this, loc_t *loc, quota_inode_ctx_t *ctx,
cb8e9e
+                  inode_contribution_t *contri, quota_meta_t *delta)
cb8e9e
 {
cb8e9e
         int32_t              ret                         = -1;
cb8e9e
         char                 contri_key[CONTRI_KEY_MAX]  = {0, };
cb8e9e
@@ -2588,7 +2599,8 @@ mq_remove_contri (xlator_t *this, loc_t *loc, inode_contribution_t *contri)
cb8e9e
 
cb8e9e
         ret = syncop_removexattr (FIRST_CHILD(this), loc, contri_key, 0, NULL);
cb8e9e
         if (ret < 0) {
cb8e9e
-                if (-ret == ENOENT || -ret == ESTALE || -ret == ENODATA) {
cb8e9e
+                if (-ret == ENOENT || -ret == ESTALE || -ret == ENODATA ||
cb8e9e
+                    -ret == ENOATTR) {
cb8e9e
                         /* Remove contri in done when unlink operation is
cb8e9e
                          * performed, so return success on ENOENT/ESTSLE
cb8e9e
                          * rename operation removes xattr earlier,
cb8e9e
@@ -2605,14 +2617,16 @@ mq_remove_contri (xlator_t *this, loc_t *loc, inode_contribution_t *contri)
cb8e9e
 
cb8e9e
         LOCK (&contri->lock);
cb8e9e
         {
cb8e9e
-                contri->contribution = 0;
cb8e9e
-                contri->file_count = 0;
cb8e9e
-                contri->dir_count = 0;
cb8e9e
+                contri->contribution += delta->size;
cb8e9e
+                contri->file_count += delta->file_count;
cb8e9e
+                contri->dir_count += delta->dir_count;
cb8e9e
         }
cb8e9e
         UNLOCK (&contri->lock);
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
+
cb8e9e
 out:
cb8e9e
+        QUOTA_FREE_CONTRIBUTION_NODE (ctx, contri);
cb8e9e
 
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
@@ -2809,10 +2823,12 @@ mq_start_quota_txn_v2 (xlator_t *this, loc_t *loc, quota_inode_ctx_t *ctx,
cb8e9e
         gf_boolean_t       status     = _gf_true;
cb8e9e
         quota_meta_t       delta      = {0, };
cb8e9e
 
cb8e9e
+        GF_VALIDATE_OR_GOTO ("marker", contri, out);
cb8e9e
+        GF_REF_GET (contri);
cb8e9e
+
cb8e9e
         GF_VALIDATE_OR_GOTO ("marker", loc, out);
cb8e9e
         GF_VALIDATE_OR_GOTO ("marker", loc->inode, out);
cb8e9e
         GF_VALIDATE_OR_GOTO ("marker", ctx, out);
cb8e9e
-        GF_VALIDATE_OR_GOTO ("marker", contri, out);
cb8e9e
 
cb8e9e
         ret = mq_loc_copy (&child_loc, loc);
cb8e9e
         if (ret < 0) {
cb8e9e
@@ -2907,6 +2923,8 @@ mq_start_quota_txn_v2 (xlator_t *this, loc_t *loc, quota_inode_ctx_t *ctx,
cb8e9e
                         ret = -1;
cb8e9e
                         goto out;
cb8e9e
                 }
cb8e9e
+
cb8e9e
+                GF_REF_PUT (contri);
cb8e9e
                 contri = mq_get_contribution_node (child_loc.parent, ctx);
cb8e9e
                 GF_ASSERT (contri != NULL);
cb8e9e
         }
cb8e9e
@@ -2923,6 +2941,8 @@ out:
cb8e9e
 
cb8e9e
         loc_wipe (&child_loc);
cb8e9e
         loc_wipe (&parent_loc);
cb8e9e
+        if (contri)
cb8e9e
+                GF_REF_PUT (contri);
cb8e9e
 
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
@@ -3100,11 +3120,12 @@ mq_reduce_parent_size_task (void *opaque)
cb8e9e
                 goto out;
cb8e9e
         dirty = _gf_true;
cb8e9e
 
cb8e9e
-        ret = mq_remove_contri (this, loc, contribution);
cb8e9e
+        mq_sub_meta (&delta, NULL);
cb8e9e
+
cb8e9e
+        ret = mq_remove_contri (this, loc, ctx, contribution, &delta);
cb8e9e
         if (ret < 0)
cb8e9e
                 goto out;
cb8e9e
 
cb8e9e
-        mq_sub_meta (&delta, NULL);
cb8e9e
         ret = mq_update_size (this, &parent_loc, &delta);
cb8e9e
         if (ret < 0)
cb8e9e
                 goto out;
cb8e9e
@@ -3121,6 +3142,9 @@ out:
cb8e9e
 
cb8e9e
         loc_wipe (&parent_loc);
cb8e9e
 
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -3203,6 +3227,9 @@ mq_initiate_quota_task (void *opaque)
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
 out:
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -3452,13 +3479,18 @@ mq_inspect_directory_xattr_task (void *opaque)
cb8e9e
         }
cb8e9e
 
cb8e9e
         ret = dict_get_int8 (dict, QUOTA_DIRTY_KEY, &dirty);
cb8e9e
-        if (ret < 0)
cb8e9e
-                goto out;
cb8e9e
+        if (ret < 0) {
cb8e9e
+                /* dirty is set only on the first file write operation
cb8e9e
+                 * so ignore this error
cb8e9e
+                 */
cb8e9e
+                ret = 0;
cb8e9e
+                dirty = 0;
cb8e9e
+        }
cb8e9e
 
cb8e9e
         ret = _quota_dict_get_meta (this, dict, QUOTA_SIZE_KEY, &size,
cb8e9e
                                     IA_IFDIR, _gf_false);
cb8e9e
         if (ret < 0)
cb8e9e
-                goto out;
cb8e9e
+                goto create_xattr;
cb8e9e
 
cb8e9e
         if (!loc_is_root(loc)) {
cb8e9e
                 GET_CONTRI_KEY (contri_key, contribution->gfid, ret);
cb8e9e
@@ -3468,7 +3500,7 @@ mq_inspect_directory_xattr_task (void *opaque)
cb8e9e
                 ret = _quota_dict_get_meta (this, dict, contri_key, &contri,
cb8e9e
                                             IA_IFDIR, _gf_false);
cb8e9e
                 if (ret < 0)
cb8e9e
-                        goto out;
cb8e9e
+                        goto create_xattr;
cb8e9e
 
cb8e9e
                 LOCK (&contribution->lock);
cb8e9e
                 {
cb8e9e
@@ -3499,11 +3531,15 @@ mq_inspect_directory_xattr_task (void *opaque)
cb8e9e
                 mq_initiate_quota_blocking_txn (this, loc);
cb8e9e
 
cb8e9e
         ret = 0;
cb8e9e
-out:
cb8e9e
+
cb8e9e
+create_xattr:
cb8e9e
         if (ret < 0)
cb8e9e
                 ret = mq_create_xattrs_blocking_txn (this, loc);
cb8e9e
 
cb8e9e
 err:
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -3575,41 +3611,32 @@ mq_inspect_file_xattr_task (void *opaque)
cb8e9e
         }
cb8e9e
         UNLOCK (&ctx->lock);
cb8e9e
 
cb8e9e
-        list_for_each_entry (contribution, &ctx->contribution_head,
cb8e9e
-                             contri_list) {
cb8e9e
-
cb8e9e
-                GET_CONTRI_KEY (contri_key, contribution->gfid, ret);
cb8e9e
-                if (ret < 0)
cb8e9e
-                        continue;
cb8e9e
-
cb8e9e
-                ret = _quota_dict_get_meta (this, dict, contri_key, &contri,
cb8e9e
-                                            IA_IFREG, _gf_true);
cb8e9e
-                if (ret < 0) {
cb8e9e
-                        ret = mq_create_xattrs_blocking_txn (this, loc);
cb8e9e
-                } else {
cb8e9e
-                        LOCK (&contribution->lock);
cb8e9e
-                        {
cb8e9e
-                                contribution->contribution = contri.size;
cb8e9e
-                                contribution->file_count = contri.file_count;
cb8e9e
-                                contribution->dir_count = contri.dir_count;
cb8e9e
-                        }
cb8e9e
-                        UNLOCK (&contribution->lock);
cb8e9e
+        GET_CONTRI_KEY (contri_key, contribution->gfid, ret);
cb8e9e
+        if (ret < 0)
cb8e9e
+                goto out;
cb8e9e
 
cb8e9e
-                        mq_compute_delta (&delta, &size, &contri);
cb8e9e
-                        if (!quota_meta_is_null (&delta)) {
cb8e9e
-                                mq_initiate_quota_blocking_txn (this, loc);
cb8e9e
-                                /* TODO: revist this code when fixing hardlinks
cb8e9e
-                                 */
cb8e9e
-                                break;
cb8e9e
-                        }
cb8e9e
+        ret = _quota_dict_get_meta (this, dict, contri_key, &contri,
cb8e9e
+                                    IA_IFREG, _gf_true);
cb8e9e
+        if (ret < 0) {
cb8e9e
+                ret = mq_create_xattrs_blocking_txn (this, loc);
cb8e9e
+        } else {
cb8e9e
+                LOCK (&contribution->lock);
cb8e9e
+                {
cb8e9e
+                        contribution->contribution = contri.size;
cb8e9e
+                        contribution->file_count = contri.file_count;
cb8e9e
+                        contribution->dir_count = contri.dir_count;
cb8e9e
                 }
cb8e9e
+                UNLOCK (&contribution->lock);
cb8e9e
 
cb8e9e
-                /* TODO: loc->parent might need to be assigned to corresponding
cb8e9e
-                 * contribution inode. We need to handle hard links here
cb8e9e
-                */
cb8e9e
+                mq_compute_delta (&delta, &size, &contri);
cb8e9e
+                if (!quota_meta_is_null (&delta))
cb8e9e
+                        mq_initiate_quota_blocking_txn (this, loc);
cb8e9e
         }
cb8e9e
+        /* TODO: revist this code when fixing hardlinks */
cb8e9e
 
cb8e9e
 out:
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
 
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
@@ -3952,7 +3979,10 @@ mq_reduce_parent_size (xlator_t *this, loc_t *loc, int64_t contri)
cb8e9e
                 goto out;
cb8e9e
 
cb8e9e
         local->ctx = ctx;
cb8e9e
-        local->contri = contribution;
cb8e9e
+        if (contribution) {
cb8e9e
+                local->contri = contribution;
cb8e9e
+                GF_REF_GET (local->contri);
cb8e9e
+        }
cb8e9e
 
cb8e9e
         ret = mq_inode_loc_fill (NULL, loc->parent, &local->parent_loc);
cb8e9e
         if (ret < 0) {
cb8e9e
@@ -3996,6 +4026,9 @@ out:
cb8e9e
         if (local != NULL)
cb8e9e
                 mq_local_unref (this, local);
cb8e9e
 
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -4030,6 +4063,10 @@ mq_rename_update_newpath (xlator_t *this, loc_t *loc)
cb8e9e
 
cb8e9e
         mq_initiate_quota_txn (this, loc);
cb8e9e
 out:
cb8e9e
+
cb8e9e
+        if (contribution)
cb8e9e
+                GF_REF_PUT (contribution);
cb8e9e
+
cb8e9e
         return ret;
cb8e9e
 }
cb8e9e
 
cb8e9e
@@ -4045,7 +4082,7 @@ mq_forget (xlator_t *this, quota_inode_ctx_t *ctx)
cb8e9e
         list_for_each_entry_safe (contri, next, &ctx->contribution_head,
cb8e9e
                                   contri_list) {
cb8e9e
                 list_del (&contri->contri_list);
cb8e9e
-                GF_FREE (contri);
cb8e9e
+                GF_REF_PUT (contri);
cb8e9e
         }
cb8e9e
 
cb8e9e
         LOCK_DESTROY (&ctx->lock);
cb8e9e
diff --git a/xlators/features/marker/src/marker-quota.h b/xlators/features/marker/src/marker-quota.h
cb8e9e
index a81db7f..2d03dfd 100644
cb8e9e
--- a/xlators/features/marker/src/marker-quota.h
cb8e9e
+++ b/xlators/features/marker/src/marker-quota.h
cb8e9e
@@ -17,6 +17,7 @@
cb8e9e
 
cb8e9e
 #include "xlator.h"
cb8e9e
 #include "marker-mem-types.h"
cb8e9e
+#include "refcount.h"
cb8e9e
 
cb8e9e
 #define QUOTA_XATTR_PREFIX "trusted.glusterfs"
cb8e9e
 #define QUOTA_DIRTY_KEY "trusted.glusterfs.quota.dirty"
cb8e9e
@@ -109,7 +110,8 @@ struct inode_contribution {
cb8e9e
         int64_t          file_count;
cb8e9e
         int64_t          dir_count;
cb8e9e
         uuid_t           gfid;
cb8e9e
-  gf_lock_t lock;
cb8e9e
+        gf_lock_t        lock;
cb8e9e
+        GF_REF_DECL;
cb8e9e
 };
cb8e9e
 typedef struct inode_contribution inode_contribution_t;
cb8e9e
 
cb8e9e
-- 
cb8e9e
1.7.1
cb8e9e