diff options
| -rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 239 | ||||
| -rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.h | 15 | 
2 files changed, 199 insertions, 55 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index 883345a2d3b..b96e92c6e2c 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -18,9 +18,6 @@  */  #include "stat-prefetch.h" -#include "locking.h" -#include "inode.h" -#include <libgen.h>  #define GF_SP_CACHE_BUCKETS 4096 @@ -374,53 +371,123 @@ sp_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                 int32_t op_ret, int32_t op_errno, inode_t *inode,                 struct stat *buf, dict_t *dict, struct stat *postparent)  { -        struct stat *stbuf = NULL; -        int32_t      ret   = -1; -        uint64_t     value = 0; +        sp_inode_ctx_t      *inode_ctx   = NULL; +        uint64_t             value       = 0; +        int                  ret         = 0; +        struct list_head     waiting_ops = {0, }; +        call_stub_t         *stub        = NULL, *tmp = NULL; +        sp_local_t          *local       = NULL; +        sp_cache_t          *cache       = NULL; -        if (op_ret == -1) { -                goto out; +        INIT_LIST_HEAD (&waiting_ops); + +        local = frame->local; +        if (local == NULL) { +                op_ret = -1; +                op_errno = EINVAL; +        } else if (op_ret == -1) { +                cache = sp_get_cache_inode (this, local->loc.parent, +                                            frame->root->pid); + +                if (cache) { +                        sp_cache_remove_entry (cache, (char *)local->loc.name, +                                               0); +                }          } -        if (S_ISDIR (buf->st_mode)) { -                LOCK (&inode->lock); +        ret = inode_ctx_get (inode, this, &value); +        if (ret == 0) { +                inode_ctx = (sp_inode_ctx_t *)(long)value;  +                if (inode_ctx == NULL) { +                        op_ret = -1; +                        op_errno = EINVAL; +                        goto out; +                } + +                LOCK (&inode_ctx->lock);                  { -                        ret = __inode_ctx_get (inode, this, &value); -                        if (ret == 0) { -                                stbuf = (struct stat *)(long)value; +                        inode_ctx->op_ret = op_ret; +                        inode_ctx->op_errno = op_errno; +                        inode_ctx->looked_up = 1; +                        inode_ctx->lookup_in_progress = 0; +                        if (S_ISDIR (buf->st_mode) && (op_ret == 0)) { +                                memcpy (&inode_ctx->stbuf, buf, +                                        sizeof (*buf));                          } +                        list_splice_init (&inode_ctx->waiting_ops, +                                          &waiting_ops); +                } +                UNLOCK (&inode_ctx->lock); -                        if (stbuf == NULL) { -                                stbuf = CALLOC (1, sizeof (*stbuf)); -                                if (stbuf == NULL) { -                                        op_ret = -1; -                                        op_errno = ENOMEM; -                                        gf_log (this->name, GF_LOG_ERROR, -                                                "out of memory"); -                                        goto unlock; -                                } +                list_for_each_entry_safe (stub, tmp, &waiting_ops, list) { +                        list_del_init (&stub->list); +                        call_resume (stub); +                } +        } else { +                op_errno = EINVAL; +                op_ret = -1; +        } -                                ret = __inode_ctx_put (inode, this, -                                                       (long)stbuf); -                                if (ret == -1) { -                                        op_ret = -1; -                                 -                                        /* FIXME: EINVAL is not correct */  -                                        op_errno = EINVAL; -                                        FREE (stbuf); -                                        goto unlock; -                                } +out: +        if ((local != NULL) && (local->is_lookup)) { +                SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict); +        } + +        return 0; +} + +void +sp_inode_ctx_free (xlator_t *this, sp_inode_ctx_t *ctx) +{ +        call_stub_t *stub = NULL, *tmp = NULL; + +        if (ctx == NULL) { +                goto out; +        } + +        LOCK (&ctx->lock); +        { +                if (!list_empty (&ctx->waiting_ops)) { +                        gf_log (this->name, GF_LOG_CRITICAL, "inode ctx is " +                                "being freed even when there are file " +                                "operations waiting for lookup-behind to " +                                "complete. The operations in the waiting list " +                                "are:"); +                        list_for_each_entry_safe (stub, tmp, &ctx->waiting_ops, +                                                  list) { +                                gf_log (this->name, GF_LOG_CRITICAL, +                                        "OP (%d)", stub->fop); + +                                list_del_init (&stub->list); +                                call_stub_destroy (stub);                          } -                         -                        memcpy (stbuf, buf, sizeof (*stbuf));                  } -        unlock: -                UNLOCK (&inode->lock);          } +        UNLOCK (&ctx->lock); + +        LOCK_DESTROY (&ctx->lock); +        FREE (ctx);  out: -	SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict); -        return 0; +        return; +} + + +sp_inode_ctx_t * +sp_inode_ctx_init () +{ +        sp_inode_ctx_t *inode_ctx = NULL; + +        inode_ctx = CALLOC (1, sizeof (*inode_ctx)); +        if (inode_ctx == NULL) { +                goto out; +        } + +        LOCK_INIT (&inode_ctx->lock); +        INIT_LIST_HEAD (&inode_ctx->waiting_ops); + +out: +        return inode_ctx;  } @@ -520,19 +587,48 @@ sp_is_empty (dict_t *this, char *key, data_t *value, void *data)          }  } - +/*  + * TODO: implement sending lookups for every fop done on this path. As of now + * lookup on the path is sent only for the first fop on this path. + */  int32_t  sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)  { -        gf_dirent_t   dirent; -        char          entry_cached    = 0;  -        uint64_t      value           = 0; -        char          xattr_req_empty = 1; -        sp_cache_t   *cache           = NULL; -        struct stat  *postparent      = NULL, *buf = NULL; -        int32_t       ret             = -1, op_ret = -1, op_errno = EINVAL;  +        gf_dirent_t     dirent; +        char            entry_cached    = 0;  +        uint64_t        value           = 0; +        char            xattr_req_empty = 1; +        sp_cache_t     *cache           = NULL; +        struct stat     postparent      = {0, }, buf = {0, }; +        int32_t         ret             = -1, op_ret = -1, op_errno = EINVAL;  +        sp_inode_ctx_t *inode_ctx       = NULL; +        sp_local_t     *local           = NULL; + +        if (loc == NULL || loc->inode == NULL) { +                goto unwind; +        } + +        LOCK (&loc->inode->lock); +        { +                ret = __inode_ctx_get (loc->inode, this, &value); +                if (ret == 0) { +                        inode_ctx = (sp_inode_ctx_t *)(long)value; +                } else { +                        inode_ctx = sp_inode_ctx_init (); +                        if (inode_ctx != NULL) { +                                ret = __inode_ctx_put (loc->inode, this, +                                                       (long)inode_ctx); +                                if (ret == -1) { +                                        sp_inode_ctx_free (this, inode_ctx); +                                        inode_ctx = NULL; +                                } +                        } +                } +        } +        UNLOCK (&loc->inode->lock); -        if (loc == NULL) { +        if (inode_ctx == NULL) { +                op_errno = ENOMEM;                  goto unwind;          } @@ -554,9 +650,10 @@ sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)                  ret = sp_cache_get_entry (cache, (char *)loc->name, &dirent);                  if (ret == 0) {                          ret = inode_ctx_get (loc->parent, this, &value); -                        if (ret == 0) { -                                postparent = (void *)(long)value; -                                buf = &dirent.d_stat; +                        if ((ret == 0) && (value != 0)) { +                                inode_ctx = (void *)(long)value; +                                postparent = inode_ctx->stbuf; +                                buf = dirent.d_stat;                                  op_ret = 0;                                  op_errno = 0;                                  entry_cached = 1; @@ -567,10 +664,15 @@ sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req)                  if (cache) {                          ret = sp_cache_get_entry (cache, ".", &dirent);                          if (ret == 0) { -                                buf = &dirent.d_stat; -                                op_ret = 0; -                                op_errno = 0; -                                entry_cached = 1; +                                ret = inode_ctx_get (loc->parent, this, &value); +                                if ((ret == 0) && (value != 0)) { +                                        inode_ctx = (void *)(long)value; +                                        postparent = inode_ctx->stbuf; +                                        buf = dirent.d_stat; +                                        op_ret = 0; +                                        op_errno = 0; +                                        entry_cached = 1; +                                }                          }                  }          } @@ -585,6 +687,33 @@ wind:                          cache->miss++;                  } +                LOCK (&inode_ctx->lock); +                { +                        if (!(inode_ctx->looked_up +                              || inode_ctx->lookup_in_progress)) { +                                inode_ctx->lookup_in_progress = 1; +                        } +                } +                UNLOCK (&inode_ctx->lock); + +                op_errno = ENOMEM;   +                local = CALLOC (1, sizeof (*local)); +                GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, +                                                ENOMEM); +                op_errno = 0; +                 +                frame->local = local; + +                ret = loc_copy (&local->loc, loc); +                if (ret == -1) { +                        op_errno = errno; +                        gf_log (this->name, GF_LOG_ERROR, "%s", +                                strerror (op_errno)); +                        goto unwind; +                } + +                local->is_lookup = 1; +                  STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this),                              FIRST_CHILD(this)->fops->lookup, loc, xattr_req); @@ -592,7 +721,7 @@ wind:          }  unwind: -	SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, buf, postparent, +	SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, &buf, &postparent,                           NULL);          return 0; diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h index dd6b067c5bd..81f504a7f31 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.h +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h @@ -25,11 +25,15 @@  #include "config.h"  #endif +#include "locking.h" +#include "inode.h"  #include "glusterfs.h"  #include "dict.h"  #include "xlator.h"  #include "rbthash.h"  #include "hashfn.h" +#include "call-stub.h" +#include <libgen.h>  struct sp_cache {          rbthash_table_t *table; @@ -58,9 +62,20 @@ typedef struct sp_fd_ctx sp_fd_ctx_t;  struct sp_local {          loc_t  loc;          fd_t  *fd; +        char   is_lookup;  };  typedef struct sp_local sp_local_t; +struct sp_inode_ctx { +        char             looked_up; +        char             lookup_in_progress; +        int32_t          op_ret; +        int32_t          op_errno; +        struct stat      stbuf;   +        gf_lock_t        lock; +        struct list_head waiting_ops; +}; +typedef struct sp_inode_ctx sp_inode_ctx_t;  void sp_local_free (sp_local_t *local);  | 
