summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshishir <shishirng@gluster.com>2011-07-27 15:03:40 +0530
committerAnand Avati <avati@gluster.com>2011-07-28 03:03:14 -0700
commitff5fddcf54805464c1033ee4665835784e260831 (patch)
tree1362796f384895229dde0fb865e286a2d08ffad5
parent2a6de14e22445fc3017c9aa25b9c56bc4259d373 (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.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c
index e7033183f..bf54bdea2 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);