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 | |
| 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>
| -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);  | 
