diff options
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-common.c | 14 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heald.c | 55 | 
2 files changed, 66 insertions, 3 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index c6b14e1def7..7fb6e2b9dc4 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -1141,6 +1141,11 @@ afr_selfheal_do (call_frame_t *frame, xlator_t *this, uuid_t gfid)  	if (ret)  		goto out; +        if (!(data_selfheal || metadata_selfheal || entry_selfheal)) { +                ret = 2; +                goto out; +        } +  	if (data_selfheal)                  data_ret = afr_selfheal_data (frame, this, inode); @@ -1169,9 +1174,12 @@ out:          return ret;  }  /* - * This is the entry point for healing a given GFID - * The function returns 0 if self-heal was successful, appropriate errno - * in case of a failure and 1 in case self-heal was never needed on the gfid. + * This is the entry point for healing a given GFID. The return values for this + * function are as follows: + * '0' if the self-heal is successful + * '1' if the afr-xattrs are non-zero (due to on-going IO) and no heal is needed + * '2' if the afr-xattrs are all-zero and no heal is needed + * $errno if the heal on the gfid failed.   */  int diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index 992ed28b994..7c235aca429 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -313,6 +313,53 @@ afr_shd_index_purge (xlator_t *subvol, inode_t *inode, char *name)  	return ret;  } +void +afr_shd_zero_xattrop (xlator_t *this, uuid_t gfid) +{ + +        call_frame_t *frame = NULL; +        inode_t *inode = NULL; +        afr_private_t *priv = NULL; +        dict_t  *xattr = NULL; +        int ret = 0; +        int i = 0; +        int raw[AFR_NUM_CHANGE_LOGS] = {0}; + +        priv = this->private; +        frame = afr_frame_create (this); +        if (!frame) +                goto out; +        inode = afr_inode_find (this, gfid); +        if (!inode) +                goto out; +        xattr = dict_new(); +        if (!xattr) +                goto out; +        ret = dict_set_static_bin (xattr, AFR_DIRTY, raw, +                                   sizeof(int) * AFR_NUM_CHANGE_LOGS); +        if (ret) +                goto out; +        for (i = 0; i < priv->child_count; i++) { +                ret = dict_set_static_bin (xattr, priv->pending_key[i], raw, +                                           sizeof(int) * AFR_NUM_CHANGE_LOGS); +                if (ret) +                        goto out; +        } + +        /*Send xattrop to all bricks. Doing a lookup to see if bricks are up or +        * has valid repies for this gfid seems a bit of an overkill.*/ +        for (i = 0; i < priv->child_count; i++) +                afr_selfheal_post_op (frame, this, inode, i, xattr); + +out: +        if (frame) +                AFR_STACK_DESTROY (frame); +        if (inode) +                inode_unref (inode); +        if (xattr) +                dict_unref (xattr); +        return; +}  int  afr_shd_selfheal_name (struct subvol_healer *healer, int child, uuid_t parent, @@ -480,6 +527,14 @@ afr_shd_index_sweep (struct subvol_healer *healer)  				afr_shd_index_purge (subvol, fd->inode,  						     entry->d_name);  			} +                        if (ret == 2) +                        /* If bricks crashed in pre-op after creating +                         * indices/xattrop link but before setting afr +                         * changelogs, we end up with stale xattrop links but +                         * zero changelogs. Remove such entries by sending a +                         * post-op with zero changelogs. +                         */ +                                afr_shd_zero_xattrop (healer->this, gfid);                          ret = 0;  		}  | 
