diff options
| author | karthik-us <ksubrahm@redhat.com> | 2019-03-13 13:00:47 +0530 | 
|---|---|---|
| committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2020-02-13 09:38:14 +0000 | 
| commit | a3c8a6180a53fb96cc090c5552c64088f68ec4dc (patch) | |
| tree | def7823bebe6d608d886c8a1d165c9d9cae37e09 | |
| parent | 8db8202f716fd24c8c52f8ee5f66e169310dc9b1 (diff) | |
cluster/afr: Check for lock on source & sink before doing data heal
Problem:
In function afr_selfheal_data_block(), we only check for the lock count
to be equal to or greater than the number of sinks. There can be a case
where we have 2 source bricks and one sink and the locking is successful
on only the source brick(s). In this case we continue with the healing
on sink without having a lock, which is not correct.
Fix:
Check for lock on atleast source & one sink before starting the data heal.
Change-Id: Iebcb57dcaa4b31831fedfee63d6ca16e9d6c8df8
fixes: bz#1688115
Signed-off-by: karthik-us <ksubrahm@redhat.com>
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 22 | 
1 files changed, 19 insertions, 3 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index cdff4a57674..37bcc2b3f9e 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -225,24 +225,40 @@ __afr_selfheal_data_read_write(call_frame_t *frame, xlator_t *this, fd_t *fd,      return ret;  } +static gf_boolean_t +afr_source_sinks_locked(xlator_t *this, unsigned char *locked_on, int source, +                        unsigned char *healed_sinks) +{ +    afr_private_t *priv = this->private; +    int i = 0; + +    if (!locked_on[source]) +        return _gf_false; + +    for (i = 0; i < priv->child_count; i++) { +        if (healed_sinks[i] && locked_on[i]) +            return _gf_true; +    } + +    return _gf_false; +} +  static int  afr_selfheal_data_block(call_frame_t *frame, xlator_t *this, fd_t *fd,                          int source, unsigned char *healed_sinks, off_t offset,                          size_t size, int type, struct afr_reply *replies)  {      int ret = -1; -    int sink_count = 0;      afr_private_t *priv = NULL;      unsigned char *data_lock = NULL;      priv = this->private; -    sink_count = AFR_COUNT(healed_sinks, priv->child_count);      data_lock = alloca0(priv->child_count);      ret = afr_selfheal_inodelk(frame, this, fd->inode, this->name, offset, size,                                 data_lock);      { -        if (ret < sink_count) { +        if (!afr_source_sinks_locked(this, data_lock, source, healed_sinks)) {              ret = -ENOTCONN;              goto unlock;          }  | 
