diff options
author | N Balachandran <nbalacha@redhat.com> | 2017-07-19 21:44:55 +0530 |
---|---|---|
committer | Shyamsundar Ranganathan <srangana@redhat.com> | 2017-07-20 12:45:59 +0000 |
commit | fdc431063f33cf4f5572771742e5502565f2a3ca (patch) | |
tree | 84771243e2e126c0eb40e1dd16b4c27bea6d98a1 | |
parent | 8a09d78076cf506f0750cccd63cc983496473cf3 (diff) |
cluster/dht: Fixed crash in dht_rmdir_is_subvol_empty
The local->call_cnt was being accessed and updated inside
the loop where the entries were being processed and the calls
were being wound.
This could end up in a scenario where the local->call_cnt became
0 before the processing was complete causing the crash when the
next entry was being processed.
Change-Id: I930f61f1a1d1948f90d4e58e80b7d6680cf27f2f
BUG: 1472949
Signed-off-by: N Balachandran <nbalacha@redhat.com>
Reviewed-on: https://review.gluster.org/17825
Smoke: Gluster Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com>
-rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 253fd71068c..d328b78cbe1 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -8203,6 +8203,7 @@ dht_rmdir_linkfile_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this } this_call_cnt = dht_frame_return (readdirp_frame); + if (is_last_call (this_call_cnt)) dht_rmdir_readdirp_do (readdirp_frame, this); @@ -8263,8 +8264,9 @@ dht_rmdir_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, err: this_call_cnt = dht_frame_return (readdirp_frame); - if (is_last_call (this_call_cnt)) + if (is_last_call (this_call_cnt)) { dht_rmdir_readdirp_do (readdirp_frame, this); + } DHT_STACK_DESTROY (frame); return 0; @@ -8372,7 +8374,10 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, dict_t *xattrs = NULL; dht_conf_t *conf = this->private; xlator_t *subvol = NULL; - char gfid[GF_UUID_BUF_SIZE] = {0}; + char gfid[GF_UUID_BUF_SIZE] = {0}; + int count = 0; + gf_boolean_t unwind = _gf_false; + local = frame->local; @@ -8383,7 +8388,7 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, continue; if (check_is_linkfile (NULL, (&trav->d_stat), trav->dict, conf->link_xattr_name)) { - ret++; + count++; continue; } @@ -8413,16 +8418,17 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, return -1; } + local->call_cnt = count; + ret = 0; + list_for_each_entry (trav, &entries->list, list) { if (strcmp (trav->d_name, ".") == 0) continue; if (strcmp (trav->d_name, "..") == 0) continue; - lookup_frame = NULL; - lookup_local = NULL; - lookup_frame = copy_frame (frame); + if (!lookup_frame) { /* out of memory, let the rmdir fail (as non-empty, unfortunately) */ @@ -8452,13 +8458,6 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, "looking up %s on subvolume %s, gfid = %s", lookup_local->loc.path, src->name, gfid); - LOCK (&frame->lock); - { - /* Increment the call count for the readdir frame */ - local->call_cnt++; - } - UNLOCK (&frame->lock); - subvol = dht_linkfile_subvol (this, NULL, &trav->d_stat, trav->dict); if (!subvol) { @@ -8488,6 +8487,9 @@ dht_rmdir_is_subvol_empty (call_frame_t *frame, xlator_t *this, &lookup_local->loc, xattrs); } ret++; + + lookup_frame = NULL; + lookup_local = NULL; } if (xattrs) @@ -8500,6 +8502,25 @@ err: if (lookup_frame) DHT_STACK_DESTROY (lookup_frame); + + /* Handle the case where the wound calls have unwound before the + * loop processing is done + */ + + LOCK (&frame->lock); + { + local->op_ret = -1; + local->op_errno = ENOTEMPTY; + + local->call_cnt -= (count - ret); + if (!local->call_cnt) + unwind = _gf_true; + } + UNLOCK (&frame->lock); + + if (!unwind) { + return ret; + } return 0; } |