From ba1d55c083a39f56077305037de0b619316b2717 Mon Sep 17 00:00:00 2001 From: shishir gowda Date: Wed, 3 Nov 2010 02:13:31 +0000 Subject: Fix DHT getxattr for directories When a heal on the directory or layout changes, the user xattrs do not get healed in dht. The current fix sends the getxattr call n all the subvolumes, aggregates it and sends the response Signed-off-by: shishir gowda Signed-off-by: Anand V. Avati BUG: 1991 (distribute directory self-heal does not copy user extended attributes) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1991 --- xlators/cluster/dht/src/dht-common.c | 80 ++++++++++++++++++++++++++++-------- xlators/cluster/dht/src/dht-common.h | 1 - xlators/cluster/dht/src/dht-helper.c | 4 ++ 3 files changed, 68 insertions(+), 17 deletions(-) (limited to 'xlators') diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index d1e04b16ae7..1ab55ccdc97 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -1805,14 +1805,33 @@ int dht_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, dict_t *xattr) { - if (op_ret != -1) { - if (dict_get (xattr, "trusted.glusterfs.dht")) { - dict_del (xattr, "trusted.glusterfs.dht"); - } - } + int this_call_cnt = 0; + dht_local_t *local = NULL; - DHT_STACK_UNWIND (getxattr, frame, op_ret, op_errno, xattr); + VALIDATE_OR_GOTO (frame, out); + VALIDATE_OR_GOTO (frame->local, out); + + local = frame->local; + + this_call_cnt = dht_frame_return (frame); + + if (!xattr || (op_ret == -1)) + goto out; + + if (dict_get (xattr, "trusted.glusterfs.dht")) { + dict_del (xattr, "trusted.glusterfs.dht"); + } + local->op_ret = 0; + if (!local->xattr) { + local->xattr = dict_copy_with_ref (xattr, NULL); + } else { + local->xattr = dict_copy (xattr, local->xattr); + } +out: + if (is_last_call (this_call_cnt)) { + DHT_STACK_UNWIND (getxattr, frame, local->op_ret, op_errno, local->xattr); + } return 0; } @@ -1831,6 +1850,7 @@ dht_getxattr (call_frame_t *frame, xlator_t *this, int ret = 0; int flag = 0; int i = 0; + int cnt = 0; VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); @@ -1939,18 +1959,46 @@ dht_getxattr (call_frame_t *frame, xlator_t *this, op_errno = ENODATA; goto err; } - subvol = dht_subvol_get_cached (this, loc->inode); - if (!subvol) { - gf_log (this->name, GF_LOG_DEBUG, - "no cached subvolume for path=%s", loc->path); - op_errno = EINVAL; - goto err; - } - STACK_WIND (frame, dht_getxattr_cbk, - subvol, subvol->fops->getxattr, - loc, key); + local = dht_local_init (frame); + if (!local) { + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); + goto err; + } + + ret = loc_dup (loc, &local->loc); + if (ret == -1) { + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); + goto err; + } + if (key) { + local->key = gf_strdup (key); + if (!local->key) { + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "Out of memory"); + goto err; + } + } + local->layout = layout; + + if (loc->inode-> ia_type == IA_IFDIR) { + cnt = local->call_cnt = layout->cnt; + } else { + cnt = local->call_cnt = 1; + } + + for (i = 0; i < cnt; i++) { + subvol = layout->list[i].xlator; + STACK_WIND (frame, dht_getxattr_cbk, + subvol, subvol->fops->getxattr, + loc, key); + } return 0; err: diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h index f0510f868f3..becc8d9c8e9 100644 --- a/xlators/cluster/dht/src/dht-common.h +++ b/xlators/cluster/dht/src/dht-common.h @@ -301,5 +301,4 @@ int dht_build_child_loc (xlator_t *this, loc_t *child, loc_t *parent, char *name int dht_filter_loc_subvol_key (xlator_t *this, loc_t *loc, loc_t *new_loc, xlator_t **subvol); - #endif /* _DHT_H */ diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c index f6ecebf93a7..dd257164701 100644 --- a/xlators/cluster/dht/src/dht-helper.c +++ b/xlators/cluster/dht/src/dht-helper.c @@ -221,6 +221,10 @@ dht_local_wipe (xlator_t *this, dht_local_t *local) GF_FREE (local->newpath); } + if (local->key) { + GF_FREE (local->key); + } + GF_FREE (local); } -- cgit