diff options
| -rwxr-xr-x | tests/bugs/bug-1117851.t | 1 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 139 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.h | 5 | 
3 files changed, 130 insertions, 15 deletions
diff --git a/tests/bugs/bug-1117851.t b/tests/bugs/bug-1117851.t index 8292058cf2f..633b15aec09 100755 --- a/tests/bugs/bug-1117851.t +++ b/tests/bugs/bug-1117851.t @@ -43,7 +43,6 @@ check_files () {  				# I hope I remember to come back and strengthen  				# this test accordingly.  				echo "file $i didnt get moved" > /dev/stderr -				#warnings=$((warnings+1))  			else  				echo "file $i is MISSING" > /dev/stderr  				errors=$((errors+1)) diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index cc7df9a3ea6..3d355b307cf 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -2560,6 +2560,72 @@ out:  /* }}} */ +int32_t +afr_unlock_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int32_t op_ret, int32_t op_errno, dict_t *xdata) + +{ +        afr_local_t *local = NULL; +        afr_private_t *priv = NULL; +        int call_count = -1; +        int child_index = (long)cookie; +        uuid_t  gfid = {0}; + +        local = frame->local; +        priv = this->private; + +        if (op_ret < 0 && op_errno != ENOTCONN) { +                loc_gfid (&local->loc, gfid); +                gf_log (this->name, GF_LOG_ERROR, "%s: Failed to unlock %s " +                        "with lk_owner: %s (%s)", uuid_utoa (gfid), +                        priv->children[child_index]->name, +                        lkowner_utoa (&frame->root->lk_owner), +                        strerror (op_errno)); +        } + +        call_count = afr_frame_return (frame); +        if (call_count == 0) { +                AFR_STACK_UNWIND (inodelk, frame, local->op_ret, +                                  local->op_errno, local->xdata_rsp); +        } + +        return 0; +} + +int32_t +afr_unlock_inodelks_and_unwind (call_frame_t *frame, xlator_t *this, +                                int call_count) +{ +        int i = 0; +        afr_private_t *priv = NULL; +        afr_local_t *local = NULL; + +        local = frame->local; +        priv = this->private; +        local->call_count = call_count; +        local->cont.inodelk.flock.l_type = F_UNLCK; + +        for (i = 0; i < priv->child_count; i++) { +                if (!local->replies[i].valid) +                        continue; + +                if (local->replies[i].op_ret == -1) +                        continue; + +                STACK_WIND_COOKIE (frame, afr_unlock_inodelk_cbk, +                                   (void*) (long) i, +                                   priv->children[i], +                                   priv->children[i]->fops->inodelk, +                                   local->cont.inodelk.volume, +                                   &local->loc, local->cont.inodelk.cmd, +                                   &local->cont.inodelk.flock, 0); + +                if (!--call_count) +                        break; +        } + +        return 0; +}  int32_t  afr_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -2567,24 +2633,63 @@ afr_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  {          afr_local_t *local = NULL; +        afr_private_t *priv = NULL;          int call_count = -1; +        int child_index = (long)cookie; +        int i = 0; +        int lock_count = 0;          local = frame->local; +        priv = this->private; -        LOCK (&frame->lock); -        { -                if (op_ret == 0) -                        local->op_ret = 0; - -                local->op_errno = op_errno; +        local->replies[child_index].valid = 1; +        local->replies[child_index].op_ret = op_ret; +        local->replies[child_index].op_errno = op_errno; +        if (op_ret == 0 && xdata) { +                local->replies[child_index].xdata = dict_ref (xdata); +                LOCK (&frame->lock); +                { +                        if (!local->xdata_rsp) +                                local->xdata_rsp = dict_ref (xdata); +                } +                UNLOCK (&frame->lock);          } -        UNLOCK (&frame->lock);          call_count = afr_frame_return (frame); -        if (call_count == 0) -                AFR_STACK_UNWIND (inodelk, frame, local->op_ret, -                                  local->op_errno, xdata); +        if (call_count == 0) { +                for (i = 0; i < priv->child_count; i++) { +                        if (!local->replies[i].valid) +                                continue; + +                        if (local->replies[i].op_ret == 0) +                                lock_count++; + +                        if (local->op_ret == -1 && local->op_errno == EAGAIN) +                                continue; + +                        if ((local->replies[i].op_ret == -1) && +                            (local->replies[i].op_errno == EAGAIN)) { +                                local->op_ret = -1; +                                local->op_errno = EAGAIN; +                                continue; +                        } + +                        if (local->replies[i].op_ret == 0) +                                local->op_ret = 0; + +                        local->op_errno = local->replies[i].op_errno; +                } + +                if (lock_count && local->cont.inodelk.flock.l_type != F_UNLCK && +                    (local->op_ret == -1 && local->op_errno == EAGAIN)) { +                        afr_unlock_inodelks_and_unwind (frame, this, +                                                        lock_count); +                } else { +                        AFR_STACK_UNWIND (inodelk, frame, local->op_ret, +                                          local->op_errno, local->xdata_rsp); +                } +        }          return 0;  } @@ -2607,6 +2712,11 @@ afr_inodelk (call_frame_t *frame, xlator_t *this,          if (!local)                  goto out; +        loc_copy (&local->loc, loc); +        local->cont.inodelk.volume = volume; +        local->cont.inodelk.cmd = cmd; +        local->cont.inodelk.flock = *flock; +          call_count = local->call_count;  	if (!call_count) {  		op_errno = ENOMEM; @@ -2615,10 +2725,11 @@ afr_inodelk (call_frame_t *frame, xlator_t *this,          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) { -                        STACK_WIND (frame, afr_inodelk_cbk, -                                    priv->children[i], -                                    priv->children[i]->fops->inodelk, -                                    volume, loc, cmd, flock, xdata); +                        STACK_WIND_COOKIE (frame, afr_inodelk_cbk, +                                           (void*) (long) i, +                                           priv->children[i], +                                           priv->children[i]->fops->inodelk, +                                           volume, loc, cmd, flock, xdata);                          if (!--call_count)                                  break; diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index 35d4d545bc9..ddcb2c0e177 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -604,6 +604,11 @@ typedef struct _afr_local {                          struct iatt postbuf;                  } zerofill; +                struct { +                        const char *volume; +                        int32_t cmd; +                        struct gf_flock flock; +                } inodelk;          } cont;  | 
