21ab4e
From 6750f6bb329b70733d1673fb8c95d3e4a5d514d6 Mon Sep 17 00:00:00 2001
21ab4e
From: N Balachandran <nbalacha@redhat.com>
21ab4e
Date: Wed, 19 Jul 2017 21:44:55 +0530
21ab4e
Subject: [PATCH 571/576] cluster/dht: Fixed crash in dht_rmdir_is_subvol_empty
21ab4e
21ab4e
The local->call_cnt was being accessed and updated inside
21ab4e
the loop where the entries were being processed and the calls
21ab4e
were being wound.
21ab4e
This could end up in a scenario where the local->call_cnt became
21ab4e
0 before the processing was complete causing the crash when the
21ab4e
next entry was being processed.
21ab4e
21ab4e
> BUG: 1472949
21ab4e
> Signed-off-by: N Balachandran <nbalacha@redhat.com>
21ab4e
> Reviewed-on: https://review.gluster.org/17825
21ab4e
> Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
> Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
21ab4e
> Reviewed-by: Amar Tumballi <amarts@redhat.com>
21ab4e
> Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com>
21ab4e
Change-Id: I930f61f1a1d1948f90d4e58e80b7d6680cf27f2f
21ab4e
BUG: 1471918
21ab4e
Signed-off-by: N Balachandran <nbalacha@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/113509
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
---
21ab4e
 xlators/cluster/dht/src/dht-common.c | 47 ++++++++++++++++++++++++++----------
21ab4e
 1 file changed, 34 insertions(+), 13 deletions(-)
21ab4e
21ab4e
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
21ab4e
index aebea2f..55106fa 100644
21ab4e
--- a/xlators/cluster/dht/src/dht-common.c
21ab4e
+++ b/xlators/cluster/dht/src/dht-common.c
21ab4e
@@ -8330,6 +8330,7 @@ dht_rmdir_linkfile_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this
21ab4e
         }
21ab4e
 
21ab4e
         this_call_cnt = dht_frame_return (readdirp_frame);
21ab4e
+
21ab4e
         if (is_last_call (this_call_cnt))
21ab4e
                 dht_rmdir_readdirp_do (readdirp_frame, this);
21ab4e
 
21ab4e
@@ -8390,8 +8391,9 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
21ab4e
 err:
21ab4e
 
21ab4e
         this_call_cnt = dht_frame_return (readdirp_frame);
21ab4e
-        if (is_last_call (this_call_cnt))
21ab4e
+        if (is_last_call (this_call_cnt)) {
21ab4e
                 dht_rmdir_readdirp_do (readdirp_frame, this);
21ab4e
+        }
21ab4e
 
21ab4e
         DHT_STACK_DESTROY (frame);
21ab4e
         return 0;
21ab4e
@@ -8499,7 +8501,10 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
21ab4e
         dict_t             *xattrs       = NULL;
21ab4e
         dht_conf_t         *conf         = this->private;
21ab4e
         xlator_t           *subvol       = NULL;
21ab4e
-        char               gfid[GF_UUID_BUF_SIZE] = {0};
21ab4e
+        char                gfid[GF_UUID_BUF_SIZE] = {0};
21ab4e
+        int                 count        = 0;
21ab4e
+        gf_boolean_t        unwind        = _gf_false;
21ab4e
+
21ab4e
 
21ab4e
         local = frame->local;
21ab4e
 
21ab4e
@@ -8510,7 +8515,7 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
21ab4e
                         continue;
21ab4e
                 if (check_is_linkfile (NULL, (&trav->d_stat), trav->dict,
21ab4e
                                               conf->link_xattr_name)) {
21ab4e
-                        ret++;
21ab4e
+                        count++;
21ab4e
                         continue;
21ab4e
                 }
21ab4e
 
21ab4e
@@ -8540,16 +8545,17 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
21ab4e
                 return -1;
21ab4e
         }
21ab4e
 
21ab4e
+        local->call_cnt = count;
21ab4e
+        ret = 0;
21ab4e
+
21ab4e
         list_for_each_entry (trav, &entries->list, list) {
21ab4e
                 if (strcmp (trav->d_name, ".") == 0)
21ab4e
                         continue;
21ab4e
                 if (strcmp (trav->d_name, "..") == 0)
21ab4e
                         continue;
21ab4e
 
21ab4e
-                lookup_frame = NULL;
21ab4e
-                lookup_local = NULL;
21ab4e
-
21ab4e
                 lookup_frame = copy_frame (frame);
21ab4e
+
21ab4e
                 if (!lookup_frame) {
21ab4e
                         /* out of memory, let the rmdir fail
21ab4e
                            (as non-empty, unfortunately) */
21ab4e
@@ -8578,13 +8584,6 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
21ab4e
                               "looking up %s on subvolume %s, gfid = %s",
21ab4e
                               lookup_local->loc.path, src->name, gfid);
21ab4e
 
21ab4e
-                LOCK (&frame->lock);
21ab4e
-                {
21ab4e
-                        /* Increment the call count for the readdir frame */
21ab4e
-                        local->call_cnt++;
21ab4e
-                }
21ab4e
-                UNLOCK (&frame->lock);
21ab4e
-
21ab4e
                 subvol = dht_linkfile_subvol (this, NULL, &trav->d_stat,
21ab4e
                                               trav->dict);
21ab4e
                 if (!subvol) {
21ab4e
@@ -8614,6 +8613,9 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this,
21ab4e
                                     &lookup_local->loc, xattrs);
21ab4e
                 }
21ab4e
                 ret++;
21ab4e
+
21ab4e
+                lookup_frame = NULL;
21ab4e
+                lookup_local = NULL;
21ab4e
         }
21ab4e
 
21ab4e
         if (xattrs)
21ab4e
@@ -8626,6 +8628,25 @@ err:
21ab4e
 
21ab4e
         if (lookup_frame)
21ab4e
                 DHT_STACK_DESTROY (lookup_frame);
21ab4e
+
21ab4e
+        /* Handle the case where the wound calls have unwound before the
21ab4e
+         * loop processing is done
21ab4e
+         */
21ab4e
+
21ab4e
+        LOCK (&frame->lock);
21ab4e
+        {
21ab4e
+                local->op_ret = -1;
21ab4e
+                local->op_errno = ENOTEMPTY;
21ab4e
+
21ab4e
+                local->call_cnt -= (count - ret);
21ab4e
+                if (!local->call_cnt)
21ab4e
+                        unwind = _gf_true;
21ab4e
+        }
21ab4e
+        UNLOCK (&frame->lock);
21ab4e
+
21ab4e
+        if (!unwind) {
21ab4e
+                return ret;
21ab4e
+        }
21ab4e
         return 0;
21ab4e
 }
21ab4e
 
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e