diff options
author | Venky Shankar <venky@gluster.com> | 2011-07-01 00:18:53 +0000 |
---|---|---|
committer | Anand Avati <avati@gluster.com> | 2011-07-12 05:37:51 -0700 |
commit | 4c55f76d6a4d13ec1ed3cffd31ff4acc3d3122f0 (patch) | |
tree | bdc9a5522e30adee821e53f2bb5613e7296aa95d /xlators/cluster/afr/src/afr-inode-read.c | |
parent | 1a82b4539b69390dfb1a158c420385c7ad5d999f (diff) |
afr/stripe: collect pathinfo xattrs from all childs
Signed-off-by: Venky Shankar <venky@gluster.com>
Signed-off-by: Anand Avati <avati@gluster.com>
BUG: 3046 (getxattr for afr should returns realpath from all childs)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=3046
Diffstat (limited to 'xlators/cluster/afr/src/afr-inode-read.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-inode-read.c | 124 |
1 files changed, 123 insertions, 1 deletions
diff --git a/xlators/cluster/afr/src/afr-inode-read.c b/xlators/cluster/afr/src/afr-inode-read.c index 431b73475..742d3687c 100644 --- a/xlators/cluster/afr/src/afr-inode-read.c +++ b/xlators/cluster/afr/src/afr-inode-read.c @@ -654,6 +654,110 @@ afr_getxattr_unwind (call_frame_t *frame, } int32_t +afr_getxattr_pathinfo_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + dict_t *dict) +{ + afr_local_t *local = NULL; + int32_t callcnt = 0; + int ret = 0; + char *pathinfo = NULL; + char *pathinfo_serz = NULL; + char pathinfo_cky[1024] = {0,}; + dict_t *xattr = NULL; + long cky = 0; + int32_t padding = 0; + int32_t tlen = 0; + + if (!frame || !frame->local || !this) { + gf_log (this->name, GF_LOG_ERROR, "possible NULL deref"); + goto out; + } + + local = frame->local; + cky = (long) cookie; + + LOCK (&frame->lock); + { + callcnt = --local->call_count; + + if (!dict || (op_ret < 0)) + goto out; + + if (!local->dict) + local->dict = dict_new (); + + if (local->dict) { + ret = dict_get_str (dict, GF_XATTR_PATHINFO_KEY, &pathinfo); + if (ret) + goto out; + + pathinfo = gf_strdup (pathinfo); + + snprintf (pathinfo_cky, 1024, "%s-%ld", GF_XATTR_PATHINFO_KEY, cky); + ret = dict_set_dynstr (local->dict, pathinfo_cky, pathinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Cannot set pathinfo cookie key"); + goto out; + } + + local->cont.getxattr.pathinfo_len += strlen (pathinfo) + 1; + } + } + out: + UNLOCK (&frame->lock); + + if (!callcnt) { + if (!local->cont.getxattr.pathinfo_len) + goto unwind; + + xattr = dict_new (); + if (!xattr) + goto unwind; + + /* extra bytes for decorations (brackets and <>'s) */ + padding = strlen (this->name) + strlen (AFR_PATHINFO_HEADER) + 4; + local->cont.getxattr.pathinfo_len += (padding + 2); + + pathinfo_serz = GF_CALLOC (local->cont.getxattr.pathinfo_len, sizeof (char), + gf_common_mt_char); + + if (!pathinfo_serz) + goto unwind; + + /* the xlator info */ + sprintf (pathinfo_serz, "(<"AFR_PATHINFO_HEADER"%s> ", this->name); + + /* actual series of pathinfo */ + ret = dict_serialize_value_with_delim (local->dict, pathinfo_serz + strlen (pathinfo_serz), + &tlen, ' '); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Error serializing dictionary"); + goto unwind; + } + + /* closing part */ + *(pathinfo_serz + padding + tlen) = ')'; + *(pathinfo_serz + padding + tlen + 1) = '\0'; + + ret = dict_set_dynstr (xattr, GF_XATTR_PATHINFO_KEY, pathinfo_serz); + if (ret) + gf_log (this->name, GF_LOG_ERROR, "Cannot set pathinfo key in dict"); + + unwind: + AFR_STACK_UNWIND (getxattr, frame, op_ret, op_errno, xattr); + + if (local->dict) + dict_unref (local->dict); + + if (xattr) + dict_unref (xattr); + } + + return ret; +} + +int32_t afr_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name) { @@ -683,7 +787,7 @@ afr_getxattr (call_frame_t *frame, xlator_t *this, loc_copy (&local->loc, loc); if (name) - local->cont.getxattr.name = gf_strdup (name); + local->cont.getxattr.name = gf_strdup (name); if (name) { @@ -724,6 +828,24 @@ afr_getxattr (call_frame_t *frame, xlator_t *this, return 0; } + /* + * if we are doing getxattr with pathinfo as the key then we + * collect information from all childs + */ + if (strncmp (name, GF_XATTR_PATHINFO_KEY, + strlen (GF_XATTR_PATHINFO_KEY)) == 0) { + + local->call_count = priv->child_count; + for (i = 0; i < priv->child_count; i++) { + STACK_WIND_COOKIE (frame, afr_getxattr_pathinfo_cbk, + (void *) (long) i, + children[i], children[i]->fops->getxattr, + loc, name); + } + + return 0; + } + if (*priv->vol_uuid) { if ((match_uuid_local (name, priv->vol_uuid) == 0) && (-1 == frame->root->pid)) { |