diff options
-rw-r--r-- | libglusterfs/src/iatt.h | 2 | ||||
-rw-r--r-- | xlators/cluster/stripe/src/stripe.c | 105 |
2 files changed, 91 insertions, 16 deletions
diff --git a/libglusterfs/src/iatt.h b/libglusterfs/src/iatt.h index b84eaa379c0..aac42e22abb 100644 --- a/libglusterfs/src/iatt.h +++ b/libglusterfs/src/iatt.h @@ -103,6 +103,8 @@ struct iatt { #define IA_PROT_SGID(prot) ((prot).sgid == 1) #define IA_PROT_STCKY(prot) ((prot).sticky == 1) +#define IA_FILE_OR_DIR(t) (IA_ISREG(t) || IA_ISDIR(t)) + static inline uint32_t ia_major (uint64_t ia_dev) { diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c index 6762d9adc2c..c3f1b483f4f 100644 --- a/xlators/cluster/stripe/src/stripe.c +++ b/xlators/cluster/stripe/src/stripe.c @@ -3997,7 +3997,41 @@ int stripe_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno) { - STRIPE_STACK_UNWIND (setxattr, frame, op_ret, op_errno); + int ret = -1; + int call_cnt = 0; + stripe_local_t *local = NULL; + + if (!frame || !frame->local || !this) { + gf_log ("", GF_LOG_ERROR, "Possible NULL deref"); + return ret; + } + + local = frame->local; + + LOCK (&frame->lock); + { + call_cnt = --local->wind_count; + + /** + * We overwrite ->op_* values here for subsequent faliure + * conditions, hence we propogate the last errno down the + * stack. + */ + if (op_ret < 0) { + local->op_ret = op_ret; + local->op_errno = op_errno; + goto unlock; + } + } + + unlock: + UNLOCK (&frame->lock); + + if (!call_cnt) { + STRIPE_STACK_UNWIND (setxattr, frame, local->op_ret, + local->op_errno); + } + return 0; } @@ -4005,20 +4039,52 @@ int stripe_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, int flags) { - data_pair_t *trav = NULL; - int32_t op_errno = EINVAL; + data_pair_t *pair = NULL; + int32_t op_errno = EINVAL; + xlator_list_t *trav = NULL; + stripe_private_t *priv = NULL; + stripe_local_t *local = NULL; + int i = 0; VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); VALIDATE_OR_GOTO (loc, err); + VALIDATE_OR_GOTO (loc->inode, err); GF_IF_INTERNAL_XATTR_GOTO ("trusted.*stripe*", dict, - trav, op_errno, err); + pair, op_errno, err); + + priv = this->private; + trav = this->children; + + local = mem_get0 (this->local_pool); + if (!local) { + op_errno = ENOMEM; + goto err; + } + + frame->local = local; + local->wind_count = priv->child_count; + local->op_ret = local->op_errno = 0; + + /** + * Set xattrs for directories on all subvolumes. Additionally + * this power is only given to a special client. + */ + if ((frame->root->pid == -1) && IA_ISDIR (loc->inode->ia_type)) { + for (i = 0; i < priv->child_count; i++, trav = trav->next) { + STACK_WIND (frame, stripe_setxattr_cbk, + trav->xlator, trav->xlator->fops->setxattr, + loc, dict, flags); + } + } else { + local->wind_count = 1; + STACK_WIND (frame, stripe_setxattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, + loc, dict, flags); + } - STACK_WIND (frame, stripe_setxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, - loc, dict, flags); return 0; err: STRIPE_STACK_UNWIND (setxattr, frame, -1, op_errno); @@ -4854,7 +4920,7 @@ stripe_vgetxattr_cbk (call_frame_t *frame, void *cookie, dict_t *stripe_xattr = NULL; if (!frame || !frame->local || !this) { - gf_log (this->name, GF_LOG_ERROR, "Possible NULL deref"); + gf_log ("", GF_LOG_ERROR, "Possible NULL deref"); return ret; } @@ -5044,26 +5110,33 @@ stripe_getxattr (call_frame_t *frame, xlator_t *this, if (name &&(*priv->vol_uuid)) { if ((match_uuid_local (name, priv->vol_uuid) == 0) && (-1 == frame->root->pid)) { - local->marker.call_count = priv->child_count; - sub_volumes = alloca ( priv->child_count * - sizeof (xlator_t *)); - for (i = 0, trav = this->children; trav ; - trav = trav->next, i++) { + if (!IA_FILE_OR_DIR (loc->inode->ia_type)) + local->marker.call_count = 1; + else + local->marker.call_count = priv->child_count; + + sub_volumes = alloca (local->marker.call_count * + sizeof (xlator_t *)); + for (i = 0, trav = this->children; + i < local->marker.call_count; + i++, trav = trav->next) { *(sub_volumes + i) = trav->xlator; } if (cluster_getmarkerattr (frame, this, loc, name, - local, stripe_getxattr_unwind, + local, + stripe_getxattr_unwind, sub_volumes, - priv->child_count, + local->marker.call_count, MARKER_XTIME_TYPE, priv->vol_uuid)) { op_errno = EINVAL; goto err; } + return 0; } } |