diff options
Diffstat (limited to 'xlators/cluster/afr/src/afr-common.c')
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 193 | 
1 files changed, 161 insertions, 32 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 9b2c0d7caea..dec667fd460 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -43,6 +43,20 @@  #include "afr-self-heald.h"  #include "afr-messages.h" +gf_boolean_t +afr_is_consistent_io_possible (afr_local_t *local, afr_private_t *priv, +                               int32_t *op_errno) +{ +        if (priv->consistent_io && local->call_count != priv->child_count) { +                gf_msg (THIS->name, GF_LOG_INFO, 0, +                        AFR_MSG_SUBVOLS_DOWN, "All subvolumes are not up"); +                if (op_errno) +                        *op_errno = ENOTCONN; +                return _gf_false; +        } +        return _gf_true; +} +  call_frame_t *  afr_copy_frame (call_frame_t *base)  { @@ -1555,6 +1569,100 @@ afr_remove_eager_lock_stub (afr_local_t *local)          UNLOCK (&local->fd->lock);  } +static gf_boolean_t +afr_entrylk_is_unlock (entrylk_cmd cmd) +{ +        if (ENTRYLK_UNLOCK == cmd) +                return _gf_true; +        return _gf_false; +} + +static gf_boolean_t +afr_inodelk_is_unlock (int32_t cmd, struct gf_flock *flock) +{ +        switch (cmd) { +        case F_SETLKW: +        case F_SETLK: +                if (F_UNLCK == flock->l_type) +                        return _gf_true; +                break; +        default: +                return _gf_false; +        } +        return _gf_false; +} + +static gf_boolean_t +afr_lk_is_unlock (int32_t cmd, struct gf_flock *flock) +{ +        switch (cmd) { +        case F_RESLK_UNLCK: +                return _gf_true; +                break; + +#if F_SETLKW != F_SETLKW64 +        case F_SETLKW64: +#endif +        case F_SETLKW: + +#if F_SETLK != F_SETLK64 +        case F_SETLK64: +#endif +        case F_SETLK: +                if (F_UNLCK == flock->l_type) +                        return _gf_true; +                break; +        default: +                return _gf_false; +        } +        return _gf_false; +} + +void +afr_handle_inconsistent_fop (call_frame_t *frame, int32_t *op_ret, +                             int32_t *op_errno) +{ +        afr_private_t *priv = NULL; +        afr_local_t   *local = NULL; + +        if (!frame || !frame->this || !frame->local || !frame->this->private) +                return; + +        if (*op_ret < 0) +                return; + +        /* Failing inodelk/entrylk/lk here is not a good idea because we +         * need to cleanup the locks on the other bricks if we choose to fail +         * the fop here. The brick may go down just after unwind happens as well +         * so anyways the fop will fail when the next fop is sent so leaving +         * it like this for now.*/ +        local = frame->local; +        switch (local->op) { +        case GF_FOP_LOOKUP: +        case GF_FOP_INODELK: +        case GF_FOP_FINODELK: +        case GF_FOP_ENTRYLK: +        case GF_FOP_FENTRYLK: +        case GF_FOP_LK: +                return; +        default: +                break; +        } + +        priv = frame->this->private; +        if (!priv->consistent_io) +                return; + +        if (local->event_generation && +            (local->event_generation != priv->event_generation)) +                goto inconsistent; + +        return; +inconsistent: +        *op_ret = -1; +        *op_errno = ENOTCONN; +} +  void  afr_local_cleanup (afr_local_t *local, xlator_t *this)  { @@ -2997,10 +3105,9 @@ afr_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata)  	if (!local)  		goto out; -	if (!local->call_count) { -		op_errno = ENOTCONN; +        local->op = GF_FOP_FLUSH; +	if (!afr_is_consistent_io_possible (local, this->private, &op_errno))  		goto out; -	}  	local->fd = fd_ref(fd); @@ -3126,11 +3233,9 @@ afr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync,  	if (!local)  		goto out; -        call_count = local->call_count; -	if (!call_count) { -		op_errno = ENOTCONN; +        local->op = GF_FOP_FSYNC; +	if (!afr_is_consistent_io_possible (local, priv, &op_errno))  		goto out; -	}          local->fd = fd_ref (fd); @@ -3140,6 +3245,7 @@ afr_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync,  	local->inode = inode_ref (fd->inode); +        call_count = local->call_count;          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) {                          STACK_WIND_COOKIE (frame, afr_fsync_cbk, @@ -3210,12 +3316,11 @@ afr_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync,  	if (!local)  		goto out; -        call_count = local->call_count; -	if (!call_count) { -		op_errno = ENOTCONN; +        local->op = GF_FOP_FSYNCDIR; +	if (!afr_is_consistent_io_possible (local, priv, &op_errno))  		goto out; -	} +        call_count = local->call_count;          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) {                          STACK_WIND (frame, afr_fsyncdir_cbk, @@ -3506,6 +3611,11 @@ afr_inodelk (call_frame_t *frame, xlator_t *this,          if (!local)                  goto out; +        local->op = GF_FOP_INODELK; +        if (!afr_inodelk_is_unlock (cmd, flock) && +            !afr_is_consistent_io_possible (local, this->private, &op_errno)) +                goto out; +          loc_copy (&local->loc, loc);          local->cont.inodelk.volume = gf_strdup (volume);          if (!local->cont.inodelk.volume) { @@ -3589,12 +3699,23 @@ afr_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd,  	if (!local)  		goto out; -        call_count = local->call_count; -	if (!call_count) { -		op_errno = ENOTCONN; -		goto out; -	} +        local->op = GF_FOP_FINODELK; +        if (!afr_inodelk_is_unlock (cmd, flock) && +            !afr_is_consistent_io_possible (local, this->private, &op_errno)) +                goto out; +        local->cont.inodelk.volume = gf_strdup (volume); +        if (!local->cont.inodelk.volume) { +                op_errno = ENOMEM; +                goto out; +        } + +        local->fd = fd_ref (fd); +        local->cont.inodelk.cmd = cmd; +        local->cont.inodelk.flock = *flock; +        if (xdata) +                local->xdata_req = dict_ref (xdata); +        call_count = local->call_count;          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) {                          STACK_WIND (frame, afr_finodelk_cbk, @@ -3610,7 +3731,6 @@ afr_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd,  	return 0;  out:  	AFR_STACK_UNWIND (finodelk, frame, -1, op_errno, NULL); -          return 0;  } @@ -3642,7 +3762,6 @@ afr_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          return 0;  } -  int  afr_entrylk (call_frame_t *frame, xlator_t *this, const char *volume,  	     loc_t *loc, const char *basename, entrylk_cmd cmd, @@ -3660,12 +3779,13 @@ afr_entrylk (call_frame_t *frame, xlator_t *this, const char *volume,  	if (!local)  		goto out; -        call_count = local->call_count; -	if (!call_count) { -		op_errno = ENOTCONN; -		goto out; -	} +        local->op = GF_FOP_ENTRYLK; +        if (!afr_entrylk_is_unlock (cmd) && +            !afr_is_consistent_io_possible (local, priv, &op_errno)) +                goto out; +        local->cont.entrylk.cmd = cmd; +        call_count = local->call_count;          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) {                          STACK_WIND (frame, afr_entrylk_cbk, @@ -3733,12 +3853,13 @@ afr_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd,  	if (!local)  		goto out; -        call_count = local->call_count; -	if (!call_count) { -		op_errno = ENOTCONN; -		goto out; -	} +        local->op = GF_FOP_FENTRYLK; +        if (!afr_entrylk_is_unlock (cmd) && +            !afr_is_consistent_io_possible (local, priv, &op_errno)) +                goto out; +        local->cont.entrylk.cmd = cmd; +        call_count = local->call_count;          for (i = 0; i < priv->child_count; i++) {                  if (local->child_up[i]) {                          STACK_WIND (frame, afr_fentrylk_cbk, @@ -3823,6 +3944,10 @@ afr_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)  	if (!local)  		goto out; +        local->op = GF_FOP_STATFS; +	if (!afr_is_consistent_io_possible (local, priv, &op_errno)) +		goto out; +          if (priv->arbiter_count == 1 && local->child_up[ARBITER_BRICK_INDEX])                  local->call_count--;          call_count = local->call_count; @@ -3963,7 +4088,6 @@ afr_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          return 0;  } -  int  afr_lk (call_frame_t *frame, xlator_t *this,          fd_t *fd, int32_t cmd, struct gf_flock *flock, dict_t *xdata) @@ -3979,6 +4103,11 @@ afr_lk (call_frame_t *frame, xlator_t *this,          if (!local)                  goto out; +        local->op = GF_FOP_LK; +        if (!afr_lk_is_unlock (cmd, flock) && +            !afr_is_consistent_io_possible (local, priv, &op_errno)) +                goto out; +          local->cont.lk.locked_nodes = GF_CALLOC (priv->child_count,                                                   sizeof (*local->cont.lk.locked_nodes),                                                   gf_afr_mt_char); @@ -4311,7 +4440,7 @@ afr_notify (xlator_t *this, int32_t event,                                          down_children++;                          if (down_children == priv->child_count) {                                  gf_msg (this->name, GF_LOG_ERROR, 0, -                                        AFR_MSG_ALL_SUBVOLS_DOWN, +                                        AFR_MSG_SUBVOLS_DOWN,                                         "All subvolumes are down. Going offline "                                      "until atleast one of them comes back up.");                          } else { @@ -4399,7 +4528,6 @@ out:          return ret;  } -  int  afr_local_init (afr_local_t *local, afr_private_t *priv, int32_t *op_errno)  { @@ -4422,11 +4550,12 @@ afr_local_init (afr_local_t *local, afr_private_t *priv, int32_t *op_errno)          local->call_count = AFR_COUNT (local->child_up, priv->child_count);          if (local->call_count == 0) {                  gf_msg (THIS->name, GF_LOG_INFO, 0, -                        AFR_MSG_ALL_SUBVOLS_DOWN, "no subvolumes up"); +                        AFR_MSG_SUBVOLS_DOWN, "no subvolumes up");                  if (op_errno)                          *op_errno = ENOTCONN;                  goto out;          } +  	local->event_generation = priv->event_generation;  	local->read_attempted = GF_CALLOC (priv->child_count, sizeof (char),  | 
