diff options
| author | Krutika Dhananjay <kdhananj@redhat.com> | 2014-08-21 17:27:17 +0530 | 
|---|---|---|
| committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2014-09-02 07:57:22 -0700 | 
| commit | 6c4325ca57bca72d10e5172f8423262cdb3a379c (patch) | |
| tree | b1337a1865d4b5500fda362fb4bf8324c0f9d3c7 | |
| parent | 2c0a694b8d910c530899077c1d242ad1ea250965 (diff) | |
cluster/afr: Propagate EIO on inode's type mismatch
Original author of the test script:
            Pranith Kumar K <pkarampu@redhat.com>
Change-Id: If515ecefd3c17f85f175b6a8cb4b78ce8c916de2
BUG: 1132469
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-on: http://review.gluster.org/8574
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
| -rw-r--r-- | tests/basic/afr/gfid-self-heal.t | 129 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 20 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-common.c | 9 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 3 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-entry.c | 31 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-metadata.c | 4 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-name.c | 366 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal.h | 20 | 
8 files changed, 462 insertions, 120 deletions
diff --git a/tests/basic/afr/gfid-self-heal.t b/tests/basic/afr/gfid-self-heal.t new file mode 100644 index 00000000000..f9d88c5d21a --- /dev/null +++ b/tests/basic/afr/gfid-self-heal.t @@ -0,0 +1,129 @@ +#!/bin/bash + +#Tests for files without gfids + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 self-heal-daemon off +TEST $CLI volume set $V0 nfs.disable on +TEST touch $B0/${V0}{0,1}/{1,2,3,4} +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 --attribute-timeout=0 --entry-timeout=0 +#Test that readdir returns entries even when no gfids are present +EXPECT 4 echo $(ls -l $M0 | grep -vi total | wc -l) +sleep 2; +#stat the files and check that the files have same gfids on the bricks now +TEST stat $M0/1 +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/1) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/1) +TEST "[[ ! -z $gfid_0 ]]" +EXPECT $gfid_0 echo $gfid_1 + +TEST stat $M0/2 +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/2) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/2) +TEST "[[ ! -z $gfid_0 ]]" +EXPECT $gfid_0 echo $gfid_1 + +TEST stat $M0/3 +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/3) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/3) +TEST "[[ ! -z $gfid_0 ]]" +EXPECT $gfid_0 echo $gfid_1 + +TEST stat $M0/4 +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/4) +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/4) +TEST "[[ ! -z $gfid_0 ]]" +EXPECT $gfid_0 echo $gfid_1 + +#Check gfid self-heal happens from one brick to other when a file has missing +#gfid +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST touch $M0/a +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/a) +TEST touch $B0/${V0}0/a +$CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST stat $M0/a +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/a) +EXPECT $gfid_1 echo $gfid_0 + +#Check gfid self-heal doesn't happen from one brick to other when type mismatch +#is present for a name, without any xattrs +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST touch $M0/b +TEST mkdir $B0/${V0}0/b +TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1 +$CLI volume start $V0 force +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +TEST ! stat $M0/b +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/b) +TEST "[[ -z \"$gfid_0\" ]]" + +#Check gfid assigning doesn't happen when there is type mismatch +TEST touch $B0/${V0}1/c +TEST mkdir $B0/${V0}0/c +TEST ! stat $M0/c +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/c) +gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/c) +TEST "[[ -z \"$gfid_1\" ]]" +TEST "[[ -z \"$gfid_0\" ]]" + +#Check gfid assigning doesn't happen only when even one brick is down to prevent +# gfid split-brain +TEST kill_brick $V0 $H0 $B0/${V0}0 +TEST touch $B0/${V0}1/d +TEST ! stat $M0/d +gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/d) +TEST "[[ -z \"$gfid_1\" ]]" +TEST $CLI volume start $V0 force; +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +#Check gfid self-heal doesn't happen from one brick to other when type mismatch +#is present for a name without any pending xattrs +#TEST kill_brick $V0 $H0 $B0/${V0}0 +#TEST touch $M0/e +#TEST $CLI volume start $V0 force; +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +#TEST kill_brick $V0 $H0 $B0/${V0}1 +#TEST mkdir $M0/e +#TEST $CLI volume stop $V0 force; +#TEST setfattr -x trusted.gfid $B0/${V0}1/e +#TEST setfattr -x trusted.gfid $B0/${V0}0/e +#TEST $CLI volume set $V0 cluster.entry-self-heal off +#$CLI volume start $V0 force +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +#TEST ! stat $M0/e +#gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/e) +#gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/e) +#TEST "[[ -z \"$gfid_1\" ]]" +#TEST "[[ -z \"$gfid_0\" ]]" + +#Check if lookup fails with gfid-mismatch of a file +#is present for a name without any pending xattrs +#TEST kill_brick $V0 $H0 $B0/${V0}0 +#TEST touch $M0/f +#$CLI volume start $V0 force +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +#TEST kill_brick $V0 $H0 $B0/${V0}1 +#TEST touch $M0/f +#simulate no pending changelog +#$CLI volume stop $V0 force +#TEST setfattr -x trusted.afr.$V0-client-0 $B0/${V0}1 +#TEST setfattr -x trusted.afr.$V0-client-1 $B0/${V0}0 +#$CLI volume start $V0 force +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +#EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 +#TEST ! stat $M0/f + +cleanup diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 8ab67af405f..2a6b0c957fb 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -1219,9 +1219,8 @@ afr_lookup_done (call_frame_t *frame, xlator_t *this)  			continue;  		} -		if (!uuid_compare (replies[i].poststat.ia_gfid, -				   read_gfid)) -			continue; +		if (!uuid_compare (replies[i].poststat.ia_gfid, read_gfid)) +                        continue;  		can_interpret = _gf_false; @@ -1442,6 +1441,7 @@ afr_attempt_local_discovery (xlator_t *this, int32_t child_index)  int  afr_lookup_selfheal_wrap (void *opaque)  { +        int ret = 0;  	call_frame_t *frame = opaque;  	afr_local_t *local = NULL;  	xlator_t *this = NULL; @@ -1450,19 +1450,25 @@ afr_lookup_selfheal_wrap (void *opaque)  	local = frame->local;  	this = frame->this; -	afr_selfheal_name (frame->this, local->loc.pargfid, local->loc.name, -                           &local->cont.lookup.gfid_req); +	ret = afr_selfheal_name (frame->this, local->loc.pargfid, +                                 local->loc.name, &local->cont.lookup.gfid_req); +        if (ret == -EIO) +                goto unwind;          afr_local_replies_wipe (local, this->private);  	inode = afr_selfheal_unlocked_lookup_on (frame, local->loc.parent,  						 local->loc.name, local->replies, -						 local->child_up); +						 local->child_up, NULL);  	if (inode)  		inode_unref (inode); +  	afr_lookup_done (frame, this); +        return 0; -	return 0; +unwind: +	AFR_STACK_UNWIND (lookup, frame, -1, EIO, NULL, NULL, NULL, NULL); +        return 0;  } diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index 1c3d4a5dc86..9a88a7d9e5c 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -312,8 +312,7 @@ afr_selfheal_extract_xattr (xlator_t *this, struct afr_reply *replies,   */  int -afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this, -			     struct afr_reply *replies, +afr_selfheal_find_direction (xlator_t *this, struct afr_reply *replies,  			     afr_transaction_type type, unsigned char *locked_on,  			     unsigned char *sources, unsigned char *sinks)  { @@ -415,7 +414,7 @@ afr_selfheal_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  inode_t *  afr_selfheal_unlocked_lookup_on (call_frame_t *frame, inode_t *parent,  				 const char *name, struct afr_reply *replies, -				 unsigned char *lookup_on) +				 unsigned char *lookup_on, dict_t *xattr)  {  	loc_t loc = {0, };  	dict_t *xattr_req = NULL; @@ -430,6 +429,9 @@ afr_selfheal_unlocked_lookup_on (call_frame_t *frame, inode_t *parent,  	if (!xattr_req)  		return NULL; +        if (xattr) +                dict_copy (xattr, xattr_req); +  	if (afr_xattr_req_prepare (frame->this, xattr_req) != 0) {  		dict_destroy (xattr_req);  		return NULL; @@ -457,7 +459,6 @@ afr_selfheal_unlocked_lookup_on (call_frame_t *frame, inode_t *parent,  	return inode;  } -  int  afr_selfheal_unlocked_discover_on (call_frame_t *frame, inode_t *inode,  				   uuid_t gfid, struct afr_reply *replies, diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index a8a2607dbe9..455648b7564 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -455,8 +455,7 @@ __afr_selfheal_data_prepare (call_frame_t *frame, xlator_t *this, fd_t *fd,  	if (ret)  		return ret; -	ret = afr_selfheal_find_direction (frame, this, replies, -					   AFR_DATA_TRANSACTION, +	ret = afr_selfheal_find_direction (this, replies, AFR_DATA_TRANSACTION,  					   locked_on, sources, sinks);  	if (ret)  		return ret; diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index 97397c1b098..cb682a7dccc 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -21,9 +21,8 @@  static int -afr_selfheal_entry_delete (call_frame_t *frame, xlator_t *this, inode_t *dir, -			   const char *name, inode_t *inode, int child, -			   struct afr_reply *replies) +afr_selfheal_entry_delete (xlator_t *this, inode_t *dir, const char *name, +                           inode_t *inode, int child, struct afr_reply *replies)  {  	afr_private_t *priv = NULL;  	xlator_t *subvol = NULL; @@ -68,9 +67,9 @@ afr_selfheal_entry_delete (call_frame_t *frame, xlator_t *this, inode_t *dir,  int -afr_selfheal_recreate_entry (call_frame_t *frame, xlator_t *this, int dst, -			     int source, inode_t *dir, const char *name, -			     inode_t *inode, struct afr_reply *replies) +afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir, +                             const char *name, inode_t *inode, +                             struct afr_reply *replies)  {  	int ret = 0;  	loc_t loc = {0,}; @@ -93,8 +92,7 @@ afr_selfheal_recreate_entry (call_frame_t *frame, xlator_t *this, int dst,  	loc.name = name;  	loc.inode = inode_ref (inode); -	ret = afr_selfheal_entry_delete (frame, this, dir, name, inode, dst, -					 replies); +	ret = afr_selfheal_entry_delete (this, dir, name, inode, dst, replies);  	if (ret)  		goto out; @@ -214,14 +212,14 @@ __afr_selfheal_heal_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,  			continue;  		if (replies[source].op_ret == -1 &&  		    replies[source].op_errno == ENOENT) { -			ret = afr_selfheal_entry_delete (frame, this, fd->inode, -							 name, inode, i, replies); +			ret = afr_selfheal_entry_delete (this, fd->inode, name, +                                                         inode, i, replies);  		} else {  			if (!uuid_compare (replies[i].poststat.ia_gfid,  					   replies[source].poststat.ia_gfid))  				continue; -			ret = afr_selfheal_recreate_entry (frame, this, i, source, +			ret = afr_selfheal_recreate_entry (this, i, source,  							   fd->inode, name, inode,  							   replies);  			if (ret > 0) { @@ -272,9 +270,8 @@ __afr_selfheal_merge_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,  		if (replies[i].op_errno != ENOENT)  			continue; -		ret = afr_selfheal_recreate_entry (frame, this, i, source, -						   fd->inode, name, inode, -						   replies); +		ret = afr_selfheal_recreate_entry (this, i, source, fd->inode, +                                                   name, inode, replies);  	}  	return ret; @@ -327,7 +324,8 @@ afr_selfheal_entry_dirent (call_frame_t *frame, xlator_t *this, fd_t *fd,  		}  		inode = afr_selfheal_unlocked_lookup_on (frame, fd->inode, name, -							 replies, locked_on); +							 replies, locked_on, +                                                         NULL);  		if (!inode) {  			ret = -ENOMEM;  			goto unlock; @@ -476,8 +474,7 @@ __afr_selfheal_entry_prepare (call_frame_t *frame, xlator_t *this, fd_t *fd,  	if (ret)  		return ret; -	ret = afr_selfheal_find_direction (frame, this, replies, -					   AFR_ENTRY_TRANSACTION, +	ret = afr_selfheal_find_direction (this, replies, AFR_ENTRY_TRANSACTION,  					   locked_on, sources, sinks);  	if (ret)  		return ret; diff --git a/xlators/cluster/afr/src/afr-self-heal-metadata.c b/xlators/cluster/afr/src/afr-self-heal-metadata.c index efbfd63aa21..dc7825d3d16 100644 --- a/xlators/cluster/afr/src/afr-self-heal-metadata.c +++ b/xlators/cluster/afr/src/afr-self-heal-metadata.c @@ -160,8 +160,8 @@ __afr_selfheal_metadata_prepare (call_frame_t *frame, xlator_t *this, inode_t *i  	if (ret)  		return ret; -	ret = afr_selfheal_find_direction (frame, this, replies, -					   AFR_METADATA_TRANSACTION, +	ret = afr_selfheal_find_direction (this, replies, +                                           AFR_METADATA_TRANSACTION,  					   locked_on, sources, sinks);  	if (ret)  		return ret; diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c index f1626cc034e..9e7bb3bffa4 100644 --- a/xlators/cluster/afr/src/afr-self-heal-name.c +++ b/xlators/cluster/afr/src/afr-self-heal-name.c @@ -19,29 +19,43 @@  int -__afr_selfheal_assign_gfid (call_frame_t *frame, xlator_t *this, inode_t *parent, -			    uuid_t pargfid, const char *bname, inode_t *inode, -			    struct afr_reply *replies, void *gfid) +__afr_selfheal_assign_gfid (xlator_t *this, inode_t *parent, uuid_t pargfid, +                            const char *bname, inode_t *inode, +                            struct afr_reply *replies, void *gfid, +                            unsigned char *locked_on, +                            gf_boolean_t is_gfid_absent)  { -	int i = 0; -	afr_private_t *priv = NULL; -	dict_t *xdata = NULL; -	int ret = 0; -	loc_t loc = {0, }; +	int             ret          = 0; +        int             up_count     = 0; +        int             locked_count = 0; +	afr_private_t  *priv         = NULL; +	dict_t         *xdata        = NULL; +	loc_t           loc          = {0, }; +        call_frame_t   *new_frame    = NULL; +        afr_local_t    *new_local    = NULL;  	priv = this->private; +        new_frame = afr_frame_create (this); +        if (!new_frame) { +                ret = -ENOMEM; +                goto out; +        } + +        new_local = new_frame->local; +  	uuid_copy (parent->gfid, pargfid);  	xdata = dict_new ();  	if (!xdata) { -		return -ENOMEM; +                ret = -ENOMEM; +		goto out;  	}  	ret = dict_set_static_bin (xdata, "gfid-req", gfid, 16);  	if (ret) { -		dict_destroy (xdata); -		return -ENOMEM; +		ret = -ENOMEM; +		goto out;  	}  	loc.parent = inode_ref (parent); @@ -49,24 +63,53 @@ __afr_selfheal_assign_gfid (call_frame_t *frame, xlator_t *this, inode_t *parent  	uuid_copy (loc.pargfid, pargfid);  	loc.name = bname; -	for (i = 0; i < priv->child_count; i++) { -		if (replies[i].op_ret == 0 || replies[i].op_errno != ENODATA) -			continue; +        if (is_gfid_absent) { +                /* Ensure all children of AFR are up before performing gfid heal, to +                 * guard against the possibility of gfid split brain. */ + +                up_count = AFR_COUNT (priv->child_up, priv->child_count); +                if (up_count != priv->child_count) { +                        ret = -EIO; +                        goto out; +                } + +                locked_count = AFR_COUNT (locked_on, priv->child_count); +                if (locked_count != priv->child_count) { +                        ret = -EIO; +                        goto out; +                } +        } -		ret = syncop_lookup (priv->children[i], &loc, xdata, 0, 0, 0); -	} +        /* Clear out old replies here and wind lookup on all locked +         * subvolumes to achieve two things: +         *   a. gfid heal on those subvolumes that do not have gfid associated +         *      with the inode, and +         *   b. refresh replies, which can be consumed by +         *      __afr_selfheal_name_impunge(). +         */ + +        afr_replies_wipe (replies, priv->child_count); + +        AFR_ONLIST (locked_on, new_frame, afr_selfheal_discover_cbk, lookup, +                    &loc, xdata); +        afr_replies_copy (replies, new_local->replies, priv->child_count); + +out:  	loc_wipe (&loc); -	dict_unref (xdata); +        if (xdata) +                dict_unref (xdata); +        if (new_frame) +                AFR_STACK_DESTROY (new_frame);  	return ret;  }  int -__afr_selfheal_name_impunge (call_frame_t *frame, xlator_t *this, inode_t *parent, -			     uuid_t pargfid, const char *bname, inode_t *inode, -			     struct afr_reply *replies, int gfid_idx) +__afr_selfheal_name_impunge (xlator_t *this, inode_t *parent, uuid_t pargfid, +                             const char *bname, inode_t *inode, +                             struct afr_reply *replies, int gfid_idx)  {  	int i = 0;  	afr_private_t *priv = NULL; @@ -84,8 +127,8 @@ __afr_selfheal_name_impunge (call_frame_t *frame, xlator_t *this, inode_t *paren  				  replies[gfid_idx].poststat.ia_gfid) == 0)  			continue; -		ret |= afr_selfheal_recreate_entry (frame, this, i, gfid_idx, -						    parent, bname, inode, replies); +		ret |= afr_selfheal_recreate_entry (this, i, gfid_idx, parent, +                                                    bname, inode, replies);  	}  	return ret; @@ -93,8 +136,8 @@ __afr_selfheal_name_impunge (call_frame_t *frame, xlator_t *this, inode_t *paren  int -__afr_selfheal_name_expunge (call_frame_t *frame, xlator_t *this, inode_t *parent, -			     uuid_t pargfid, const char *bname, inode_t *inode, +__afr_selfheal_name_expunge (xlator_t *this, inode_t *parent, uuid_t pargfid, +                             const char *bname, inode_t *inode,  			     struct afr_reply *replies)  {  	loc_t loc = {0, }; @@ -143,25 +186,44 @@ __afr_selfheal_name_expunge (call_frame_t *frame, xlator_t *this, inode_t *paren  } +/* This function is to be called after ensuring that there is no gfid mismatch + * for the inode across multiple sources + */ +static int +afr_selfheal_gfid_idx_get (xlator_t *this, struct afr_reply *replies, +                           unsigned char *sources) +{ +        int             i        =  0; +        int             gfid_idx = -1; +        afr_private_t  *priv     =  NULL; + +        priv = this->private; -int -__afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent, -			uuid_t pargfid, const char *bname, inode_t *inode, -			unsigned char *sources, unsigned char *sinks, -			unsigned char *healed_sinks, int source, -			unsigned char *locked_on, struct afr_reply *replies, -                        void *gfid_req) +        for (i = 0; i < priv->child_count; i++) { +                if (!replies[i].valid) +                        continue; + +                if (!sources[i]) +                        continue; + +                if (uuid_is_null (replies[i].poststat.ia_gfid)) +                        continue; + +                gfid_idx = i; +                break; +        } +        return gfid_idx; +} + +static gf_boolean_t +afr_selfheal_name_need_heal_check (xlator_t *this, struct afr_reply *replies)  { -	int i = 0; -	afr_private_t *priv = NULL; -	void* gfid = NULL; -	int gfid_idx = -1; -	gf_boolean_t source_is_empty = _gf_true; -	gf_boolean_t need_heal = _gf_false; -	int first_idx = -1; -	char g1[64],g2[64]; +        int             i           = 0; +	int             first_idx   = -1; +        gf_boolean_t    need_heal   = _gf_false; +        afr_private_t  *priv        = NULL; -	priv = this->private; +        priv = this->private;  	for (i = 0; i < priv->child_count; i++) {  		if (!replies[i].valid) @@ -182,29 +244,76 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,  		if (uuid_compare (replies[i].poststat.ia_gfid,  				  replies[first_idx].poststat.ia_gfid))  			need_heal = _gf_true; + +                if ((replies[i].op_ret == 0) && +                    (uuid_is_null(replies[i].poststat.ia_gfid))) +                        need_heal = _gf_true; +  	} -	if (!need_heal) -		return 0; +        return need_heal; +} -	for (i = 0; i < priv->child_count; i++) { -                if (!sources[i]) +static int +afr_selfheal_name_type_mismatch_check (xlator_t *this, struct afr_reply *replies, +                                       int source, unsigned char *sources, +                                       uuid_t pargfid, const char *bname) +{ +        int             i           = 0; +        int             type_idx    = -1; +        ia_type_t       inode_type  = IA_INVAL; +        afr_private_t  *priv        = NULL; + +        priv = this->private; + +        for (i = 0; i < priv->child_count; i++) { +                if (!replies[i].valid)                          continue; -                if (replies[i].op_ret == -1 && replies[i].op_errno == ENOENT) +                if (replies[i].poststat.ia_type == IA_INVAL)                          continue; -                source_is_empty = _gf_false; -                break; -	} +                if (inode_type == IA_INVAL) { +                        inode_type = replies[i].poststat.ia_type; +                        type_idx = i; +                        continue; +                } + +                if (sources[i] || source == -1) { +                        if ((sources[type_idx] || source == -1) && +                            (inode_type != replies[i].poststat.ia_type)) { +                                    gf_msg (this->name, GF_LOG_WARNING, 0, +                                            AFR_MSG_SPLIT_BRAIN, +                                            "Type mismatch for <gfid:%s>/%s: " +                                            "%d on %s and %d on %s", +                                            uuid_utoa(pargfid), bname, +                                            replies[i].poststat.ia_type, +                                            priv->children[i]->name, +                                            replies[type_idx].poststat.ia_type, +                                            priv->children[type_idx]->name); +                                return -EIO; +                        } +                } +                inode_type = replies[i].poststat.ia_type; +                type_idx = i; +                continue; +        } +        return 0; +} -        if (source == -1) -                source_is_empty = _gf_false; +static int +afr_selfheal_name_gfid_mismatch_check (xlator_t *this, struct afr_reply *replies, +                                       int source, unsigned char *sources, +                                       int *gfid_idx, uuid_t pargfid, +                                       const char *bname) +{ +        int             i             = 0; +	int             gfid_idx_iter = -1; +        void           *gfid          = NULL; +        afr_private_t  *priv          = NULL; +	char g1[64], g2[64]; -	if (source_is_empty) { -		return __afr_selfheal_name_expunge (frame, this, parent, pargfid, -						    bname, inode, replies); -	} +        priv = this->private;  	for (i = 0; i < priv->child_count; i++) {  		if (!replies[i].valid) @@ -215,13 +324,12 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,  		if (!gfid) {  			gfid = &replies[i].poststat.ia_gfid; -			gfid_idx = i; +			gfid_idx_iter = i;  			continue;  		}  		if (sources[i] || source == -1) { -			if (gfid_idx != -1 && -			    (sources[gfid_idx] || source == -1) && +			if ((sources[gfid_idx_iter] || source == -1) &&  			    uuid_compare (gfid, replies[i].poststat.ia_gfid)) {  				gf_msg (this->name, GF_LOG_WARNING, 0,                                          AFR_MSG_SPLIT_BRAIN, @@ -230,34 +338,110 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,  					uuid_utoa (pargfid), bname,  					uuid_utoa_r (replies[i].poststat.ia_gfid, g1),  					priv->children[i]->name, -					uuid_utoa_r (replies[gfid_idx].poststat.ia_gfid, g2), -					priv->children[gfid_idx]->name); -				return -1; +					uuid_utoa_r (replies[gfid_idx_iter].poststat.ia_gfid, g2), +					priv->children[gfid_idx_iter]->name); +				return -EIO;  			}                          gfid = &replies[i].poststat.ia_gfid; -			gfid_idx = i; +			gfid_idx_iter = i;  			continue;  		}  	} +        *gfid_idx = gfid_idx_iter; +        return 0; +} + +static gf_boolean_t +afr_selfheal_name_source_empty_check (xlator_t *this, struct afr_reply *replies, +                                      unsigned char *sources, int source) +{ +	int             i               = 0; +	afr_private_t  *priv            = NULL; +	gf_boolean_t    source_is_empty = _gf_true; + +	priv = this->private; + +        if (source == -1) { +                source_is_empty = _gf_false; +                goto out; +        } + +	for (i = 0; i < priv->child_count; i++) { +                if (!sources[i]) +                        continue; + +                if (replies[i].op_ret == -1 && replies[i].op_errno == ENOENT) +                        continue; + +                source_is_empty = _gf_false; +                break; +	} +out: +        return source_is_empty; +} + +int +__afr_selfheal_name_do (xlator_t *this, inode_t *parent, uuid_t pargfid, +                        const char *bname, inode_t *inode, +                        unsigned char *sources, unsigned char *sinks, +			unsigned char *healed_sinks, int source, +			unsigned char *locked_on, struct afr_reply *replies, +                        void *gfid_req) +{ +	int             gfid_idx        = -1; +        int             ret             = -1; +	void           *gfid            = NULL; +	gf_boolean_t    source_is_empty = _gf_true; +	gf_boolean_t    need_heal       = _gf_false; +        gf_boolean_t    is_gfid_absent  = _gf_false; + +        need_heal = afr_selfheal_name_need_heal_check (this, replies); +	if (!need_heal) +		return 0; + +        source_is_empty = afr_selfheal_name_source_empty_check (this, replies, +                                                                sources, +                                                                source); +	if (source_is_empty) +		return __afr_selfheal_name_expunge (this, parent, pargfid, +						    bname, inode, replies); + +        ret = afr_selfheal_name_type_mismatch_check (this, replies, source, +                                                     sources, pargfid, bname); +        if (ret) +                return ret; + +        ret = afr_selfheal_name_gfid_mismatch_check (this, replies, source, +                                                     sources, &gfid_idx, +                                                     pargfid, bname); +        if (ret) +                return ret; +  	if (gfid_idx == -1) {                  if (!gfid_req || uuid_is_null (gfid_req))                          return -1;                  gfid = gfid_req; +        } else { +                gfid = &replies[gfid_idx].poststat.ia_gfid;          } -	__afr_selfheal_assign_gfid (frame, this, parent, pargfid, bname, inode, -				    replies, gfid); -        /*TODO: -         * once the gfid is assigned refresh the replies and carry on with -         * impunge. i.e. gfid_idx won't be -1. -         */ -        if (gfid_idx == -1) -                return -1; +        is_gfid_absent = (gfid_idx == -1) ? _gf_true : _gf_false; +	ret = __afr_selfheal_assign_gfid (this, parent, pargfid, bname, inode, +                                          replies, gfid, locked_on, +                                          is_gfid_absent); +        if (ret) +                return ret; + +        if (gfid_idx == -1) { +                gfid_idx = afr_selfheal_gfid_idx_get (this, replies, sources); +                if (gfid_idx == -1) +                        return -1; +        } -	return __afr_selfheal_name_impunge (frame, this, parent, pargfid, -					    bname, inode, replies, gfid_idx); +	return __afr_selfheal_name_impunge (this, parent, pargfid, bname, inode, +                                            replies, gfid_idx);  } @@ -310,8 +494,7 @@ __afr_selfheal_name_prepare (call_frame_t *frame, xlator_t *this, inode_t *paren  	if (ret)  		goto out; -	ret = afr_selfheal_find_direction (frame, this, replies, -					   AFR_ENTRY_TRANSACTION, +	ret = afr_selfheal_find_direction (this, replies, AFR_ENTRY_TRANSACTION,  					   locked_on, sources, sinks);  	if (ret)  		goto out; @@ -355,6 +538,17 @@ afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,          struct afr_reply *replies = NULL;  	int ret = -1;  	inode_t *inode = NULL; +        dict_t *xattr = NULL; + +        xattr = dict_new (); +        if (!xattr) +                return -ENOMEM; + +        ret = dict_set_int32 (xattr, GF_GFIDLESS_LOOKUP, 1); +        if (ret) { +                dict_destroy (xattr); +                return -1; +        }  	priv = this->private; @@ -379,16 +573,17 @@ afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,  		if (ret)  			goto unlock; -		inode = afr_selfheal_unlocked_lookup_on (frame, parent, bname, -							 replies, locked_on); +                inode = afr_selfheal_unlocked_lookup_on (frame, parent, bname, +						         replies, locked_on, +                                                         xattr);  		if (!inode) {  			ret = -ENOMEM;  			goto unlock;  		} -		ret = __afr_selfheal_name_do (frame, this, parent, pargfid, bname, -					      inode, sources, sinks, healed_sinks, -					      source, locked_on, replies, +		ret = __afr_selfheal_name_do (this, parent, pargfid, bname, +                                              inode, sources, sinks, healed_sinks, +                                              source, locked_on, replies,                                                gfid_req);  	}  unlock: @@ -399,6 +594,8 @@ unlock:          if (replies)                  afr_replies_wipe (replies, priv->child_count); +        if (xattr) +                dict_unref (xattr);  	return ret;  } @@ -420,7 +617,7 @@ afr_selfheal_name_unlocked_inspect (call_frame_t *frame, xlator_t *this,  	replies = alloca0 (sizeof (*replies) * priv->child_count);  	inode = afr_selfheal_unlocked_lookup_on (frame, parent, bname, -						 replies, priv->child_up); +						 replies, priv->child_up, NULL);  	if (!inode)  		return -ENOMEM; @@ -474,9 +671,14 @@ afr_selfheal_name (xlator_t *this, uuid_t pargfid, const char *bname,  	if (ret)  		goto out; -	if (need_heal) -		afr_selfheal_name_do (frame, this, parent, pargfid, bname, -                                      gfid_req); +	if (need_heal) { +		ret = afr_selfheal_name_do (frame, this, parent, pargfid, bname, +                                            gfid_req); +                if (ret) +                        goto out; +        } + +        ret = 0;  out:  	if (parent)  		inode_unref (parent); diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h index da0025bb600..84da0d8000f 100644 --- a/xlators/cluster/afr/src/afr-self-heal.h +++ b/xlators/cluster/afr/src/afr-self-heal.h @@ -132,11 +132,10 @@ afr_selfheal_unlocked_discover (call_frame_t *frame, inode_t *inode,  inode_t *  afr_selfheal_unlocked_lookup_on (call_frame_t *frame, inode_t *parent,  				 const char *name, struct afr_reply *replies, -				 unsigned char *lookup_on); +				 unsigned char *lookup_on, dict_t *xattr);  int -afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this, -			     struct afr_reply *replies, +afr_selfheal_find_direction (xlator_t *this, struct afr_reply *replies,  			     afr_transaction_type type, unsigned char *locked_on,  			     unsigned char *sources, unsigned char *sinks); @@ -151,9 +150,9 @@ afr_selfheal_undo_pending (call_frame_t *frame, xlator_t *this, inode_t *inode,  			   struct afr_reply *replies, unsigned char *locked_on);  int -afr_selfheal_recreate_entry (call_frame_t *frame, xlator_t *this, int dst, -			     int source, inode_t *dir, const char *name, -			     inode_t *inode, struct afr_reply *replies); +afr_selfheal_recreate_entry (xlator_t *this, int dst, int source, inode_t *dir, +                             const char *name, inode_t *inode, +                             struct afr_reply *replies);  int  afr_selfheal_post_op (call_frame_t *frame, xlator_t *this, inode_t *inode, @@ -165,4 +164,13 @@ afr_frame_create (xlator_t *this);  inode_t *  afr_inode_find (xlator_t *this, uuid_t gfid); +int +afr_selfheal_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +			   int op_ret, int op_errno, inode_t *inode, +			   struct iatt *buf, dict_t *xdata, +                           struct iatt *parbuf); + +void +afr_replies_copy (struct afr_reply *dst, struct afr_reply *src, int count); +  #endif /* !_AFR_SELFHEAL_H */  | 
