diff options
| author | Venky Shankar <venky@gluster.com> | 2011-08-16 12:17:29 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2011-08-24 06:41:39 -0700 | 
| commit | d499cb8064f61b70bc37a7d6cbf0f0c3b219c342 (patch) | |
| tree | 5a93bc707dd7a18e103e0ce686615711323f9775 | |
| parent | 6f1062f3473407cebfd5d902db2d2c6965dcf034 (diff) | |
afr/stripe: collect pathinfo xattr from all childs
Change-Id: Iec8b609e66ef21f4fdd6ee2ff3060f0b71d47ca0
BUG: 3046
Reviewed-on: http://review.gluster.com/237
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
| -rw-r--r-- | libglusterfs/src/dict.c | 96 | ||||
| -rw-r--r-- | libglusterfs/src/dict.h | 2 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-inode-read.c | 125 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.h | 2 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 60 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-common.h | 1 | ||||
| -rw-r--r-- | xlators/cluster/stripe/src/stripe-mem-types.h | 1 | ||||
| -rw-r--r-- | xlators/cluster/stripe/src/stripe.c | 178 | ||||
| -rw-r--r-- | xlators/cluster/stripe/src/stripe.h | 12 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 2 | 
10 files changed, 460 insertions, 19 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index 18e62d96f42..7fbacf7c3d0 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -2610,3 +2610,99 @@ unlock:  out:          return ret;  } + +/** + * _dict_serialize_value_with_delim: serialize the values in the dictionary + * into a buffer separated by delimiter (except the last) + * + * @this      : dictionary to serialize + * @buf       : the buffer to store the serialized data + * @serz_len  : the length of the serialized data (excluding the last delimiter) + * @delimiter : the delimiter to separate the values + * + * @return    : 0 -> success + *            : -errno -> faliure + */ +int +_dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, +                                  char delimiter) +{ +        int          ret       = -1; +        int32_t      count     = 0; +        int32_t      vallen    = 0; +        int32_t      total_len = 0; +        data_pair_t *pair      = NULL; + +        if (!buf) { +                gf_log ("dict", GF_LOG_ERROR, "buf is null"); +                goto out; +        } + +        count = this->count; +        if (count < 0) { +                gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0", count); +                goto out; +        } + +        pair = this->members_list; + +        while (count) { +                if (!pair) { +                        gf_log ("dict", GF_LOG_ERROR, +                                "less than count data pairs found"); +                        goto out; +                } + +                if (!pair->key || !pair->value) { +                        gf_log ("dict", GF_LOG_ERROR, +                                "key or value is null"); +                        goto out; +                } + +                if (!pair->value->data) { +                        gf_log ("dict", GF_LOG_ERROR, +                                "null value found in dict"); +                        goto out; +                } + +                vallen = pair->value->len - 1; // length includes \0 +                memcpy (buf, pair->value->data, vallen); +                buf += vallen; +                *buf++ = delimiter; + +                total_len += (vallen + 1); + +                pair = pair->next; +                count--; +        } + +        *--buf = '\0'; // remove the last delimiter +        total_len--;   // adjust the length +        ret = 0; + +        if (serz_len) +                *serz_len = total_len; + + out: +        return ret; +} + +int +dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, +                                 char delimiter) +{ +        int           ret    = -1; + +        if (!this || !buf) { +                gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is null!"); +                goto out; +        } + +        LOCK (&this->lock); +        { +                ret = _dict_serialize_value_with_delim (this, buf, serz_len, delimiter); +        } +        UNLOCK (&this->lock); +out: +        return ret; +} diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 9ee094eca62..0d404997ee0 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -184,4 +184,6 @@ GF_MUST_CHECK int dict_set_dynstr (dict_t *this, char *key, char *str);  GF_MUST_CHECK int dict_get_str (dict_t *this, char *key, char **str);  GF_MUST_CHECK int dict_get_str_boolean (dict_t *this, char *key, int default_val); +GF_MUST_CHECK int dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, +                                                    char delimiter);  #endif diff --git a/xlators/cluster/afr/src/afr-inode-read.c b/xlators/cluster/afr/src/afr-inode-read.c index efeb952017a..0f934f8028f 100644 --- a/xlators/cluster/afr/src/afr-inode-read.c +++ b/xlators/cluster/afr/src/afr-inode-read.c @@ -665,6 +665,111 @@ 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 unlock; +        } + +        local = frame->local; +        cky = (long) cookie; + +        LOCK (&frame->lock); +                { +                        callcnt = --local->call_count; + +                        if (!dict || (op_ret < 0)) +                                goto unlock; + +                        if (!local->dict) +                                local->dict = dict_new (); + +                        if (local->dict) { +                                ret = dict_get_str (dict, GF_XATTR_PATHINFO_KEY, &pathinfo); +                                if (ret) +                                        goto unlock; + +                                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 unlock; +                                } + +                                local->cont.getxattr.pathinfo_len += strlen (pathinfo) + 1; +                        } +                } + unlock: +        if (frame) +                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)  { @@ -694,7 +799,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) { @@ -735,6 +840,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)) { diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index ef8ad2af262..6f40ded1274 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -33,6 +33,7 @@  #include "libxlator.h"  #define AFR_XATTR_PREFIX "trusted.afr" +#define AFR_PATHINFO_HEADER "REPLICATE:"  struct _pump_private; @@ -388,6 +389,7 @@ typedef struct _afr_local {                  struct {                          char *name;                          int last_tried; +                        long pathinfo_len;                  } getxattr;                  struct { diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 3bd9df9c3e1..e03c463bc0e 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -1913,28 +1913,50 @@ int  dht_pathinfo_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                             int op_ret, int op_errno, dict_t *xattr)  { -        dht_local_t  *local = NULL; -        int ret = 0; -        int flag = 0; -        int this_call_cnt = 0; -        char *value_got = NULL; -        char  layout_buf[8192] = {0,}; -        char  xattr_buf[8192 + 1024] = {0,}; -        dict_t *dict = NULL; +        dht_local_t *local         = NULL; +        int          ret           = 0; +        int          flag          = 0; +        int          this_call_cnt = 0; +        char        *value_got     = NULL; +        char  layout_buf[8192]     = {0,}; +        char        *xattr_buf     = NULL; +        dict_t      *dict          = NULL; +        int32_t      alloc_len     = 0; +        int32_t      plen          = 0;          local = frame->local;          if (op_ret != -1) {                  ret = dict_get_str (xattr, GF_XATTR_PATHINFO_KEY, &value_got);                  if (!ret) { -                        if (!local->pathinfo) -                                local->pathinfo = GF_CALLOC (8192, sizeof (char), -                                                             gf_common_mt_char); -                        if (local->pathinfo) +                        alloc_len = strlen (value_got); + +                        /** +                         * allocate the buffer:- we allocate 10 bytes extra in case we need to +                         * append ' Link: ' in the buffer for another STACK_WIND +                         */ +                        if (!local->pathinfo) { +                                alloc_len += (strlen (DHT_PATHINFO_HEADER) + 10); +                                local->pathinfo = GF_CALLOC (alloc_len, sizeof (char), gf_common_mt_char); +                        } + +                        if (local->pathinfo) { +                                plen = strlen (local->pathinfo); +                                if (plen) { +                                        /* extra byte(s) for \0 to be safe */ +                                        alloc_len += (plen + 2); +                                        local->pathinfo = GF_REALLOC (local->pathinfo, +                                                                      alloc_len); +                                        if (!local->pathinfo) +                                                goto out; +                                } +                                  strcat (local->pathinfo, value_got); +                        }                  }          } + out:          this_call_cnt = dht_frame_return (frame);          if (is_last_call (this_call_cnt)) {                  if (local->layout->cnt > 1) { @@ -1945,19 +1967,23 @@ dht_pathinfo_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  dict = dict_new (); +                /* we would need max-to-max this many bytes to create pathinfo string */ +                alloc_len += (2 * strlen (this->name)) + strlen (layout_buf) + 40; +                xattr_buf = GF_CALLOC (alloc_len, sizeof (char), gf_common_mt_char); +                  if (flag && local->pathinfo) -                        snprintf (xattr_buf, 9216, "((%s %s) (%s-layout %s))", +                        snprintf (xattr_buf, alloc_len, "((<"DHT_PATHINFO_HEADER"%s> %s) (%s-layout %s))",                                    this->name, local->pathinfo, this->name,                                    layout_buf);                  else if (local->pathinfo) -                        snprintf (xattr_buf, 9216, "(%s %s)", +                        snprintf (xattr_buf, alloc_len, "(<"DHT_PATHINFO_HEADER"%s> %s)",                                    this->name, local->pathinfo);                  else if (flag) -                        snprintf (xattr_buf, 9216, "(%s-layout %s)", +                        snprintf (xattr_buf, alloc_len, "(%s-layout %s)",                                    this->name, layout_buf); -                ret = dict_set_str (dict, GF_XATTR_PATHINFO_KEY, -                                    xattr_buf); +                ret = dict_set_dynstr (dict, GF_XATTR_PATHINFO_KEY, +                                       xattr_buf);                  if (local->pathinfo)                          GF_FREE (local->pathinfo); diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h index 7e93b02f8c7..437e0dff3dd 100644 --- a/xlators/cluster/dht/src/dht-common.h +++ b/xlators/cluster/dht/src/dht-common.h @@ -31,6 +31,7 @@  #define GF_XATTR_FIX_LAYOUT_KEY   "trusted.distribute.fix.layout"  #define GF_DHT_LOOKUP_UNHASHED_ON   1  #define GF_DHT_LOOKUP_UNHASHED_AUTO 2 +#define DHT_PATHINFO_HEADER "DISTRIBUTE:"  #include <fnmatch.h> diff --git a/xlators/cluster/stripe/src/stripe-mem-types.h b/xlators/cluster/stripe/src/stripe-mem-types.h index 25fd22835b6..29c95c2571d 100644 --- a/xlators/cluster/stripe/src/stripe-mem-types.h +++ b/xlators/cluster/stripe/src/stripe-mem-types.h @@ -34,6 +34,7 @@ enum gf_stripe_mem_types_ {          gf_stripe_mt_xlator_t,          gf_stripe_mt_stripe_private_t,          gf_stripe_mt_stripe_options, +        gf_stripe_mt_xattr_sort_t,          gf_stripe_mt_end  };  #endif diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c index 81f37a57277..72762555aa0 100644 --- a/xlators/cluster/stripe/src/stripe.c +++ b/xlators/cluster/stripe/src/stripe.c @@ -4255,6 +4255,166 @@ out:          return 0;  } +int32_t +stripe_pathinfo_aggregate (char *buffer, stripe_local_t *local, int32_t *total) +{ +        int32_t              i     = 0; +        int32_t              ret   = -1; +        int32_t              len   = 0; +        char                *sbuf  = NULL; +        stripe_xattr_sort_t *xattr = NULL; + +        if (!buffer || !local || !local->xattr_list) +                goto out; + +        sbuf = buffer; + +        for (i = 0; i < local->nallocs; i++) { +                xattr = local->xattr_list + i; +                len = xattr->pathinfo_len; + +                if (len && xattr && xattr->pathinfo) { +                        memcpy (buffer, xattr->pathinfo, len); +                        buffer += len; +                        *buffer++ = ' '; +                } +        } + +        *--buffer = '\0'; +        if (total) +                *total = buffer - sbuf; +        ret = 0; + + out: +        return ret; +} + +int32_t +stripe_free_pathinfo_str (stripe_local_t *local) +{ +        int32_t              i     = 0; +        int32_t              ret   = -1; +        stripe_xattr_sort_t *xattr = NULL; + +        if (!local || !local->xattr_list) +                goto out; + +        for (i = 0; i < local->nallocs; i++) { +                xattr = local->xattr_list + i; + +                if (xattr && xattr->pathinfo) +                        GF_FREE (xattr->pathinfo); +        } + +        ret = 0; + out: +        return ret; +} + +int32_t +stripe_getxattr_pathinfo_cbk (call_frame_t *frame, void *cookie, +                             xlator_t *this, int32_t op_ret, int32_t op_errno, +                             dict_t *dict) { +        stripe_local_t      *local         = NULL; +        int32_t              callcnt       = 0; +        int32_t              ret           = -1; +        long                 cky           = 0; +        char                *pathinfo      = NULL; +        char                *pathinfo_serz = NULL; +        int32_t              padding       = 0; +        int32_t              tlen          = 0; +        char stripe_size_str[20]           = {0,}; +        stripe_xattr_sort_t *xattr         = NULL; +        dict_t              *stripe_xattr  = NULL; + +        if (!frame || !frame->local || !this) { +                gf_log (this->name, GF_LOG_ERROR, "Possible NULL deref"); +                return ret; +        } + +        local = frame->local; +        cky = (long) cookie; + +        LOCK (&frame->lock); +        { +                callcnt = --local->wind_count; + +                if (!dict || (op_ret < 0)) +                        goto out; + +                if (!local->xattr_list) +                        local->xattr_list = (stripe_xattr_sort_t *) GF_CALLOC (local->nallocs, +                                                                               sizeof (stripe_xattr_sort_t), +                                                                               gf_stripe_mt_xattr_sort_t); + +                if (local->xattr_list) { +                        ret = dict_get_str (dict, GF_XATTR_PATHINFO_KEY, &pathinfo); +                        if (ret) +                                goto out; + +                        xattr = local->xattr_list + (int32_t) cky; + +                        pathinfo = gf_strdup (pathinfo); +                        xattr->pos = cky; +                        xattr->pathinfo = pathinfo; +                        xattr->pathinfo_len = strlen (pathinfo); + +                        local->xattr_total_len += strlen (pathinfo) + 1; +                } +        } + out: +        UNLOCK (&frame->lock); + +        if (!callcnt) { +                if (!local->xattr_total_len) +                        goto unwind; + +                stripe_xattr = dict_new (); +                if (!stripe_xattr) +                        goto unwind; + +                snprintf (stripe_size_str, 20, "%ld", local->stripe_size); + +                /* extra bytes for decorations (brackets and <>'s) */ +                padding = strlen (this->name) + strlen (STRIPE_PATHINFO_HEADER) +                        + strlen (stripe_size_str) + 7; +                local->xattr_total_len += (padding + 2); + +                pathinfo_serz = GF_CALLOC (local->xattr_total_len, sizeof (char), +                                           gf_common_mt_char); +                if (!pathinfo_serz) +                        goto unwind; + +                /* xlator info */ +                sprintf (pathinfo_serz, "(<"STRIPE_PATHINFO_HEADER"%s:[%s]> ", this->name, stripe_size_str); + +                ret = stripe_pathinfo_aggregate (pathinfo_serz + padding, local, &tlen); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Cannot aggregate pathinfo list"); +                        goto unwind; +                } + +                *(pathinfo_serz + padding + tlen) = ')'; +                *(pathinfo_serz + padding + tlen + 1) = '\0'; + +                ret = dict_set_dynstr (stripe_xattr, GF_XATTR_PATHINFO_KEY, pathinfo_serz); +                if (ret) +                        gf_log (this->name, GF_LOG_ERROR, "Cannot set pathinfo key in dict"); + +        unwind: +                STRIPE_STACK_UNWIND (getxattr, frame, op_ret, op_errno, stripe_xattr); + +                ret = stripe_free_pathinfo_str (local); + +                if (local->xattr_list) +                        GF_FREE (local->xattr_list); + +                if (stripe_xattr) +                        dict_unref (stripe_xattr); +        } + +        return ret; +}  int32_t  stripe_getxattr (call_frame_t *frame, xlator_t *this, @@ -4326,6 +4486,24 @@ stripe_getxattr (call_frame_t *frame, xlator_t *this,                  return 0;          } +        if (name && (strncmp (name, GF_XATTR_PATHINFO_KEY, +                              strlen (GF_XATTR_PATHINFO_KEY)) == 0)) { +                local->stripe_size = stripe_get_matching_bs (loc->path, +                                                             priv->pattern, +                                                             priv->block_size); +                local->nallocs = local->wind_count = priv->child_count; + +                for (i = 0, trav = this->children; i < priv->child_count; i++, +                     trav = trav->next) { +                        STACK_WIND_COOKIE (frame, stripe_getxattr_pathinfo_cbk, +                                           (void *) (long) i, trav->xlator, +                                           trav->xlator->fops->getxattr, +                                           loc, name); +                } + +                return 0; +        } +          if (name &&(*priv->vol_uuid)) {                  if ((match_uuid_local (name, priv->vol_uuid) == 0)                      && (-1 == frame->root->pid)) { diff --git a/xlators/cluster/stripe/src/stripe.h b/xlators/cluster/stripe/src/stripe.h index dc310138d75..8d43a960e54 100644 --- a/xlators/cluster/stripe/src/stripe.h +++ b/xlators/cluster/stripe/src/stripe.h @@ -37,6 +37,8 @@  #include <fnmatch.h>  #include <signal.h> +#define STRIPE_PATHINFO_HEADER "STRIPE:" +  #define STRIPE_STACK_UNWIND(fop, frame, params ...) do {           \                  stripe_local_t *__local = NULL;                    \ @@ -62,6 +64,12 @@                  }                                         \          } while (0) +typedef struct stripe_xattr_sort { +        int32_t  pos; +        int32_t  pathinfo_len; +        char    *pathinfo; +} stripe_xattr_sort_t; +  /**   * struct stripe_options : This keeps the pattern and the block-size   *     information, which is used for striping on a file. @@ -165,6 +173,10 @@ struct stripe_local {          /* For File I/O fops */          dict_t              *dict; +        stripe_xattr_sort_t *xattr_list; +        int32_t              xattr_total_len; +        int32_t              nallocs; +          struct marker_str    marker;          /* General usage */ diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 75719021b2c..6d0786c2949 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -3336,7 +3336,7 @@ posix_getxattr (call_frame_t *frame, xlator_t *this,          }          if (loc->inode && IA_ISREG (loc->inode->ia_type) && name &&              (strcmp (name, GF_XATTR_PATHINFO_KEY) == 0)) { -                snprintf (host_buf, 1024, "%s:%s", priv->hostname, +                snprintf (host_buf, 1024, "<POSIX:%s:%s>", priv->hostname,                            real_path);                  ret = dict_set_str (dict, GF_XATTR_PATHINFO_KEY,                                      host_buf);  | 
