diff options
author | shishir <shishirng@gluster.com> | 2011-07-27 15:03:40 +0530 |
---|---|---|
committer | Anand Avati <avati@gluster.com> | 2011-07-28 03:03:14 -0700 |
commit | ff5fddcf54805464c1033ee4665835784e260831 (patch) | |
tree | 1362796f384895229dde0fb865e286a2d08ffad5 /xlators/cluster/stripe/src/stripe.c | |
parent | 2a6de14e22445fc3017c9aa25b9c56bc4259d373 (diff) |
Stripe_readdirp: Fix race in wind/unwind which led to crash
Scenario - The race window exists when before we wind to a stat call
in readdirp_cbk, whereas stats have returned to cbk. We would free up
local, which leads to a crash.
Fix - We assume all entries to be regular files, and set the wind_count
as a multiple of entries * subvol (stat calls). When we encounter a non
regular file, we decrement the windcount accordingly (subvol times). If
the last entry happens to be a non-regular file, and all stat calls have
wound back, we unwind from here itself.
Change-Id: Ia8e225ef557cbe1fedb9b72de9bd9fa61f371a24
BUG: 3257
Reviewed-on: http://review.gluster.com/115
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
Diffstat (limited to 'xlators/cluster/stripe/src/stripe.c')
-rw-r--r-- | xlators/cluster/stripe/src/stripe.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c index e7033183f6c..bf54bdea2c2 100644 --- a/xlators/cluster/stripe/src/stripe.c +++ b/xlators/cluster/stripe/src/stripe.c @@ -3774,8 +3774,8 @@ stripe_readdirp_entry_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *thi LOCK (&frame->lock); { - local->count++; - if (local->count == local->wind_count) + local->wind_count--; + if (!local->wind_count) done = 1; if (op_ret == -1) { local->op_errno = op_errno; @@ -3815,6 +3815,8 @@ stripe_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, inode_t *inode = NULL; char *path; int32_t count = 0; + stripe_private_t *priv = NULL; + int32_t subvols = 0; if (!this || !frame || !frame->local || !cookie) { gf_log ("stripe", GF_LOG_DEBUG, "possible NULL deref"); @@ -3823,6 +3825,9 @@ stripe_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, prev = cookie; local = frame->local; trav = this->children; + priv = this->private; + + subvols = priv->child_count; LOCK (&frame->lock); { @@ -3837,6 +3842,7 @@ stripe_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; list_splice_init (&orig_entries->list, &local->entries.list); + local->wind_count = op_ret * subvols; } } unlock: @@ -3845,14 +3851,22 @@ unlock: if (op_ret == -1) goto out; + count = op_ret; ret = 0; list_for_each_entry_safe (local_entry, tmp_entry, (&local->entries.list), list) { if (!local_entry) break; - if (!IA_ISREG (local_entry->d_stat.ia_type)) + if (!IA_ISREG (local_entry->d_stat.ia_type)) { + LOCK (&frame->lock); + { + local->wind_count -= subvols; + count = local->wind_count; + } + UNLOCK (&frame->lock); continue; + } inode = inode_new (local->fd->inode->table); if (!inode) @@ -3877,15 +3891,9 @@ unlock: loc.name++; trav = this->children; while (trav) { - LOCK (&frame->lock); - { - local->wind_count++; - } - UNLOCK (&frame->lock); STACK_WIND_COOKIE (frame, stripe_readdirp_entry_stat_cbk, local_entry, trav->xlator, trav->xlator->fops->stat, &loc); - count++; trav = trav->next; } inode_unref (loc.inode); |