diff options
| author | Vikas Gorur <vikas@gluster.com> | 2009-10-14 14:07:51 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-11-24 04:36:45 -0800 | 
| commit | 7c6bc261e7d60bb1c4103c2e2e64a8ab89aa66e9 (patch) | |
| tree | 59927d8a1a3e9bbb4179849c14fd70f5ba1fe9dc | |
| parent | 1cd2e389020b8713d45dce44df9f473622109b0d (diff) | |
cluster/afr: Unlock only those paths which have been locked during rename.
For ENTRY_RENAME_TRANSACTIONs, keep track separately whether the
lower_path and the higher_path have been locked, and unlock only
those which have been.
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 112 (parallel deletion of files mounted by different clients on the same back-end hangs and/or does not completely delete)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=112
| -rw-r--r-- | xlators/cluster/afr/src/afr-transaction.c | 219 | 
1 files changed, 142 insertions, 77 deletions
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c index 526129846c2..ca13b9f0711 100644 --- a/xlators/cluster/afr/src/afr-transaction.c +++ b/xlators/cluster/afr/src/afr-transaction.c @@ -27,6 +27,12 @@  #include <alloca.h> +#define LOCKED_NO       0x0        /* no lock held */ +#define LOCKED_YES      0x1        /* for DATA, METADATA, ENTRY and higher_path +                                      of RENAME */ +#define LOCKED_LOWER    0x2        /* for lower_path of RENAME */ + +  static void  afr_pid_save (call_frame_t *frame)  { @@ -379,6 +385,43 @@ afr_lock_server_count (afr_private_t *priv, afr_transaction_type type)  /* {{{ unlock */ +static int +afr_transaction_locked_nodes_count (afr_local_t *local, int child_count) +{ +        int i; +        int call_count = 0; + +        for (i = 0; i < child_count; i++) { +                if (local->transaction.locked_nodes[i] & LOCKED_YES) +                        call_count++; + +                if ((local->transaction.type == AFR_ENTRY_RENAME_TRANSACTION) +                    && (local->transaction.locked_nodes[i] & LOCKED_LOWER)) { +                        call_count++; +                } +        } + +        return call_count; +} + + +static loc_t * +lower_path (loc_t *l1, const char *b1, loc_t *l2, const char *b2) +{ +	int ret = 0; + +	ret = strcmp (l1->path, l2->path); +	 +	if (ret == 0)  +		ret = strcmp (b1, b2); + +	if (ret <= 0) +		return l1; +	else +		return l2; +} + +  int32_t  afr_unlock_common_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  		       int32_t op_ret, int32_t op_errno) @@ -413,6 +456,12 @@ afr_unlock (call_frame_t *frame, xlator_t *this)  	afr_local_t *local = NULL;  	afr_private_t * priv = this->private; +        loc_t * lower  = NULL; +        loc_t * higher = NULL; + +        const char *lower_name  = NULL; +        const char *higher_name = NULL; +  	local = frame->local;          /* @@ -422,17 +471,14 @@ afr_unlock (call_frame_t *frame, xlator_t *this)          frame->root->pid = (long) frame->root; -	call_count = afr_locked_nodes_count (local->transaction.locked_nodes,  -					     priv->child_count); -	 +	call_count = afr_transaction_locked_nodes_count (local, +                                                         priv->child_count); +  	if (call_count == 0) {  		local->transaction.done (frame, this);  		return 0;  	} -	if (local->transaction.type == AFR_ENTRY_RENAME_TRANSACTION)  -		call_count *= 2; -  	local->call_count = call_count;		  	for (i = 0; i < priv->child_count; i++) {				 @@ -440,66 +486,101 @@ afr_unlock (call_frame_t *frame, xlator_t *this)  		flock.l_len   = local->transaction.len;  		flock.l_type  = F_UNLCK;			 -		if (local->transaction.locked_nodes[i]) { -			switch (local->transaction.type) { -			case AFR_DATA_TRANSACTION: -			case AFR_METADATA_TRANSACTION: -			case AFR_FLUSH_TRANSACTION: - -				if (local->fd) { -					STACK_WIND (frame, afr_unlock_common_cbk,	 -						    priv->children[i],  -						    priv->children[i]->fops->finodelk,  -						    this->name, local->fd,  +                switch (local->transaction.type) { +                case AFR_DATA_TRANSACTION: +                case AFR_METADATA_TRANSACTION: +                case AFR_FLUSH_TRANSACTION: + +                        if (local->transaction.locked_nodes[i] & LOCKED_YES) { +                                if (local->fd) { +                                        STACK_WIND (frame, afr_unlock_common_cbk,	 +                                                    priv->children[i],  +                                                    priv->children[i]->fops->finodelk,  +                                                    this->name, local->fd,                                                       F_SETLK, &flock);  -				} else { -					STACK_WIND (frame, afr_unlock_common_cbk,	 -						    priv->children[i],  -						    priv->children[i]->fops->inodelk,  -						    this->name, &local->loc, +                                } else { +                                        STACK_WIND (frame, afr_unlock_common_cbk,	 +                                                    priv->children[i],  +                                                    priv->children[i]->fops->inodelk,  +                                                    this->name, &local->loc,                                                      F_SETLK, &flock);  -				} -				 -				break; +                                } -			case AFR_ENTRY_RENAME_TRANSACTION: -				 -				STACK_WIND (frame, afr_unlock_common_cbk,	 -					    priv->children[i],  -					    priv->children[i]->fops->entrylk,  +                                call_count--; +                        } + +                        break; + +                case AFR_ENTRY_RENAME_TRANSACTION: +                        lower = lower_path (&local->transaction.parent_loc, +                                            local->transaction.basename, +                                            &local->transaction.new_parent_loc, +                                            local->transaction.new_basename); + +                        lower_name = (lower == &local->transaction.parent_loc ? +                                      local->transaction.basename : +                                      local->transaction.new_basename); + +                        higher = (lower == &local->transaction.parent_loc ? +                                  &local->transaction.new_parent_loc : +                                  &local->transaction.parent_loc); + +                        higher_name = (higher == &local->transaction.parent_loc ? +                                       local->transaction.basename : +                                       local->transaction.new_basename); + +                        if (local->transaction.locked_nodes[i] & LOCKED_LOWER) { +                                STACK_WIND (frame, afr_unlock_common_cbk,	 +                                            priv->children[i],  +                                            priv->children[i]->fops->entrylk,                                               this->name, -					    &local->transaction.new_parent_loc,  -					    local->transaction.new_basename, -					    ENTRYLK_UNLOCK, ENTRYLK_WRLCK); +                                            lower, lower_name, +                                            ENTRYLK_UNLOCK, ENTRYLK_WRLCK); -				call_count--; +                                call_count--; +                        } -				/* fall through */ +                        if (local->transaction.locked_nodes[i] & LOCKED_YES) { +                                STACK_WIND (frame, afr_unlock_common_cbk,	 +                                            priv->children[i],  +                                            priv->children[i]->fops->entrylk,  +                                            this->name, +                                            higher, higher_name, +                                            ENTRYLK_UNLOCK, ENTRYLK_WRLCK); -			case AFR_ENTRY_TRANSACTION: -				if (local->fd) { -					STACK_WIND (frame, afr_unlock_common_cbk,	 -						    priv->children[i],  -						    priv->children[i]->fops->fentrylk,  -						    this->name, local->fd,  -						    local->transaction.basename, -						    ENTRYLK_UNLOCK, ENTRYLK_WRLCK); -				} else { -					STACK_WIND (frame, afr_unlock_common_cbk,	 -						    priv->children[i],  -						    priv->children[i]->fops->entrylk,  -						    this->name, +                                call_count--; +                        } + +                        break; + +                case AFR_ENTRY_TRANSACTION: +                        if (local->transaction.locked_nodes[i] & LOCKED_YES) { +                                if (local->fd) { +                                        STACK_WIND (frame, afr_unlock_common_cbk,	 +                                                    priv->children[i],  +                                                    priv->children[i]->fops->fentrylk,  +                                                    this->name, local->fd,  +                                                    local->transaction.basename, +                                                    ENTRYLK_UNLOCK, ENTRYLK_WRLCK); +                                } else { +                                        STACK_WIND (frame, afr_unlock_common_cbk,	 +                                                    priv->children[i],  +                                                    priv->children[i]->fops->entrylk,  +                                                    this->name,                                                      &local->transaction.parent_loc,  -						    local->transaction.basename, -						    ENTRYLK_UNLOCK, ENTRYLK_WRLCK); +                                                    local->transaction.basename, +                                                    ENTRYLK_UNLOCK, ENTRYLK_WRLCK); -				} -				break; -			} -			 -			if (!--call_count) -				break; -		} +                                } + +                                call_count--; +                        } + +                        break; +                } + +                if (!call_count) +                        break;  	}  	return 0; @@ -920,7 +1001,8 @@ afr_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  afr_unlock (frame, this);          } else {                  if (op_ret == 0) { -                        local->transaction.locked_nodes[child_index] = 1; +                        local->transaction.locked_nodes[child_index] +                                |= LOCKED_YES;                          local->transaction.lock_count++;                  }                  afr_lock_rec (frame, this, child_index + 1); @@ -930,23 +1012,6 @@ afr_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  } -static loc_t * -lower_path (loc_t *l1, const char *b1, loc_t *l2, const char *b2) -{ -	int ret = 0; - -	ret = strcmp (l1->path, l2->path); -	 -	if (ret == 0)  -		ret = strcmp (b1, b2); - -	if (ret <= 0) -		return l1; -	else -		return l2; -} - -  int32_t  afr_lock_lower_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                      int32_t op_ret, int32_t op_errno) @@ -988,7 +1053,7 @@ afr_lock_lower_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  afr_unlock (frame, this);                  goto out;          } else { -                local->transaction.locked_nodes[child_index] = 1; +                local->transaction.locked_nodes[child_index] |= LOCKED_LOWER;          }          /* The lower path has been locked. Now lock the higher path */ @@ -1057,7 +1122,7 @@ int afr_lock_rec (call_frame_t *frame, xlator_t *this, int child_index)  		local->op_ret   = -1;  		local->op_errno = EAGAIN; -		local->transaction.done (frame, this); +                afr_unlock (frame, this);  		return 0;  | 
