diff options
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 9 | ||||
| -rw-r--r-- | xlators/performance/Makefile.am | 2 | ||||
| -rw-r--r-- | xlators/performance/stat-prefetch/src/Makefile.am | 11 | ||||
| -rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 2078 | ||||
| -rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.h | 57 | 
6 files changed, 1774 insertions, 385 deletions
diff --git a/configure.ac b/configure.ac index bbadeb9ebe7..e6e620e0531 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,8 @@ AC_CONFIG_FILES([Makefile  		xlators/performance/io-cache/src/Makefile  		xlators/performance/symlink-cache/Makefile  		xlators/performance/symlink-cache/src/Makefile +                xlators/performance/stat-prefetch/Makefile +                xlators/performance/stat-prefetch/src/Makefile  		xlators/debug/Makefile  		xlators/debug/trace/Makefile  		xlators/debug/trace/src/Makefile diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index c90342f7a3d..248efc83c0c 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -116,6 +116,15 @@ extern char *gf_cbk_list[GF_CBK_MAXVALUE];  		}						\  	} while (0);  +#define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, error) do { \ +                if (!arg) {                                          \ +                        errno = error;                               \ +                        gf_log (name, GF_LOG_ERROR,                  \ +                                "invalid argument: " #arg);          \ +                        goto label;                                  \ +                }                                                    \ +        }while (0); +  #define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name,arg,label)       \          do {                                                    \                  GF_VALIDATE_OR_GOTO (name, arg, label);         \ diff --git a/xlators/performance/Makefile.am b/xlators/performance/Makefile.am index f7504bbe8f3..5caa59f327f 100644 --- a/xlators/performance/Makefile.am +++ b/xlators/performance/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = write-behind read-ahead io-threads io-cache symlink-cache +SUBDIRS = write-behind read-ahead io-threads io-cache symlink-cache stat-prefetch  CLEANFILES =  diff --git a/xlators/performance/stat-prefetch/src/Makefile.am b/xlators/performance/stat-prefetch/src/Makefile.am index e52f2df48fd..b16c133a1ab 100644 --- a/xlators/performance/stat-prefetch/src/Makefile.am +++ b/xlators/performance/stat-prefetch/src/Makefile.am @@ -1,11 +1,14 @@ -xlator_PROGRAMS = stat-prefetch.so +xlator_LTLIBRARIES = stat-prefetch.la  xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/performance -stat_prefetch_so_SOURCES = stat-prefetch.c +stat_prefetch_la_LDFLAGS = -module -avoidversion +stat_prefetch_la_SOURCES = stat-prefetch.c  noinst_HEADERS = stat-prefetch.h -AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall \ -	-I$(top_srcdir)/libglusterfs/src -shared -nostartfiles +stat_prefetch_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\ +	-I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)  CLEANFILES =  diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index c6bf1e684cf..57bed9a52a7 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -1,508 +1,1838 @@  /* -   Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> -   This file is part of GlusterFS. - -   GlusterFS is free software; you can redistribute it and/or modify -   it under the terms of the GNU General Public License as published -   by the Free Software Foundation; either version 3 of the License, -   or (at your option) any later version. - -   GlusterFS is distributed in the hope that it will be useful, but -   WITHOUT ANY WARRANTY; without even the implied warranty of -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -   General Public License for more details. - -   You should have received a copy of the GNU General Public License -   along with this program.  If not, see -   <http://www.gnu.org/licenses/>. +  Copyright (c) 2009-2010 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>.  */ -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "glusterfs.h"  #include "stat-prefetch.h" -#include "dict.h" -#include "xlator.h" -#include <sys/time.h> - -struct sp_cache { -  struct sp_cache *next; -  struct sp_cache *prev; -  pid_t pid; -  long long tv_time; -  char *dirname; -  dir_entry_t entries; -  int32_t count; -  pthread_mutex_t lock; -}; +#include "locking.h" +#include "inode.h" +#include <libgen.h> + -static void -stat_prefetch_cache_flush (struct sp_cache *cache, int32_t force) +sp_cache_t * +sp_cache_init (void)  { -  struct sp_cache *trav; -  struct timeval tv; -  long long tv_time; +        sp_cache_t *cache = NULL; -  gettimeofday (&tv, NULL); -  tv_time = (tv.tv_usec + (tv.tv_sec * 1000000)); +        cache = CALLOC (1, sizeof (*cache)); +        if (cache) { +                INIT_LIST_HEAD (&cache->entries.list); +                LOCK_INIT (&cache->lock); +        } -  pthread_mutex_lock (&cache->lock); +        return cache; +} -  trav = cache->next; -  while (trav != cache) { -    struct sp_cache *next = trav->next; -    { -      if (tv_time > trav->tv_time || force) { -	gf_log ("stat-prefetch", -		GF_LOG_DEBUG, -		"flush on: %s", -		trav->dirname); -	dir_entry_t *entries; +         +void +sp_local_free (sp_local_t *local) +{ +        if (local) { +                loc_wipe (&local->loc); +                FREE (local); +        } +} -	trav->prev->next = trav->next; -	trav->next->prev = trav->prev; -	entries = trav->entries.next; +int32_t +sp_cache_remove_entry (sp_cache_t *cache, char *name, char remove_all) +{ +        int32_t      ret   = -1; +        gf_dirent_t *entry = NULL, *tmp = NULL; + +        if ((cache == NULL) || ((name == NULL) && !remove_all)) { +                goto out; +        } + +        LOCK (&cache->lock); +        { +                list_for_each_entry_safe (entry, tmp, &cache->entries.list, +                                          list) { +                        if (remove_all || (!strcmp (name, entry->d_name))) { +                                list_del_init (&entry->list); +                                FREE (entry); +                                ret = 0; + +                                if (!remove_all) { +                                        break; +                                } +                        } +                } +        } +        UNLOCK (&cache->lock); + +out: +        return ret;     +} + -	while (entries) { -	  dir_entry_t *nextentry = entries->next; -	  { -	    free (entries->name); -	    free (entries); -	  } -	  entries = nextentry; -	} -	free (trav->dirname); -	free (trav); -      } -    } -    trav = next; -  } +int32_t +sp_cache_get_entry (sp_cache_t *cache, char *name, gf_dirent_t *entry) +{ +        int32_t      ret = -1; +        gf_dirent_t *tmp = NULL; + +        if ((cache == NULL) || (name == NULL) || (entry == NULL)) { +                goto out; +        } + +        LOCK (&cache->lock); +        { +                list_for_each_entry (tmp, &cache->entries.list, list) { +                        if (!strcmp (name, tmp->d_name)) { +                                memcpy (entry, tmp, sizeof (*entry)); +                                ret = 0; +                                break; +                        } +                } + +        } +        UNLOCK (&cache->lock); + +out: +        return ret; +} +  -  pthread_mutex_unlock (&cache->lock); +void +sp_cache_free (sp_cache_t *cache) +{ +        sp_cache_remove_entry (cache, NULL, 1); +        FREE (cache);  } -static int32_t -stat_prefetch_cache_fill (struct sp_cache *cache, -			  pid_t pid, -			  char *dirname, -			  dir_entry_t *entries) -{ -  struct sp_cache *trav; -  struct timeval tv; - -  pthread_mutex_unlock (&cache->lock); -  trav = cache->next; -  while (trav != cache) { -    //    if (trav->pid == pid && !strcmp (trav->dirname, dirname)) { -    if (!strcmp (trav->dirname, dirname)) { -      break; -    } -    trav = trav->next; -  } - -  if (trav == cache) { -    trav = CALLOC (1, sizeof (*trav)); -    ERR_ABORT (trav); -    trav->pid = pid; -    trav->dirname = dirname; - -    trav->prev = cache->prev; -    trav->next = cache; -    trav->next->prev = trav; -    trav->prev->next = trav; -  } else { -    free (dirname); -  } - -  while (trav->entries.next) { -    dir_entry_t *tmp = trav->entries.next; - -    trav->entries.next = trav->entries.next->next; -    free (tmp->name); -    free (tmp); -  } -  trav->entries.next = entries->next; -  entries->next = NULL; - -  gettimeofday (&tv, NULL); -  trav->tv_time = (tv.tv_usec + (tv.tv_sec * 1000000)) + cache->tv_time; - -  pthread_mutex_unlock (&cache->lock); -  return 0; + +sp_cache_t * +sp_get_cache_fd (xlator_t *this, fd_t *fd) +{ +        sp_cache_t  *cache     = NULL; +        uint64_t     value     = 0; +        int32_t      ret       = -1; +        sp_fd_ctx_t *fd_ctx = NULL; + +        if (fd == NULL) { +                goto out; +        } + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                goto out; +        } + +        fd_ctx = (void *)(long) value; + +        LOCK (&fd_ctx->lock); +        { +                cache = fd_ctx->cache; +        } +        UNLOCK (&fd_ctx->lock); +out: +        return cache; +} + + +void +sp_fd_ctx_free (sp_fd_ctx_t *fd_ctx) +{ +        if (fd_ctx == NULL) { +                goto out; +        } + +        if (fd_ctx->parent_inode) { +                inode_unref (fd_ctx->parent_inode); +                fd_ctx->parent_inode = NULL; +        } +                 +        if (fd_ctx->name) { +                FREE (fd_ctx->name); +                fd_ctx->name = NULL; +        } + +        if (fd_ctx->cache) { +                sp_cache_free (fd_ctx->cache); +        } + +        FREE (fd_ctx); +out: +        return; +} +  + +inline sp_fd_ctx_t * +sp_fd_ctx_init (void) +{ +        sp_fd_ctx_t *fd_ctx = NULL; + +        fd_ctx = CALLOC (1, sizeof (*fd_ctx)); +        if (fd_ctx) { +                LOCK_INIT (&fd_ctx->lock); +        } + +        return fd_ctx;  } + +sp_fd_ctx_t * +sp_fd_ctx_new (xlator_t *this, inode_t *parent, char *name, sp_cache_t *cache) +{ +        sp_fd_ctx_t *fd_ctx = NULL; + +        fd_ctx = sp_fd_ctx_init (); +        if (fd_ctx == NULL) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto out; +        } + +        if (parent) { +                fd_ctx->parent_inode = inode_ref (parent); +        } + +        if (name) { +                fd_ctx->name = strdup (name); +                if (fd_ctx->name == NULL) { +                        sp_fd_ctx_free (fd_ctx); +                        fd_ctx = NULL; +                } +        } + +        fd_ctx->cache = cache; + +out: +        return fd_ctx; +} + + +sp_cache_t * +sp_del_cache_fd (xlator_t *this, fd_t *fd) +{ +        sp_cache_t  *cache = NULL; +        uint64_t     value = 0; +        int32_t      ret   = -1; +        sp_fd_ctx_t *fd_ctx = NULL; + +        if (fd == NULL) { +                goto out; +        } + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                goto out; +        } + +        fd_ctx = (void *)(long) value; + +        LOCK (&fd_ctx->lock); +        { +                cache = fd_ctx->cache; +                fd_ctx->cache = NULL; +        } +        UNLOCK (&fd_ctx->lock); + +out: +        return cache; +} + + +sp_cache_t * +sp_get_cache_inode (xlator_t *this, inode_t *inode, int32_t pid) +{ +        fd_t       *fd    = NULL; +        sp_cache_t *cache = NULL; + +        if (inode == NULL) { +                goto out; +        } + +        fd = fd_lookup (inode, pid); +        if (fd == NULL) { +                goto out; +        } + +        cache = sp_get_cache_fd (this, fd); +out: +        return cache; +} + + +inline int32_t +sp_put_cache (xlator_t *this, fd_t *fd, sp_cache_t *cache) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        int32_t      ret    = -1;  +        uint64_t     value  = 0; + +        ret = fd_ctx_get (fd, this, &value); +        if (!ret) { +                fd_ctx = (void *)(long)value; +        } else { +                fd_ctx = sp_fd_ctx_init (); +                if (fd_ctx == NULL) { +                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                        ret = -1; +                        goto out; +                } + +                ret = fd_ctx_set (fd, this, (long)(void *)fd_ctx); +                if (ret == -1) { +                        sp_fd_ctx_free (fd_ctx);  +                        goto out; +                } +        } + +        LOCK (&fd_ctx->lock); +        {  +                if (fd_ctx->cache) { +                        sp_cache_free (fd_ctx->cache); +                } + +                fd_ctx->cache = cache; +        } +        UNLOCK (&fd_ctx->lock); + +out: +        return ret; +} + + +int32_t +sp_cache_add_entries (sp_cache_t *cache, gf_dirent_t *entries) +{ +        gf_dirent_t  copy; +        gf_dirent_t *entry           = NULL, *new = NULL; +        int32_t      ret             = -1; +        uint64_t     expected_offset = 0; +         +        memset (©, 0, sizeof (copy)); +        INIT_LIST_HEAD (©.list); + +        LOCK (&cache->lock); +        { +                list_for_each_entry (entry, &entries->list, list) { +                        new = gf_dirent_for_name (entry->d_name); +                        if (new == NULL) { +                                gf_dirent_free (©); +                                goto unlock; +                        } + +                        new->d_ino  = entry->d_ino; +                        new->d_off  = entry->d_off; +                        new->d_len  = entry->d_len; +                        new->d_type = entry->d_type; +                        new->d_stat = entry->d_stat; + +                        list_add_tail (&new->list, ©.list); + +                        expected_offset = new->d_off; +                } + +                /*  +                 * splice entries in cache to copy, so that we have a list in +                 * ascending order of offsets +                 */ +                list_splice_init (&cache->entries.list, ©.list); + +                /* splice back the copy into cache */ +                list_splice_init (©.list, &cache->entries.list); + +                cache->expected_offset = expected_offset; + +                ret = 0; +        } +unlock: +        UNLOCK (&cache->lock); + +        return ret; +} + + +int32_t +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 *stbuf = NULL; +        int32_t      ret = -1; + +        if (op_ret == -1) { +                goto out; +        } + +        if (S_ISDIR (buf->st_mode)) { +                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 out; +                } + +                memcpy (stbuf, buf, sizeof (*stbuf)); +                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 out; +                } +        } + +out: +	SP_STACK_UNWIND (frame, op_ret, op_errno, inode, buf, dict); +        return 0; +} + + +int32_t +sp_lookup_behind_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) +{ +        sp_local_t *local = NULL; +        sp_cache_t *cache = NULL; + +        local = frame->local; +        if (local == NULL) { +                goto out; +        } + +        if ((op_ret == -1) && (op_errno = ENOENT)) { +                cache = sp_get_cache_inode (this, local->loc.parent, +                                            frame->root->pid); + +                if (cache) { +                        sp_cache_remove_entry (cache, (char *)local->loc.name, +                                               0); +                } +        }  + +out: +        SP_STACK_DESTROY (frame); +        return 0; +} + + +int32_t +sp_get_ancestors (char *path, char **parent, char **grand_parent) +{ +        int32_t  ret = -1, i = 0; +        char    *cpy = NULL; + +        if (!path || !parent || !grand_parent) { +                ret = 0; +                goto out; +        } + +        for (i = 0; i < 2; i++) { +                if (!strcmp (path, "/")) { +                        break; +                } + +                cpy = strdup (path); +                if (cpy == NULL) { +                        goto out; +                } + +                path = dirname (cpy); +                switch (i) +                { +                case 0: +                        *parent = path; +                        break; +                case 1: +                        *grand_parent = path; +                        break; +                } +        } + +        ret = 0; +out: +        return ret;  +} + + +int32_t +sp_cache_remove_parent_entry (call_frame_t *frame, xlator_t *this, char *path) +{ +        char       *parent    = NULL, *grand_parent = NULL, *cpy = NULL; +        inode_t    *inode_gp  = NULL; +        sp_cache_t *cache_gp  = NULL; +        int32_t     ret       = -1; + +        ret = sp_get_ancestors (path, &parent, &grand_parent); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto out; +        } + +        if (grand_parent && strcmp (grand_parent, "/")) { +                inode_gp = inode_from_path (frame->root->frames.this->itable, +                                            grand_parent); +                if (inode_gp) { +                        cache_gp = sp_get_cache_inode (this, inode_gp, +                                                       frame->root->pid); +                        if (cache_gp) { +                                cpy = strdup (parent); +                                GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, +                                                                cpy, out, +                                                                ENOMEM); +                                path = basename (cpy); +                                sp_cache_remove_entry (cache_gp, path, 0); +                                FREE (cpy); +                        } +                        inode_unref (inode_gp); +                } +        } + +        ret = 0; +out: +        if (parent) { +                FREE (parent); +        } + +        if (grand_parent) { +                FREE (grand_parent); +        } + +        return ret; +} + + +int32_t +sp_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) +{ +        sp_local_t   *local      = NULL; +        gf_dirent_t   dirent;      +        int32_t       ret        = -1, op_ret = -1, op_errno = EINVAL;  +        sp_cache_t   *cache      = NULL; +        struct stat  *postparent = NULL, *buf = NULL; +        uint64_t      value      = 0;  +        call_frame_t *wind_frame = NULL; +        char          lookup_behind = 0; + +        if (loc == NULL) { +                goto unwind; +        } + +        if (xattr_req || (loc->parent == NULL) || (loc->name == NULL)) { +                goto wind; +        } + +        memset (&dirent, 0, sizeof (dirent)); +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                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; +                                op_ret = 0; +                                op_errno = 0; +                                lookup_behind = 1; +                        }  +                }  +        }  + +wind:         +        if (lookup_behind) { +                wind_frame = copy_frame (frame); +                if (wind_frame == NULL) { +                        op_ret = -1; +                        op_errno = ENOMEM; +                        gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                        goto unwind; +                }  + +                local = CALLOC (1, sizeof (*local)); +                if (local == NULL) { +                        op_ret = -1; +                        op_errno = ENOMEM; +                        STACK_DESTROY (wind_frame->root); +                        goto unwind; +                } +                 +                loc_copy (&local->loc, loc); +                wind_frame->local = local; +                STACK_WIND (wind_frame, sp_lookup_behind_cbk, FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->lookup, loc, xattr_req); +        } else { +                STACK_WIND (frame, sp_lookup_cbk, FIRST_CHILD(this), +                            FIRST_CHILD(this)->fops->lookup, loc, xattr_req); +      +                return 0; +        } + +unwind: +	SP_STACK_UNWIND (frame, op_ret, op_errno, loc->inode, buf, postparent, +                         NULL); +        return 0; + +} + + +int32_t +sp_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, gf_dirent_t *entries) +{ +        sp_local_t *local = NULL; +        sp_cache_t *cache = NULL;   +        fd_t       *fd    = NULL; +        int32_t     ret   = 0; + +        local = frame->local; +        if (local == NULL) { +                goto out; +        } + +        fd = local->fd; + +        cache = sp_get_cache_fd (this, fd); +        if (cache == NULL) { +                cache = sp_cache_init (); +                if (cache == NULL) { +                        goto out; +                } + +                ret = sp_put_cache (this, fd, cache); +                if (ret == -1) { +                        sp_cache_free (cache); +                        goto out; +                } +        } + +        sp_cache_add_entries (cache, entries); + +out: +	SP_STACK_UNWIND (frame, op_ret, op_errno, entries); +	return 0; +} + + +int32_t +sp_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, +            off_t off) +{ +        sp_cache_t *cache    = NULL; +        sp_local_t *local    = NULL; +        char       *path     = NULL; +        int32_t     ret      = -1; + +        cache = sp_get_cache_fd (this, fd); +        if (cache) { +                if (off != cache->expected_offset) { +                        cache = sp_del_cache_fd (this, fd); +                        if (cache) { +                                sp_cache_free (cache); +                        } +                } +        } + +        ret = inode_path (fd->inode, NULL, &path); +        if (ret == -1) { +                goto unwind; +        } +   +        ret = sp_cache_remove_parent_entry (frame, this, path); +        if (ret < 0) { +                errno = -ret; +                goto unwind; +        } + +        local = CALLOC (1, sizeof (*local)); +        if (local) { +                local->fd = fd; +                frame->local = local; +        } + +	STACK_WIND (frame, sp_readdir_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->readdir, fd, size, off); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} + + +int32_t +sp_stbuf_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, +              int32_t op_errno, struct stat *buf) +{ +	SP_STACK_UNWIND (frame, op_ret, op_errno, buf); +	return 0; +} + + +int32_t +sp_chmod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode) +{ +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->chmod, loc, mode); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} + + +int32_t +sp_fd_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, +           int32_t op_errno, fd_t *fd) +{ +        sp_local_t  *local = NULL; +        sp_fd_ctx_t *fd_ctx = NULL; + +        if (op_ret == -1) { +                goto out; +        } + +        local = frame->local; +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, EINVAL); + +        fd_ctx = sp_fd_ctx_new (this, local->loc.parent, +                                (char *)local->loc.name, NULL); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, fd_ctx, out, ENOMEM); + +        op_ret = fd_ctx_set (fd, this, (long)(void *)fd_ctx); +        if (op_ret == -1) { +                sp_fd_ctx_free (fd_ctx); +                op_errno = ENOMEM; +        } + +out: +        SP_STACK_UNWIND (frame, op_ret, op_errno, fd); +        return 0; +} + + +int32_t +sp_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, +         fd_t *fd) +{ +        sp_local_t *local = NULL; +        int32_t     ret   = -1; + +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, ENOMEM); + +        frame->local = local; + +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                goto unwind; +        } + +	STACK_WIND (frame, sp_fd_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->open, loc, flags, fd); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, fd); +        return 0; +} + +  static int32_t -stat_prefetch_cache_lookup (struct sp_cache *cache, -			    pid_t pid, -			    const char *path, -			    struct stat *buf) -{ -  struct sp_cache *trav; -  char *dirname = strdup (path); -  char *filename = strrchr (dirname, '/'); -  dir_entry_t *entries; -  dir_entry_t *prev = NULL; +sp_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +               int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, +               struct stat *buf) +{ +        sp_local_t  *local = NULL; +        sp_fd_ctx_t *fd_ctx = NULL; -  *filename = '\0'; -  filename ++; +        if (op_ret == -1) { +                goto out; +        } -  pthread_mutex_lock (&cache->lock); -  trav = cache->next; -  while (trav != cache) { -    //    if ((trav->pid == pid) && !strcmp (dirname, trav->dirname)) -    if (!strcmp (dirname, trav->dirname)) -      break; -    trav = trav->next; -  } -  if (trav == cache) { -    free (dirname); -    pthread_mutex_unlock (&cache->lock); -    return -1; -  } - -  entries = trav->entries.next; -  prev = &trav->entries; -  while (entries) { -    if (!strcmp (entries->name, filename)) -      break; -    prev = entries; -    entries = entries->next; -  } -  if (!entries) { -    free (dirname); -    pthread_mutex_unlock (&cache->lock); -    return -1; -  } +        local = frame->local; +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, out, EINVAL); -  *buf = entries->buf; -  prev->next = entries->next; -  free (entries->name); -  free (entries); -  free (dirname); +        fd_ctx = sp_fd_ctx_new (this, local->loc.parent, +                                (char *)local->loc.name, NULL); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, fd_ctx, out, ENOMEM); -  pthread_mutex_unlock (&cache->lock); +        op_ret = fd_ctx_set (fd, this, (long)(void *)fd_ctx); +        if (op_ret == -1) { +                sp_fd_ctx_free (fd_ctx); +                op_errno = ENOMEM; +        } -  return 0; +out: +        SP_STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf); +        return 0;  } -			     +  int32_t -stat_prefetch_readdir_cbk (call_frame_t *frame, -			   void *cookie, -			   xlator_t *this, -			   int32_t op_ret, -			   int32_t op_errno, -			   dir_entry_t *entries, -			   int32_t count) +sp_create (call_frame_t *frame,	xlator_t *this,	loc_t *loc, int32_t flags, +           mode_t mode, fd_t *fd)  { -  char *path = frame->local; -  pid_t pid = frame->root->pid; -  frame->local = NULL; +        sp_local_t *local     = NULL; +        int32_t     ret       = -1; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind); + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, ENOMEM); -  STACK_UNWIND (frame, op_ret, op_errno, entries, count); +        frame->local = local; -  if (op_ret == 0) -    stat_prefetch_cache_fill (this->private, -			      pid, -			      path, -			      entries); -  else -    free (path); +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                goto unwind; +        } -  return 0; +	STACK_WIND (frame, sp_create_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->create, loc, flags, mode, fd); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, fd); +        return 0;  } +  int32_t -stat_prefetch_readdir (call_frame_t *frame, -		       xlator_t *this, -		       const char *path) +sp_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd)  { -  stat_prefetch_cache_flush (this->private, 0); +        sp_local_t *local = NULL; +        int32_t     ret   = -1; + +        local = CALLOC (1, sizeof (*local)); +        GF_VALIDATE_OR_GOTO_WITH_ERROR (this->name, local, unwind, ENOMEM); -  frame->local = strdup (path); -  STACK_WIND (frame, -	      stat_prefetch_readdir_cbk, -	      FIRST_CHILD(this), -	      FIRST_CHILD(this)->fops->readdir, -	      path); -  return 0; +        frame->local = local; + +        ret = loc_copy (&local->loc, loc); +        if (ret == -1) { +                goto unwind; +        } + +	STACK_WIND (frame, sp_fd_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->opendir, loc, fd); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, fd); +        return 0;  }  int32_t -stat_prefetch_getattr_cbk (call_frame_t *frame, -			   void *cookie, -			   xlator_t *this, -			   int32_t op_ret, -			   int32_t op_errno, -			   struct stat *buf) +sp_new_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, inode_t *inode, +                  struct stat *buf)  { -  STACK_UNWIND (frame, op_ret, op_errno, buf); -  return 0; +	STACK_UNWIND (frame, op_ret, op_errno, inode, buf); +	return 0;  } +  int32_t -stat_prefetch_getattr (call_frame_t *frame, -		       struct xlator *this, -		       const char *path) +sp_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode)  { -  struct stat buf; -  pid_t pid = frame->root->pid; -  stat_prefetch_cache_flush (this->private, 0); +        int32_t     ret = 0; -  if (stat_prefetch_cache_lookup (this->private, -				  pid, -				  path, -				  &buf) == 0) { -    STACK_UNWIND (frame, 0, 0, &buf); -    return 0; -  } +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind); -  STACK_WIND (frame, -	      stat_prefetch_getattr_cbk, -	      FIRST_CHILD(this), -	      FIRST_CHILD(this)->fops->getattr, -	      path); +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } -  return 0; +	STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->mkdir, loc, mode); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, loc->inode, NULL); +        return 0;  }  int32_t -stat_prefetch_unlink_cbk (call_frame_t *frame, -                          void *cookie, -                          xlator_t *this, -                          int32_t op_ret, -                          int32_t op_errno) +sp_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, +          dev_t rdev)  { -  STACK_UNWIND (frame, op_ret, op_errno); -  return 0; +        int32_t     ret = 0; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind); + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +	STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->mknod, loc, mode, rdev); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, loc->inode, NULL); +        return 0; +} + + +int32_t +sp_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, +            loc_t *loc) +{ +        int32_t     ret = 0; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind); + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +	STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->symlink, linkpath, loc); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, loc->inode, NULL); +        return 0;  } +  int32_t -stat_prefetch_unlink (call_frame_t *frame, -                      struct xlator *this, -                      const char *path) +sp_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc)  { -  stat_prefetch_cache_flush (this->private, 1); +        int32_t     ret = 0; -  STACK_WIND (frame, -              stat_prefetch_unlink_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->unlink, -              path); +        GF_VALIDATE_OR_GOTO (this->name, newloc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, newloc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, newloc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, newloc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, newloc->inode, unwind); -  return 0; +        ret = sp_cache_remove_parent_entry (frame, this, (char *)newloc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +	STACK_WIND (frame, sp_new_entry_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->link, oldloc, newloc); + +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, oldloc->inode, NULL); +        return 0;  }  int32_t -stat_prefetch_chmod_cbk (call_frame_t *frame, -			 void *cookie, -			 xlator_t *this, -			 int32_t op_ret, -			 int32_t op_errno, -			 struct stat *buf) +sp_fchmod (call_frame_t *frame, xlator_t *this,	fd_t *fd, mode_t mode)  { -  STACK_UNWIND (frame, op_ret, op_errno, buf); -  return 0; +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fchmod, fd, mode); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  } +  int32_t -stat_prefetch_chmod (call_frame_t *frame, -		     struct xlator *this, -		     const char *path, -		     mode_t mode) +sp_chown (call_frame_t *frame, xlator_t *this, loc_t *loc, uid_t uid, gid_t gid)  { -  stat_prefetch_cache_flush (this->private, 1); +        sp_cache_t *cache = NULL; -  STACK_WIND (frame, -              stat_prefetch_chmod_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->chmod, -              path, -	      mode); +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); -  return 0; +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->chown, loc, uid, gid); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  }  int32_t -stat_prefetch_chown_cbk (call_frame_t *frame, -			 void *cookie, -			 xlator_t *this, -			 int32_t op_ret, -			 int32_t op_errno, -			 struct stat *buf) +sp_fchown (call_frame_t *frame, xlator_t *this,	fd_t *fd, uid_t uid, gid_t gid)  { -  STACK_UNWIND (frame, op_ret, op_errno, buf); -  return 0; +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fchown, fd, uid, gid); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  } +  int32_t -stat_prefetch_chown (call_frame_t *frame, -		     struct xlator *this, -		     const char *path, -		     uid_t uid, -		     gid_t gid) +sp_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset)  { -  stat_prefetch_cache_flush (this->private, 1); +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } -  STACK_WIND (frame, -              stat_prefetch_chown_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->chown, -              path, -	      uid, -	      gid); +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->truncate, loc, offset); +        return 0; -  return 0; +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  }  int32_t -stat_prefetch_utimes_cbk (call_frame_t *frame, -                          void *cookie, -                          xlator_t *this, -                          int32_t op_ret, -                          int32_t op_errno, -			  struct stat *buf) +sp_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset)  { -  STACK_UNWIND (frame, op_ret, op_errno, buf); -  return 0; +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->ftruncate, fd, offset); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  } +  int32_t -stat_prefetch_utimes (call_frame_t *frame, -		      struct xlator *this, -		      const char *path, -		      struct timespec *tvp) +sp_utimens (call_frame_t *frame, xlator_t *this, loc_t *loc, +            struct timespec tv[2])  { -  stat_prefetch_cache_flush (this->private, 1); +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); -  STACK_WIND (frame, -              stat_prefetch_utimes_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->utimes, -              path, -	      tvp); +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } -  return 0; +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->utimens, loc, tv); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  }  int32_t -stat_prefetch_truncate_cbk (call_frame_t *frame, -			    void *cookie, -			    xlator_t *this, -			    int32_t op_ret, -			    int32_t op_errno, -			    struct stat *buf) +sp_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                 int32_t op_ret, int32_t op_errno, const char *path)  { -  STACK_UNWIND (frame, op_ret, op_errno, buf); -  return 0; +	SP_STACK_UNWIND (frame, op_ret, op_errno, path); +        return 0;  } +  int32_t -stat_prefetch_truncate (call_frame_t *frame, -			struct xlator *this, -			const char *path, -			off_t offset) +sp_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size)  { -  stat_prefetch_cache_flush (this->private, 1); +        sp_cache_t *cache = NULL; -  STACK_WIND (frame, -              stat_prefetch_truncate_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->truncate, -              path, -	      offset); +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); -  return 0; +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_readlink_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->readlink, loc, size); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0;  }  int32_t -stat_prefetch_rename_cbk (call_frame_t *frame, -                          void *cookie, -                          xlator_t *this, -                          int32_t op_ret, -                          int32_t op_errno) +sp_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +            int32_t op_ret, int32_t op_errno)  { -  STACK_UNWIND (frame, op_ret, op_errno); -  return 0; +	SP_STACK_UNWIND (frame, op_ret, op_errno); +	return 0;  } +  int32_t -stat_prefetch_rename (call_frame_t *frame, -                      struct xlator *this, -                      const char *oldpath, -		      const char *newpath) +sp_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc)  { -  stat_prefetch_cache_flush (this->private, 1); +        sp_cache_t *cache = NULL; +        int32_t     ret   = 0; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +	STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->unlink, loc); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno); +        return 0; +} -  STACK_WIND (frame, -              stat_prefetch_rename_cbk, -              FIRST_CHILD(this), -              FIRST_CHILD(this)->fops->rename, -              oldpath, -	      newpath); -  return 0; +void +sp_remove_caches_from_all_fds_opened (xlator_t *this, inode_t *inode) +{ +        fd_t       *fd    = NULL; +        sp_cache_t *cache = NULL; + +        LOCK (&inode->lock); +        { +                list_for_each_entry (fd, &inode->fd_list, inode_list) { +                        cache = sp_get_cache_fd (this, fd); +                        if (cache) { +                                sp_cache_remove_entry (cache, NULL, 1); +                        } +                } +        } +        UNLOCK (&inode->lock);  } +  -int32_t  -init (struct xlator *this) +int32_t +sp_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc) +{ +        sp_cache_t *cache = NULL; +        int32_t     ret   = -1; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); + +        sp_remove_caches_from_all_fds_opened (this, loc->inode); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)loc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +        STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->rmdir, loc); +        return 0; + +unwind: +        STACK_UNWIND (frame, -1, errno); +        return 0; +} + + +int32_t +sp_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, +              int32_t op_errno, struct iovec *vector, int32_t count, +              struct stat *stbuf, struct iobref *iobref) +{ +	SP_STACK_UNWIND (frame, op_ret, op_errno, vector, count, stbuf, iobref); +	return 0; +} + + +int32_t +sp_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, +          off_t offset) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_readv_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->readv, fd, size, offset); +        return 0; + +unwind: +	SP_STACK_UNWIND (frame, -1, errno, NULL, -1, NULL, NULL); +        return 0; +} + + +int32_t +sp_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, +           int32_t count, off_t off, struct iobref *iobref) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->writev, fd, vector, count, off, +                    iobref); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} + + +int32_t +sp_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fsync, fd, flags); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno); +        return 0; +} + + +int32_t +sp_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc,loc_t *newloc) +{ +        sp_cache_t *cache = NULL; +        int32_t     ret   = -1; + +        GF_VALIDATE_OR_GOTO (this->name, oldloc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, oldloc->path, unwind); +        GF_VALIDATE_OR_GOTO (this->name, oldloc->name, unwind); +        GF_VALIDATE_OR_GOTO (this->name, oldloc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, oldloc->inode, unwind); + +        GF_VALIDATE_OR_GOTO (this->name, newloc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, newloc->path, unwind); + +        cache = sp_get_cache_inode (this, oldloc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)oldloc->name, 0); +        } + +        cache = sp_get_cache_inode (this, newloc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)newloc->name, 0); +        } + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)oldloc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +        ret = sp_cache_remove_parent_entry (frame, this, (char *)newloc->path); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +        if (S_ISDIR (oldloc->inode->st_mode)) { +                sp_remove_caches_from_all_fds_opened (this, oldloc->inode); +        } + +        STACK_WIND (frame, sp_stbuf_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->rename, oldloc, newloc); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +	return 0; +} + + +int32_t +sp_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, +             int32_t flags) +{ +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setxattr, loc, dict, flags); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno); +        return 0; +} + + +int32_t +sp_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, +                const char *name) +{ +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->removexattr, loc, name); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno); +        return 0; +} + + +int32_t +sp_setdents (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, +             dir_entry_t *entries, int32_t count) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  +        dir_entry_t *trav   = NULL; + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +        cache = sp_get_cache_fd (this, fd); +        if (cache) { +                for (trav = entries->next; trav; trav = trav->next) { +                        sp_cache_remove_entry (cache, trav->name, 0); +                } +        } + +	STACK_WIND (frame, sp_err_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setdents, fd, flags, entries, +                    count); +	return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno); +        return 0; +} + + +int32_t +sp_getdents_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                 int32_t op_ret, int32_t op_errno, dir_entry_t *entries, +                 int32_t count) +{ +        dir_entry_t *trav  = NULL; +        sp_local_t  *local = NULL; +        sp_cache_t  *cache = NULL; +         +        if (op_ret == -1) { +                goto out; +        } + +        local = frame->local; +        if ((local == NULL) || (local->fd == NULL)) { +                op_ret = -1; +                op_errno = EINVAL; +                goto out; +        } + +        cache = sp_get_cache_fd (this, local->fd); +        if (cache) { +                for (trav = entries->next; trav; trav = trav->next) { +                        if (S_ISLNK (trav->buf.st_mode)) { +                                sp_cache_remove_entry (cache, trav->name, 0); +                        } +                } +        } +         +out:  +	SP_STACK_UNWIND (frame, op_ret, op_errno, entries, count); +	return 0; +} + + +int32_t +sp_getdents (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, +             off_t offset, int32_t flags) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  +        sp_local_t  *local  = NULL; + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +        local = CALLOC (1, sizeof (*local)); +        if (local == NULL) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory"); +                goto unwind; +        } + +        local->fd = fd; +        frame->local = local; + +	STACK_WIND (frame, sp_getdents_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->getdents, fd, size, offset, flags); +	return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL, -1); +        return 0; +} + + +int32_t +sp_checksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                 int32_t op_ret, int32_t op_errno, uint8_t *file_checksum, +                 uint8_t *dir_checksum) +{ +	SP_STACK_UNWIND (frame, op_ret, op_errno, file_checksum, dir_checksum); +	return 0; +} + + +int32_t +sp_checksum (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flag) +{ +        sp_cache_t *cache = NULL; + +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); + +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } + +	STACK_WIND (frame, sp_checksum_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->checksum, loc, flag); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} + + +int32_t +sp_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, dict_t *dict) +{ +	SP_STACK_UNWIND (frame, op_ret, op_errno, dict); +	return 0; +} + + +int32_t +sp_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, +            gf_xattrop_flags_t flags, dict_t *dict)  { -  struct sp_cache *cache; -  dict_t *options = this->options; +        sp_cache_t *cache = NULL; -  if (!this->children || this->children->next) { -    gf_log ("stat-prefetch", -	    GF_LOG_ERROR, -	    "FATAL: translator %s does not have exactly one child node", -	    this->name); -    return -1; -  } +        GF_VALIDATE_OR_GOTO (this->name, loc, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->parent, unwind); +        GF_VALIDATE_OR_GOTO (this->name, loc->name, unwind); -  cache = (void *) CALLOC (1, sizeof (*cache)); -  ERR_ABORT (cache); -  cache->next = cache->prev = cache; +        cache = sp_get_cache_inode (this, loc->parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, (char *)loc->name, 0); +        } -  cache->tv_time = 1 * 1000000; +	STACK_WIND (frame, sp_xattrop_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->xattrop, loc, flags, dict); +        return 0; -  if (dict_get (options, "cache-seconds")) { -    cache->tv_time = (data_to_int64 (dict_get (options, "cache-seconds")) * -		      1000000); -  } +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} -  pthread_mutex_init (&cache->lock, NULL); -  this->private = cache; -  return 0; +int32_t +sp_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, +             gf_xattrop_flags_t flags, dict_t *dict) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        sp_cache_t  *cache  = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0;  +        inode_t     *parent = NULL; +        char        *name   = NULL;  + +        ret = fd_ctx_get (fd, this, &value); +        if (ret == -1) { +                errno = EINVAL; +                goto unwind; +        } + +        fd_ctx = (void *)(long)value; +        name   = fd_ctx->name; +        parent = fd_ctx->parent_inode; + +        cache = sp_get_cache_inode (this, parent, frame->root->pid); +        if (cache) { +                sp_cache_remove_entry (cache, name, 0); +        } + +	STACK_WIND (frame, sp_xattrop_cbk, FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict); +        return 0; + +unwind: +        SP_STACK_UNWIND (frame, -1, errno, NULL); +        return 0; +} + + +int32_t +sp_forget (xlator_t *this, inode_t *inode) +{ +        struct stat *buf   = NULL; +        uint64_t     value = 0; + +        inode_ctx_del (inode, this, &value); +         +        if (value) { +                buf = (void *)(long)value; +                FREE (buf); +        } +         +        return 0; +} + + +int32_t +sp_release (xlator_t *this, fd_t *fd) +{ +        sp_fd_ctx_t *fd_ctx = NULL; +        uint64_t     value  = 0; +        int32_t      ret    = 0; + +        ret = fd_ctx_del (fd, this, &value); +        if (!ret) { +                fd_ctx = (void *)(long) value; +                sp_fd_ctx_free (fd_ctx);       +        } + +        return 0; +} + + + +int32_t  +init (xlator_t *this) +{ +        int32_t ret = -1; +        if (!this->children || this->children->next) { +                gf_log ("stat-prefetch", +                        GF_LOG_ERROR, +                        "FATAL: translator %s does not have exactly one child " +                        "node", this->name); +                goto out; +        } + +        ret = 0; +out: +        return ret;  }  void -fini (struct xlator *this) +fini (xlator_t *this)  { -  return; +        return;  }  struct xlator_fops fops = { -  .getattr     = stat_prefetch_getattr, -  .readdir     = stat_prefetch_readdir, -  .unlink      = stat_prefetch_unlink, -  .chmod       = stat_prefetch_chmod, -  .chown       = stat_prefetch_chown, -  .rename      = stat_prefetch_rename, -  .utimes      = stat_prefetch_utimes, -  .truncate    = stat_prefetch_truncate, +        .lookup      = sp_lookup, +        .readdir     = sp_readdir, +        .chmod       = sp_chmod, +        .open        = sp_open,  +        .create      = sp_create, +        .opendir     = sp_opendir, +        .mkdir       = sp_mkdir, +        .mknod       = sp_mknod, +        .symlink     = sp_symlink, +        .link        = sp_link, +        .fchmod      = sp_fchmod, +        .chown       = sp_chown, +        .fchown      = sp_fchown, +        .truncate    = sp_truncate, +        .ftruncate   = sp_ftruncate, +        .utimens     = sp_utimens, +        .readlink    = sp_readlink, +        .unlink      = sp_unlink, +        .rmdir       = sp_rmdir, +        .readv       = sp_readv, +        .writev      = sp_writev,  +        .fsync       = sp_fsync, +        .rename      = sp_rename, +        .setxattr    = sp_setxattr, +        .removexattr = sp_removexattr, +        .setdents    = sp_setdents, +        .getdents    = sp_getdents, +        .checksum    = sp_checksum, +        .xattrop     = sp_xattrop, +        .fxattrop    = sp_fxattrop,  };  struct xlator_mops mops = {  }; + +struct xlator_cbks cbks = { +        .forget     = sp_forget, +        .release    = sp_release, +        .releasedir = sp_release +}; diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.h b/xlators/performance/stat-prefetch/src/stat-prefetch.h index ef82952b0c7..05c5d436184 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.h +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.h @@ -1,5 +1,5 @@  /* -   Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> +   Copyright (c) 2009-2010 Z RESEARCH, Inc. <http://www.zresearch.com>     This file is part of GlusterFS.     GlusterFS is free software; you can redistribute it and/or modify @@ -17,16 +17,61 @@     <http://www.gnu.org/licenses/>.  */ -#ifndef _STAT_PREFETCH_H_ -#define _STAT_PREFETCH_H_ +#ifndef _STAT_PREFETCH_H +#define _STAT_PREFETCH_H  #ifndef _CONFIG_H  #define _CONFIG_H  #include "config.h"  #endif -#include <stdio.h> -#include <sys/time.h> +#include "glusterfs.h" +#include "dict.h"  #include "xlator.h" -#endif /* _STAT_PREFETCH_H_ */ +struct sp_cache { +        gf_dirent_t entries;            /* Head of list of cached dirents */ +        uint64_t    expected_offset;    /* Offset where the next read will +                                         * happen. +                                         */ +        gf_lock_t   lock; +}; +typedef struct sp_cache sp_cache_t; + +struct sp_fd_ctx { +        sp_cache_t *cache; +        inode_t    *parent_inode;       /*  +                                         * inode corresponding to dirname (path) +                                         */ +        char       *name;               /* +                                         * basename of path on which this fd is  +                                         * opened +                                         */ +        gf_lock_t    lock; +}; +typedef struct sp_fd_ctx sp_fd_ctx_t; + +struct sp_local { +        loc_t  loc; +        fd_t  *fd; +}; +typedef struct sp_local sp_local_t; + + +void sp_local_free (sp_local_t *local); + +#define SP_STACK_UNWIND(frame, params ...) do {    \ +        sp_local_t *__local = frame->local;        \ +        frame->local = NULL;                       \ +        STACK_UNWIND (frame, params);              \ +        sp_local_free (__local);                   \ +} while (0) + +#define SP_STACK_DESTROY(frame) do {         \ +        sp_local_t *__local = frame->local;  \ +        frame->local = NULL;                 \ +        STACK_DESTROY (frame->root);         \ +        sp_local_free (__local);             \ +} while (0) + +#endif  /* #ifndef _STAT_PREFETCH_H */  | 
