diff options
Diffstat (limited to 'xlators/performance/stat-prefetch/src/stat-prefetch.c')
-rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index 6a10ac4c42c..5823634fa73 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -18,6 +18,287 @@ */ #include "stat-prefetch.h" +#include "locking.h" + + +void +sp_local_free (sp_local_t *local) +{ + loc_wipe (&local->loc); + FREE (local); +} + + +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; + char found = 0; + + 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); + found = 1; + ret = 0; + + if (!remove_all) { + break; + } + } + } + } + UNLOCK (&cache->lock); + + if (found) { + FREE (entry); + } +out: + return ret; +} + + +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; +} + + +void +sp_cache_free (sp_cache_t *cache) +{ + sp_cache_remove_entry (cache, NULL, 1); + FREE (cache); +} + + +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; + + if (fd == NULL) { + goto out; + } + + ret = fd_ctx_get (fd, this, &value); + if (ret == -1) { + goto out; + } + + cache = (void *)(long) value; +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; +} + + +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_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) || (loc->parent == NULL) || (loc->name == NULL)) { + goto unwind; + } + + if (xattr_req) { + 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_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 init (xlator_t *this) @@ -44,10 +325,12 @@ fini (xlator_t *this) struct xlator_fops fops = { + .lookup = sp_lookup, }; struct xlator_mops mops = { }; struct xlator_cbks cbks = { + .forget = sp_forget, }; |